Вопрос по c++ – Самый быстрый способ записи потока данных на диск

3

У меня есть поток изображений, поступающий с камеры со скоростью около 100 кадров в секунду, причем каждое изображение составляет около 2 МБ. Теперь, из-за скорости записи на диск, я знаю, что не могу записывать каждый кадр, поэтому я пытаюсь сохранить только одну треть этих кадров каждую секунду.

Поток представляет собой кольцевой буфер больших массивов символов. И сейчас я использую fwrite для выгрузки каждого массива во временный файл, когда он буферизируется, но кажется, что он записывает только со скоростью 20-30 МБ / с, тогда как жесткий диск теоретически должен достигать 80-100 МБ / с. s

Какие-нибудь мысли? Есть ли более быстрый способ написания, чем fwrite () или способ его оптимизации? В более общем смысле, какой самый быстрый способ выгрузить большие объемы данных на стандартный жесткий диск?

Каковы значения 2-го и 3-го аргументов для вашегоfwrite звонки?fwrite1 байт за раз будет идти намного медленнее, чемfwriteпо 64К за раз. Кроме того, ты звонишьfopen заeach Рамка? Запись всех кадров в один файл может пройти быстрее. Robᵩ
@dirkgently Не будет ли использование примитива без буферизации менее эффективным, если вы не передадите кусок данных, который в точности кратен размеру сектора? SJuan76
@ SJuan76: Это было бы идеально. Но общееFILE/ofstream вероятно, не будет оптимизирован для какой-либо конкретной системы. По крайней мере, с примитивом у OP есть некое подобие шанса извлечь немало специфических для системы преимуществ. dirkgently
Используйте специфический для ОС вызов, такой какwrite в * nix системах получать небуферизованные звонки? dirkgently
Просто подсказка, но предварительное выделение файла может помочь; написать несколько гигабайтNUL байтов в файл (и не простоfseek() и напишите в конце, что "sparse), поэтому файловой системе не нужно находить место для блоков, пока вы получаете данные с камеры. Ashe

Ваш Ответ

3   ответа
1

если вы будете использовать файлы с отображением памяти, ограниченные, например, 1 ГБ каждый? Это должно обеспечить достаточную скорость и буфер для работы со всеми кадрами, особенно если вам удастся выполнить распределение кадров без копирования.

Из того, что я прочитал, отображенные в память файлы лучше всего подходят для многократного чтения и записи в один и тот же файл. Но файл должен быть достаточно маленьким, чтобы поместиться в памяти правильно? Мне нужно написать от десятков до сотен гигабайт. user1359341
Ну проверьmmap ограничения, если вы используете систему POSIX. Насколько я понимаю, существует ограничение на максимальное количество байтов, одновременно отображаемых в памяти. Для систем Windows, использующихCreateFileMapping Вы можете создать файл неограниченного размера, но когда вы работаете с самой памятью, вы должны зарезервировать ееMapViewOfFile и это ограничено пространственным адресом приложения. Примечание. Обе системы предпочитают размеры, соответствующие размеру страницы.
0

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

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

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

0

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

Boost.Asio обеспечивает относительно хорошую инкапсуляцию системных API для популярных платформ.

Есть несколько вещей, которые нужно запомнить:

on most non-Windows platforms you will have to write to raw partitions go get system's bufferization and internal threading out of the way. keep the write queue non-empty all the time, so the SATA controller can help you by means of NCQ. pay attention to system-specific requirements to buffer alignment and size for async non-buffered IO to work. file open mode is also important to make the system to do what you want.
Будет ли применяться асинхронный ввод-вывод здесь? Я изучал это раньше, но это всегда казалось ошеломляющим, особенно Boost.Asio, у которого почти нет документации. Казалось, что это помогло бы, только если между записью должна была быть обработка, так, чтобы это могло произойти, пока происходила запись. Но так как все, что я делаю - это записываю буфер, это поможет? user1359341
@ user1359341 - хорошо, если ваши буферы относительно велики (сотни МБ), вы можете достичь максимальной скорости записи вашего HD даже с блокировкой ввода-вывода (учитывая, что вы делаете только одну запись в любой данный момент). Но как бы вы сделали свою систему самоуравновешенной? Например, вы хотите, чтобы частота выпадения кадров была функцией скорости выходного потока. И эта скорость может варьироваться для жестких дисков в зависимости от того, какую дорожку вы пишете, или она может значительно измениться, если вы устанавливаете RAID, или обновляете до SSD и т. Д. Таким образом, управляемая событиями архитектура AIO среднего размера является правильным выбором.

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