OCaml Marshal очень большая структура данных - PullRequest
1 голос
/ 29 марта 2019

Я хотел бы отправить очень большую (~ 8 ГБ) структуру данных через сеть, поэтому я использую модуль Marshal для преобразования его в байты.

Моя проблема в том, что память удваивается, потому что нам нужно хранить оба представления (исходные данные и данные Marshaled).

Есть ли простой способ превратить маршала в поток вместо этого? Это позволит избежать полного маршалловского представления исходной структуры данных.

Я думал о Marshaling для 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 *)

Ответы [ 2 ]

3 голосов
/ 01 апреля 2019

Это невозможно. Вам придется изменить модуль Marshal для потоковой передачи данных, поскольку он что-то собирает, и для восстановления данных на месте без предварительной буферизации их всех.

В краткосрочной перспективе может быть проще реализовать собственную специализированную функцию маршала, специфичную для ваших данных. Для массива 8 ГБ вы можете захотеть перейти на использование BigArray, чтобы вы могли отправлять / извлекать данные, не копируя их.

Примечание. Массив 8 ГБ будет использовать 16 ГБ, если ГХ когда-либо копирует его, по крайней мере, временно.

1 голос
/ 01 апреля 2019

Насколько я понимаю, MPI позволяет отправлять только пакеты данных с известным размером, а не поток данных. Вы можете реализовать пользовательский тип потока, который разделяет входящий поток данных на пакеты постоянного, небольшого размера (при закрытии вы сбрасываете все, что остается в буфере).

Кроме того, вы можете направлять только произвольные длинные данные в канал, потому что в противном случае вы занимаете слишком много места.

И затем вам нужен способ подключения канала к потоку, что не так просто сделать AFAIK. Возможно, вы могли бы запустить другой процесс ocaml: процесс преобразует поток байтов (вы можете обернуть пользовательский поток через Stream.of_channel) и отправлять его через MPI. Основной процесс направляет данные во входной канал процесса.

...