Самый быстрый способ записи данных при их создании - PullRequest
7 голосов
/ 03 января 2012

В моей программе я моделирую систему из N тел для большого количества итераций. Для каждой итерации я создаю набор из 6N координат, которые мне нужно добавить в файл, а затем использовать для выполнения следующей итерации. Код написан на C ++ и в настоящее время использует метод ofstream write() для записи данных в двоичном формате на каждой итерации.

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

Я запутался, потому что у меня нет опыта в реальном параллельном программировании и низкоуровневом файловом вводе / выводе. Я подумал о некоторых абстрактных методах, которые я мог бы реализовать, поскольку я программирую для современных (возможно, многоядерных) машин с ОС Unix:

  • Запись данных в файл по частям из n итераций (кажется, есть лучшие способы продолжить ...)
  • Распараллеливание кода с OpenMP (как на самом деле реализовать буфер, чтобы потоки синхронизировались надлежащим образом и не перекрывались?)
  • Использование mmap (размер файла может быть огромным, порядка ГБ, достаточно ли надежен этот подход?)

Однако я не знаю, как наилучшим образом реализовать их и правильно их объединить.

Ответы [ 4 ]

3 голосов
/ 03 января 2012

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

Вы должны использовать производитель -> потребитель шаблон проектирования. Они будут связаны очередью, подобно конвейерной ленте.

  • Производитель будет пытаться производить так быстро, как только может, только замедляя, если потребитель не сможет с этим справиться.
  • Потребитель будет пытаться «потреблять» как можно быстрее.

Разделив их, вы можете повысить производительность, поскольку каждый процесс проще и имеет меньше помех от других.

  • Если производитель работает быстрее, вам нужно улучшить потребителя, в вашем случае, записав в файл наиболее эффективным способом, фрагмент за частью, скорее всего (как вы сказали)
  • Если потребитель быстрее, вам нужно улучшить производителя, скорее всего, распараллелив его, как вы сказали.

не нужно для оптимизации обоих. Оптимизируйте только самое медленное (узкое место).

Практически вы используете потоки и синхронизированную очередь между ними. Для подсказок по реализации посмотрите здесь , особенно §18.12 «Шаблон производитель-потребитель».

Что касается управления потоками, вам придется добавить немного больше сложности, выбрав «максимальный размер очереди» и заставив производителей ждать, если в очереди недостаточно места. Остерегайтесь тупиков, закодируйте их внимательно. (см. ссылку на Википедию, которую я дал об этом)

Примечание. Рекомендуется использовать потоки повышения, поскольку потоки не очень переносимы. (ну, они с C ++ 0x, но доступность C ++ 0x пока не очень хорошая)

1 голос
/ 03 января 2012

Если вы не хотите играть с работой в разных потоках, вы можете попробовать использовать aio_write () , которая разрешает асинхронную запись.По сути, вы даете ОС буфер для записи, и функция немедленно возвращается и завершает запись, пока ваша программа продолжается, вы можете проверить позже, чтобы увидеть, завершена ли запись.

Это решение все еще страдает отпроблема производителя / потребителя, упомянутая в других ответах: если ваш алгоритм генерирует данные быстрее, чем их можно записать, в конечном итоге вам не хватит памяти для сохранения результатов между алгоритмом и записью, поэтому вам придется попробовать ипосмотрим, как это работает.

1 голос
/ 03 января 2012

Лучше разделить операцию на два независимых процесса: data-producing и file-writing.Data-producing будет использовать некоторый буфер для передачи итерационных данных, а file-writing будет использовать очередь для хранения запросов на запись.Затем data-producing просто отправит запрос на запись и продолжит работу, в то время как file-writing справится с записью в фоновом режиме.

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

0 голосов
/ 03 января 2012

"Использование mmap (размер файла может быть огромным, порядка ГБ, это подход достаточно надежный?) "

mmap - это метод загрузки программ, общих библиотек и файла подкачки и файлов подкачки в ОС - он такой же надежный, как и любой другой файловый ввод-вывод, и, как правило, более высокая производительность.

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

...