Каков Самый Быстрый Метод для Высокопроизводительного Последовательного Файлового ввода-вывода в C++?

Хотя большинство методов, изложенных здесь, верны, bash 4.2 поддерживает фактический тест на наличие переменной ( man bash ), а не тестирует значение переменной ,

[[ -v foo ]]; echo $?
# 1

foo=bar
[[ -v foo ]]; echo $?
# 0

foo=""
[[ -v foo ]]; echo $?
# 0

Примечательно, что этот подход не приведет к ошибке при использовании для проверки неустановленной переменной в режиме set -u / set -o nounset, в отличие от многих других подходов, таких как использование [ -z.

49
задан Adam Holmberg 29 July 2009 в 04:53
поделиться

5 ответов

Существуют ли общепринятые рекомендации для достижения максимально быстрого последовательного ввода-вывода файлов в C ++?

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

  1. Используйте отображаемую память вместо записи в файлы. Это не всегда быстрее, но дает возможность оптимизировать ввод-вывод специфичным для операционной системы, но относительно переносимым способом, избегая ненужного копирования и используя преимущества ОС. s знание того, как на самом деле используется диск. («Переносимый», если вы используете оболочку, а не вызов API для конкретной ОС.)

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

Некоторые возможные соображения:

  • Рекомендации по выбору оптимального размера буфера

Размер страницы для начинающих, но будьте готовы настроить оттуда.

  • Будет ли переносимая библиотека, такая как boost :: asio, слишком абстрактной, чтобы раскрыть тонкости

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

  • Некоторые возможные соображения:

    • Рекомендации по выбору оптимального размера буфера

    ] Размер страницы для начинающих, но будьте готовы настроить оттуда.

    • Будет ли переносимая библиотека, такая как boost :: asio, слишком абстрактной, чтобы раскрыть все тонкости?

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

    • Некоторые возможные соображения:

      • Рекомендации по выбору оптимального размера буфера

      ] Размер страницы для начинающих, но будьте готовы настроить оттуда.

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

      • Некоторые возможные соображения:

        • Рекомендации по выбору оптимального размера буфера

        ] Размер страницы для начинающих, но будьте готовы настроить оттуда.

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

        • Некоторые возможные соображения:

          • Рекомендации по выбору оптимального размера буфера

          ] Размер страницы для начинающих, но будьте готовы настроить оттуда.

          • Будет ли переносимая библиотека, такая как boost :: asio, слишком абстрактной, чтобы раскрыть тонкости конкретной платформы, или их можно считать оптимальными?

          Не думайте, что это оптимально. Это зависит от того, насколько тщательно библиотека используется на вашей платформе и сколько усилий приложили разработчики, чтобы сделать ее быстрой. Сказав, что переносимая библиотека ввода-вывода может быть очень быстрой, потому что быстрые абстракции существуют в большинстве систем, и обычно можно придумать общий API, который охватывает множество основ. Boost.Asio, насколько мне известно, довольно точно настроен для конкретной платформы, на которой он находится: существует целое семейство API-интерфейсов, специфичных для ОС и вариантов ОС, для быстрого асинхронного ввода-вывода (например, epoll , / dev / epoll , kqueue , Windows overlapped I / O ), и Asio обертывает их все.

          • Всегда ли асинхронный ввод-вывод предпочтительнее синхронного? Что, если приложение не связано с ЦП?

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

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

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

32
ответ дан 7 November 2019 в 11:53
поделиться

Для Windows необходимо убедиться, что вы используете FILE_FLAG_SEQUENTIAL_SCAN в вызове CreateFile (), если вы решите использовать вызов API Windows для конкретной платформы. Это оптимизирует кеширование ввода-вывода. Что касается размеров буфера, обычно рекомендуется размер буфера, кратный размеру сектора диска. 8K - прекрасная отправная точка, и от увеличения ее размера мало что можно получить.

В этой статье обсуждается сравнение между асинхронностью и синхронизацией в Windows.

http://msdn.microsoft.com/en-us/library/aa365683 (VS.85) .aspx

7
ответ дан 7 November 2019 в 11:53
поделиться

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

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

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

Если mmap () вам не по душе, то есть fadvise () и, для действительно сложных, ввод-вывод асинхронных файлов.

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

12
ответ дан 7 November 2019 в 11:53
поделиться

Как вы отметили выше, все зависит от используемого вами компьютера / системы / библиотек. Быстрое решение в одной системе может быть медленным в другой.

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

Лучшее способ узнать наверняка - это закодировать несколько разных способов и профилировать их.

3
ответ дан 7 November 2019 в 11:53
поделиться

Вы спрашивали о C ++, но похоже, что вы уже прошли это и готовы немного узнать о платформе.

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

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

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

Грубо говоря, ОЗУ в 1000 или более раз быстрее дисков, а ЦП все еще быстрее. Вероятно, не так много логических оптимизаций, которые помогут, кроме как избежать перемещений головок диска (поиска), когда это возможно. Выделенный диск только для этого файла может здесь существенно помочь.

2
ответ дан 7 November 2019 в 11:53
поделиться
Другие вопросы по тегам:

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