簡體   English   中英

在Python中讀取和切片二進制數據文件的最快方法

[英]Fastest way to read in and slice binary data files in Python

我有一個處理腳本,用於提取“uint16”類型的二進制數據文件,並一次以6400塊的形式進行各種處理。 該代碼最初是用Matlab編寫的,但由於分析代碼是用Python編寫的,我們希望通過在Python中完成所有工作來簡化流程。 問題是我注意到我的Python代碼比Matlab的fread函數慢得多。

簡單地說,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比我實現的Python方法快約5倍。 我已經探索了諸如numpy.fromfile和numpy.memmap之類的方法,但是因為這些方法需要在某些時候將整個文件打開到內存中,所以它限制了用例,因為我的二進制文件非常大。 有沒有一些pythonic方法可以做到這一點,我錯過了? 我本以為Python在打開+讀取二進制文件方面會非常快。 任何意見是極大的贊賞。

將塊寫入文件:

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要快得多。

沒有np.arraystruct.unpack時間是struct.unpack ; 僅僅是f.read ,23。所以它是unpack加上更通用和更健壯的np.array需要更長的時間。 文件讀取本身不是問題。 np.array可以處理多種輸入,列表列表,對象列表等,因此必須花費更多時間來解析和評估輸入。)

fromfile上稍微快一點的變體是你的讀取加上frombuffer

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM