Все вещи равняются тому, что самый быстрый путь к выходным данным к диску в C++?

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

Каково было бы быстрое решение, которое уменьшит наверху? iostreams? printf? Я ранее считал, что printf быстрее. Это будет зависеть от моего кода, и действительно ли невозможно получить ответ без профилирования?

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

7
задан 5 revs 15 June 2011 в 22:02
поделиться

10 ответов

Я думаю, что вы решаете не ту проблему. Зачем вы выписываете огромное количество данных в текстовом формате? Если потому, что вы хотите, чтобы они были читаемы человеком, напишите быструю программу для браузера, чтобы читать данные в двоичном формате на лету - таким образом, приложение моделирования может быстро записывать двоичные данные, а браузер может делать тяжелую работу по форматированию данных по мере необходимости. Если вы используете какой-либо статистический пакет для чтения и анализа текстовых данных, напишите программу, которая вводит двоичные данные.

3
ответ дан 6 December 2019 в 08:42
поделиться

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

  • нормальный ввод-вывод потока C ++
  • нормальный ввод-вывод потока с использованием ostream :: write ()
  • использование библиотеки CI / O
  • использование системных вызовов, таких как as write ()
  • asynch I / O

И я бы остановился, когда нашел решение, которое было достаточно быстрым.

2
ответ дан 6 December 2019 в 08:42
поделиться

Самый быстрый способ - асинхронный ввод-вывод на основе завершения.

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

API для этого зависит от ОС: в Linux он называется AIO ; в Windows это называется Порты завершения .

0
ответ дан 6 December 2019 в 08:42
поделиться

Текстовый формат означает, что он предназначен для употребления людьми. Скорость, с которой люди могут читать, намного, намного ниже скорости любого разумного метода вывода. Где-то есть противоречие. Я подозреваю, что «вывод должен быть в текстовом формате».

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

2
ответ дан 6 December 2019 в 08:42
поделиться

Пункт 23 «Рассмотрение альтернативных библиотек» Скотта Мейерса «Более эффективный C ++» предлагает использовать stdio вместо iostream, если вы предпочитаете скорость, а не безопасность и расширяемость. Стоит проверить.

3
ответ дан 6 December 2019 в 08:42
поделиться

Создавать (большие) блоки данных, которые могут быть последовательно записаны, и использовать асинхронный ввод-вывод.

Точное профилирование будет болезненным, прочтите несколько статей по этой теме: scholar.google.com .

4
ответ дан 6 December 2019 в 08:42
поделиться

Отображение файла в память (то есть с использованием файла сопоставления памяти ), а затем просто memcopy -ing данных, есть действительно быстрый способ чтения / записи.

Вы можете использовать несколько потоков / ядер для записи в данные, и ОС / ядро ​​будет синхронизировать страницы с диском, используя те же процедуры, что и для виртуальной памяти, которые можно ожидать, которые будут оптимизированы до чертиков и обратно. , более или менее.

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

2
ответ дан 6 December 2019 в 08:42
поделиться

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

Edit: related question, and Wikipedia article on memory mapped files - both mention performance benefits.

4
ответ дан 6 December 2019 в 08:42
поделиться

Откройте файл в двоичном режиме и запишите «неформатированные» данные на диск.

fstream myFile;
...
myFile.open ("mydata.bin", ios:: in | ios::out | ios::binary);
...
class Data {
    int      key;
    double   value;
    char[10] desc;
};

Data x;

myFile.seekp (location1);
myFile.write ((char*)&x, sizeof (Data));

РЕДАКТИРОВАТЬ: OP добавил: «Выходные данные должны быть в текстовом формате, независимо от того, разделены ли они табуляцией или запятой». ограничение.

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

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

Переход от двоичного кода к ascii, а затем придирки относительно относительной производительности printf по сравнению с iostreams, вероятно, не лучшее использование вашего времени.

1
ответ дан 6 December 2019 в 08:42
поделиться

Быстрый метод заключается в использовании двойной буферизации и нескольких потоков (по крайней мере, двух).

Один поток отвечает за запись данных на жесткий диск. Эта задача проверяет буфер и, если он не пуст (или возможно другое правило), начинает запись на жесткий диск.

Другой поток записывает форматированный текст в буфер.

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

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

Если переносимость не является проблемой, вы можете проверить свою ОС на наличие API, которые выполняют блочную запись на жесткий диск. Или можно спуститься ниже и использовать API, выполняющий запись непосредственно на диск.

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

0
ответ дан 6 December 2019 в 08:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: