2011-11-02 4 views
0

У меня есть много двоичных файлов, содержащих вывод числовой модели. Это плоские двоичные файлы, содержащие вывод чисел с плавающей запятой. Файлы соответствуют четырехмерному массиву, отсортированному по порядку t-z-y-x, причем x изменяется быстрее. Дело в том, что для заданных x, y и z мне нужны значения для всех t. Простое решение простого чтения всего в один большой массив numpy и, конечно, работы data[:,z,y,x], но не очень эффективно (мне нужно прочитать много файлов).Эффективное считывание значений в двоичном файле

То, что я придумал теперь следующее (при условии, start_index и volume_size представлять правильные вещи):

data=array.array('f') 
with file(my_filename,'rb') as infile: 
    for hour in range(amount_of_steps): 
     if hour==0: 
      infile.seek(start_index*data.itemsize,0) 
     else: 
      infile.seek(data.itemsize*volume_size,1) 
     data.fromfile(infile,1) 

не должны беспокоиться о enddianness и переносимости (хотя последний имеет в конечно, некоторые достоинства). Все это работает на Linux, и маловероятно, что он когда-либо будет работать над чем-то другим. Поэтому возникает вопрос: есть ли способ сделать это с более высокой производительностью? Это делается для многих файлов. Я попытался распараллеливать, но это действительно не помогает. Получение нового оборудования не является опцией, а SSD еще меньше - из-за объема данных. Также не меняется формат файла.

ответ

1

Возможные варианты могут включать в себя

  1. использовать mmap.

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

  2. чтобы прочитать полный файл в памяти. Это по существу то же самое, что и mmap, но без помощи ОС. OTOH, это можно сделать за один проход вместо шагов 4 kiB.

Если у вас есть данные в оперативной памяти (в файле), вы можете использовать StringIO эмулировать файл снова и кормить array.fromfile() с ним.

Осмотревшись на него, вы можете опустить StringIO и использовать вместо этого array.fromstring().

Использование только одного считываемого (или нескольких некоторых) обычно должно быть быстрее повторяющихся вызовов infile.seek() и data.fromfile(infile,1), особенно если вы читаете только одно значение за звонок. (За исключением, может быть, если ваш размер шага (volume_size) достаточно большой - пропуская от нескольких сотен до тысяч байт - тогда это МОЖЕТ быть быстрее, чтобы сделать это по-своему ...)

+0

У меня еще нет винта mmap и точно не знаю, для чего предназначен StringIO. Может быть, вы можете немного разобраться? Чтение всего файла происходит медленнее в моем опыте. Файлы не огромны (что-то около 10 МБ), но мне, возможно, придется работать через тысячи из них. – Christoph

+0

Отредактировал свой ответ, чтобы быть более точным. – glglgl

+0

Спасибо. Я посмотрю на это. Дело в том, что я пропускаю около половины мегабайта с infile.seek(), поэтому да, мой размер шага очень велик. – Christoph

1

Если бы я был вами, я бы взял посмотрите на numpy.memmap. Я использовал его в прошлом для проблемы, похожей на вашу, с хорошими результатами.

+0

Спасибо. Это, похоже, не быстрее, но дает более приятный код. – Christoph

Смежные вопросы