2017-05-24 43 views
3

我有一個處理腳本,用於在「uint16」類型的二進制數據文件中提取數據,並以6400爲單位進行各種處理。該代碼最初是用Matlab編寫的,但由於分析代碼是用Python編寫的,我們想通過在Python中完成所有工作來簡化流程。問題是我注意到我的Python代碼比Matlab的fread函數慢得多。在Python中讀入和分片二進制數據文件的最快方法

只要把Matlab代碼是這樣的:

fid = fopen(filename); 
frame = reshape(fread(fid,80*80,'uint16'),80,80); 

雖然我的Python代碼很簡單:

with open(filename, 'rb') as f: 
    frame = np.array(unpack("H"*6400, f.read(12800))).reshape(80, 80).astype('float64') 

文件大小從500 MB嚴重變化 - > 400 GB所以我相信找到用Python解析數據的更快方式可以在更大的文件上分紅。 500 MB通常具有〜50000個塊,並且該數量隨着文件大小線性增加。速度差我看到大致是:

Python = 4 x 10^-4 seconds/chunk 

Matlab = 6.5 x 10^-5 seconds/chunk 

處理顯示一段時間內Matlab是〜5倍比Python的方法,我實現了更快。我已經探索過諸如numpy.fromfile和numpy.memmap之類的方法,但是由於這些方法需要在整個內存中打開整個文件,所以它限制了用例,因爲我的二進制文件非常大。是否有一些pythonic方法來做到這一點,我失蹤了?我會認爲Python在打開+讀取二進制文件時會非常快。任何意見是極大的讚賞。

+1

有沒有機會使用[dask](http://dask.pydata.org/en/latest/)與[h5py](http://www.h5py.org/)。去年,我使用這兩個軟件包進行了數以百萬計的粒子的大規模模擬。 – romeric

+1

也看看[這裏](https://stackoverflow.com/questions/14245094/how-to-read-part-of-binary-file-with-numpy) – romeric

+0

@romeric我不知道dask會作爲我使用的是「.bin」文件,而轉換成類似h5py的文件對於用例來說會適得其反。數據文件格式是我目前不能控制的不幸的。第二篇文章似乎只是使用f。與np.fromfile組合使用查找命令。我看到的問題是我可以去正確的位置,但它會將文件的其餘部分讀入numpy數組,這會使我的用例中的內存超載。 –

回答

2

寫塊到一個文件:

In [117]: dat = np.random.randint(0,1028,80*80).astype(np.uint16) 
In [118]: dat.tofile('test.dat') 
In [119]: dat 
Out[119]: array([266, 776, 458, ..., 519, 38, 840], dtype=uint16) 

導入你的方式:

In [120]: import struct 
In [121]: with open('test.dat','rb') as f: 
    ...:  frame = np.array(struct.unpack("H"*6400,f.read(12800))) 
    ...:  
In [122]: frame 
Out[122]: array([266, 776, 458, ..., 519, 38, 840]) 

導入與fromfile

In [124]: np.fromfile('test.dat',count=6400,dtype=np.uint16) 
Out[124]: array([266, 776, 458, ..., 519, 38, 840], dtype=uint16) 

比較次:

In [125]: %%timeit 
    ...: with open('test.dat','rb') as f: 
    ...:  ...:  frame = np.array(struct.unpack("H"*6400,f.read(12800))) 
    ...: 
1000 loops, best of 3: 898 µs per loop 

In [126]: timeit np.fromfile('test.dat',count=6400,dtype=np.uint16) 
The slowest run took 5.41 times longe.... 
10000 loops, best of 3: 36.6 µs per loop 

fromfile要快得多。

struct.unpack的時間,沒有np.array爲266微秒;只是f.read,23。所以這是unpack加上更通用和強大的np.array需要更長的時間。文件讀取本身不是問題。 (np.array可以處理多種輸入的,列出的名單,對象列表,等等,所以不得不花費更多的時間分析和評估的投入。)

A於fromfile稍快變是你讀的加frombuffer

In [133]: with open('test.dat','rb') as f: 
    ...:  frame3 = np.frombuffer(f.read(12800),dtype=np.uint16) 
+0

我無法獲得f.seek + np.fromfile的組合工作,但您提供的替代方案工作!使用np.frombuffer(我以前從來沒有聽說過),我能夠將python降低到24 us/chunk,比matlab等效的速度快大約2倍。乾杯。 –

相關問題