Эффективный способ сохранения данных на диск при выполнении задачи, требующей большого объема вычислений - PullRequest
5 голосов
/ 18 июня 2009

Я работаю над научным программным обеспечением, которое очень интенсивно использует процессор (его привязка к процессу), но ему нужно довольно часто записывать данные на диск (привязано к вводу / выводу).

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

Я ищу «лучшую практику» для этого, и больше всего меня волнует скорость (это могут быть очень длинные симуляции).

Спасибо ~ Alex

Первые мысли:

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

Возможно, труба / буфер? Я новичок в этом, так что, возможно, это может быть возможным решением.

Ответы [ 6 ]

5 голосов
/ 18 июня 2009

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

3 голосов
/ 18 июня 2009

Первое решение, которое приходит на ум, - это почти то, что вы сказали, - запись на диск в своем собственном процессе с односторонним каналом от сима к записывающему устройству. Автор делает запись максимально быстро (получение новых данных с конвейера). Проблема в том, что если сим будет слишком далеко опережать писателя, сим все равно будет блокировать запись в трубу, и он будет привязан к вводу / выводу при одном удалении.

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

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

Первое решение было бы лучше, если цикл обработки симуляции изменяется (иногда меньше, чем время записи, иногда дольше), потому что в среднем записи могут идти в ногу с симом.

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

2 голосов
/ 20 июня 2009

Если вы реализуете OpenMP в своей программе, то лучше использовать # pragma omp single или # pragma omp master из параллельного раздела для сохранения в файл. Эти прагмы позволяют только одному потоку выполнять что-либо. Итак, ваш код может выглядеть следующим образом:

#pragma omp parallel
{
    // Calculating the first part
    Calculate();

    // Using barrier to wait all threads
    #pragma omp barrier

    #pragma omp master
    SaveFirstPartOfResults();

    // Calculate the second part
    Calculate2();

    #pragma omp barrier

    #pragma omp master
    SaveSecondPart();

    Calculate3();

    // ... and so on
}

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

Похоже на программный конвейер. Я предлагаю вам рассмотреть шаблон tbb :: pipeline из библиотеки Intel Threading Building Blocks. Я могу отослать вас к учебнику по программным конвейерам по адресу http://cache -www.intel.com / cd / 00/00/30/11 / 301132_301132.pdf # page = 25 . Пожалуйста, прочитайте пункт 4.2. Они решили проблему: один поток для чтения с диска, второй для обработки строк чтения, третий для сохранения на диск.

1 голос
/ 18 июня 2009

Поскольку вы привязаны к процессору и IO: позвольте мне догадаться: памяти все еще достаточно, верно?

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

Для самой записи: рассмотрите возможность использования ввода-вывода с отображением памяти. Прошло много времени с тех пор, как я провёл тестирование, но в прошлый раз я сделал это значительно быстрее.

Также вы всегда можете немного обменять процессор против ввода-вывода. Я думаю, что вы в настоящее время пишете данные как некие необработанные, несжатые данные, верно? Вы можете получить некоторую производительность ввода-вывода, если будете использовать простую схему сжатия для уменьшения объема данных, которые должны быть записаны. Библиотека ZLIB довольно проста в работе и очень быстро сжимается на самом низком уровне сжатия. Это зависит от характера ваших данных, но если в них много избыточности, даже очень грубый алгоритм сжатия может устранить проблему, связанную с IO.

0 голосов
/ 18 июня 2009

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

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

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

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

0 голосов
/ 18 июня 2009

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

...