При прочих равных условиях, какой самый быстрый способ вывода данных на диск в C ++? - PullRequest
7 голосов
/ 04 марта 2010

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

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

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

Ответы [ 10 ]

4 голосов
/ 04 марта 2010

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

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

4 голосов
/ 04 марта 2010

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

Редактировать: связанный вопрос и статья в Википедии о файлах с отображением в памяти - оба упоминают о преимуществах производительности.

3 голосов
/ 04 марта 2010

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

3 голосов
/ 04 марта 2010

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

2 голосов
/ 04 марта 2010

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

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

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

2 голосов
/ 04 марта 2010

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

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

2 голосов
/ 04 марта 2010

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

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

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

1 голос
/ 04 марта 2010

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

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));

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

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

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

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

0 голосов
/ 04 марта 2010

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

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

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

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

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

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

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

0 голосов
/ 04 марта 2010

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...