Как я могу разделить большой массив данных между процессами без дублирования? (МПК)

У меня есть процесс, который каждую секунду отправляет http-запрос на некоторый API. Затем этот процесс выполняет некоторую работу со строкой JSON, которая возвращается из запроса. В то же время я хочу передать эту строку JSON другому процессу, чтобы сделать что-то еще.

Ключевым моментом является то, что я хочу продолжать добавлять каждую новую строку JSON в конец массива, чтобы все строки JSON сохранялись в памяти на время выполнения программы.

Я изучаю использование каналов или mmap для обмена строками JSON, поскольку это, кажется, самые быстрые способы, о которых я знаю. Однако кажется, что конвейеры будут выполнять больше работы, чем необходимо, потому что мне придется отправлять строки, которые кажутся ненужными, поскольку они уже находятся в памяти.

Я думал, что mmap сможет избежать этой проблемы, если я смогу просто сопоставить массив обоим процессам. Я не хочу, чтобы строки записывались в реальный файл на диске, поэтому мне пришлось бы использовать анонимное сопоставление, но кажется, что анонимные сопоставления создают область, которая обнуляется, и тогда мне придется копировать свой массив в отображаемую память. области для обмена данными. Это тоже кажется ненужной работой, потому что я дублирую память.

Есть ли способ, которым я могу просто предоставить второму процессу доступ к массиву строк без дублирования строк или копирования? Я не могу использовать потоки, хотя потоки могут легко совместно использовать память, потому что процесс, выполняющий запросы REST, будет программой C++, а второй процесс будет программой Python.


person user3567004    schedule 28.05.2020    source источник
comment
Когда вы говорите большой, что вы имеете в виду? Несколько килобайт? Сотни килобайт? Мегабайты?   -  person Some programmer dude    schedule 28.05.2020
comment
Что касается вашей проблемы, существует множество способов межпроцессного взаимодействия, некоторые (например, общая память), которые могут работать без дублирования данных. Однако вам нужна какая-то синхронизация и блокировка, чтобы общая память работала.   -  person Some programmer dude    schedule 28.05.2020
comment
@Someprogrammerdude К моменту завершения программы массив будет составлять пару гигабайт. Кроме того, mmap не разделяет память? У меня сложилось впечатление, что люди использовали mmap для обмена памятью.   -  person user3567004    schedule 28.05.2020
comment
Вы можете использовать mmap для сопоставления сегмента разделяемой памяти с вашим процессом, но для создания или загрузки фактического сегмента разделяемой памяти необходимы другие обходные пути. Существует множество руководств о том, как это сделать.   -  person Some programmer dude    schedule 28.05.2020
comment
@Someprogrammerdude Я прочитал следующий пост о совместном использовании памяти, и принятый ответ, похоже, подразумевал, что mmap был современным способом совместного использования памяти, тогда как функции общей памяти, которые начинаются с shm в Linux, кажутся старым способом ведения дел. stackoverflow .com/questions/5656530/   -  person user3567004    schedule 28.05.2020
comment
Что касается данных и их количества, вам действительно нужно иметь все данные в памяти одновременно? Какие у вас есть требования, которые заставляют вас держать все это в памяти? Простая строка JSON обычно не должна превышать несколько килобайт. Как насчет общей циклической очереди для сообщений JSON?   -  person Some programmer dude    schedule 28.05.2020
comment
В принятом ответе вы видите флаг MAP_ANONYMOUS? Это означает, что это анонимный сегмент разделяемой памяти, который можно использовать только в том случае, если вы fork обрабатываете себя внутри своей программы, и, что более важно, вам нужно отслеживать указатель, возвращаемый mmap (который должен быть вызван до fork), так как это указатель, который должен использоваться всеми разветвленными дочерними процессами. Если у вас есть два независимых процесса или вы загружаете независимую программу через вызов exec, вам нужен именованный сегмент памяти.   -  person Some programmer dude    schedule 28.05.2020


Ответы (1)


Взгляните на boost interprocess.

Вам нужно создать файл с отображением памяти, который передается в boost.interprocess allocator. Этот распределитель берет фрагменты отображаемого в память файла. Затем их можно использовать так, как если бы они были возвращены std::allocator. С применением сопоставления, чтобы память была совместима с конкретной памятью внутри процесса.

Контейнер boost.interprocess будет использовать память, возвращенную распределителем. Он имеет интерфейс, похожий на std::container.

Вам нужно синхронизировать данные. Это делается с помощью некоторого межпроцессного мьютекса и должно использоваться для предотвращения условий гонки доступа к данным.

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

Используя MPI, вы запускаете несколько процессов, которые обычно вычисляют одно и то же с разными входными данными.

MPI предлагает возможность создать MPI Window. С помощью этого окна вы можете записывать в память других MPI процессов.

Таким образом, ответ на ваш вопрос - да. Но это сопряжено с некоторыми затратами. Сценарий MPI требует запуска ваших процессов. Вы можете столкнуться с тупиком, гонками данных, ...

person schorsch312    schedule 28.05.2020