【问题标题】:OCaml Marshal very large data structureOCaml Marshal 超大数据结构
【发布时间】:2019-03-29 08:37:20
【问题描述】:

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

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

有没有一种简单的方法来编组到流中?这将避免获得初始数据结构的完整编组表示。

我想过编组到一个 out_channel,在其中我打开一个带有第二个线程的管道并从主线程中的管道读取到 s 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 *)

【问题讨论】:

  • 你能告诉我们你的代码吗?您如何与网络通信?
  • 是什么意思?
  • @ivg : 标准库的 Stream 模块:caml.inria.fr/pub/docs/manual-ocaml/libref/Stream.html
  • @PatJ :当你在顶层创建一个 8GB 的​​数组时,你可以看到它占用了 8GB 的​​常驻内存。仍然在顶层,如果您对其进行编组,您可以看到您使用了 16BG 的常驻内存。
  • 正如@PatJ 所要求的那样,了解您如何写入网络确实可能会有所帮助。也许您可以作为频道直接流式传输到网络中。

标签: stream ocaml marshalling


【解决方案1】:

这是不可能的。您必须修改 Marshal 模块,以便在编组某些内容时流式传输数据,并在不先缓冲所有数据的情况下就地重建数据。

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

注意:如果 GC 曾经复制过 8GiB 数组,至少是临时的,它会使用 16GiB。

【讨论】:

    【解决方案2】:

    据我了解,MPI 只允许发送已知大小的数据包,而不是数据流。您可以实现一个自定义流类型,将传入的数据流拆分为恒定的小尺寸数据包(关闭时,您刷新缓冲区中剩余的任何内容)。

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

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

    【讨论】:

    • 您的回答类似于我使用线程的复杂解决方法(MPI 可能会在您分叉时导致问题)。所以我猜你的答案是“不,没有简单的解决方案”。谢谢!
    • 恐怕是这样,但我很想被证明是错误的。祝你好运。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-07
    • 2016-03-04
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    相关资源
    最近更新 更多