2010-12-03 3 views
6

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

Я делаю это в системе 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); 
.... 

Если я должен ломоть в письменной форме, насколько велик должен каждый кусок быть?

ответ

5

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

+0

Согласен. Единственное, что я видел, лучше, чем стандартный файл fwrite() для файла, это fwrite() для файла на/dev/shm :-) – Christoffer 2010-12-03 23:38:34

1

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

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

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

1

Вы можете найти источник 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) будет обходить эту дополнительную копию.

+0

Или напишите отчет об ошибке с помощью glibc. Смешно писать через буфер, когда данные больше, чем буфер. – 2010-12-04 03:54:52

+0

5 лет спустя это все еще так? – 2015-11-02 18:17:57

2

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

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

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

6

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

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

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