Производительность fwrite и размера записи

Я пишу большой двумерный массив размером в двоичный файл (конечный размер ~ 75 МБ).

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

Во-вторых, если я должен использовать fwrite, то должен ли я просто написать весь файл как 1 непрерывную строку?

fwrite( buf, sizeof(float), 6700*6700, fp );

или записать его в виде серии кусков

fwrite( buf, sizeof(float), 8192, fp );
fwrite( *(buf+8192), sizeof(float), 8192, fp );
....

Если я должен записать текст, насколько большой должен быть каждый кусок?

Ответ 1

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

Ответ 2

Я согласен с miked и Jerome по большей части, но... только для современной ОС. Если вы работаете в встроенной флэш файловой системе, есть некоторые основные исключения. В этой среде, если вы подозреваете fwrite(), инвестируйте в быстрый тест, используя write() с большими блоками.

Сегодня я нашел улучшение скорости на 4 раза, переходящее в write(). Это произошло из-за слоя posix во встроенной ОС, который транскрибировал fwrite() s в fputc() s... в этом случае базовый файл флэш файла SYNC просто разбивается. write() была реализована с помощью подпрограмм, гораздо более близких к ОС (Nucleus), в которых запись блоков не была разбита на байты.

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

Ответ 3

Вероятнее всего, вы получите более высокие показатели, используя nmap(), создав пространство для своего массива (виртуальное адресное пространство) и THEN, чтобы записать в "память", а не на диск.

Пусть система сделает это за вас: она, скорее всего, выделит как можно меньше страниц, что не произойдет с буфером 75 МБ, сбрасываемым fwrite().

В мире ограниченных кэшей CPU, игра с огромными буферами - это не-go (почему malloc() использует nmap() для больших распределений). Присоединив буфер к файлу при настройке nmap() - и перед заполнением буфера вы сохраните много работы в системе.

Ответ 4

Один кусок быстрее. Для этого есть несколько причин:

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

2) Диск ввода/вывода работает медленно, и поэтому ОС обычно пытается реализовать некоторое кэширование на своей стороне. Это означает, что каждый раз, когда вы используете ввод/вывод файлов, будут выполняться дополнительные проверки, если он кэшируется, если он должен быть кэширован и т.д.

Ответ 5

Вы можете найти источник fwrite в

http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/iofwrite.c;hb=HEAD

Как вы можете видеть, это, в свою очередь, вызывает IO_sputn, который в конечном итоге заканчивается на

http://sourceware.org/git/?p=glibc.git;a=blob;f=libio/fileops.c;hb=HEAD

(в частности, _IO_new_file_xsputn). Как вы можете видеть, это всегда проходит через буфер stdio.

Поэтому я бы посоветовал не использовать stdio; запись с использованием write (2) будет обходить эту дополнительную копию.