OCaml Marshal的数据结构非常庞大

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OCaml Marshal的数据结构非常庞大相关的知识,希望对你有一定的参考价值。

我想通过网络发送一个非常大的(~8GB)数据结构,所以我使用Marshal模块将其转换为Bytes。

我的问题是内存加倍,因为我们需要存储两种表示(初始数据和Marshaled数据)。

是否有一种简单的方法可以将Marshal转换成Stream?这将避免具有初始数据结构的完整Marshalled表示。

我想到Marshaling到一个out_channel,我在其中打开了一个带有第二个线程的管道,并从主线程中的管道读取到了Stream,但我想可能有一个更简单的解决方案。

谢谢 !


编辑:回答评论:

在顶层:

let a = Array.make (1024*1024*1024) 0. ;; (* Takes 8GB of RAM *)
let data = Marshal.to_bytes a [Marshal.Closures] ;; (* Takes an extra 8GB *)
答案

这是不可能的。您必须修改Marshal模块以在数据整理时对数据进行流式处理,并在不首先缓冲所有数据的情况下重建数据。

在短期内,实现特定于您的数据的专用编组功能可能更简单。对于8GiB阵列,您可能希望切换到使用BigArray,这样您就可以发送/恢复数据而无需复制它。

注意:如果GC复制它,8GiB阵列将使用16GiB,至少是临时的。

另一答案

据我所知,MPI只允许发送已知大小的数据包,而不是数据流。您可以实现一种自定义流类型,将传入的数据流拆分为常量,小尺寸的数据包(在关闭时,清除缓冲区中剩余的数据)。

此外,您只能将任意长数据编组到通道,否则会占用太多空间。

然后,您需要有一种方法将通道连接到流,AFAIK不容易实现。也许你可以启动antoer ocaml进程:进程将转换字节流(你可以在Stream.of_channel上包装自定义流)并通过MPI发送它。主要流程将数据编组到流程的输入通道。

以上是关于OCaml Marshal的数据结构非常庞大的主要内容,如果未能解决你的问题,请参考以下文章

在啥情况下 Marshal.SizeOf 在堆上分配?

Flask 学习-75.Flask-RESTX 使用 marshal_with 处理嵌套字段

Flask 学习-47.Flask-RESTX 自定义响应内容marshal_with

非常庞大的数据避免分析功能

在处理数据结构中的复杂键(如 int*int*int)时,F# 比 Ocaml 慢得多

OCaml 数组切片?