[英]Fastest way to write HDF5 files with Python?
給定一個大的(10英寸GB)混合文本/數字的CSV文件,創建具有相同內容的HDF5文件的最快方法是什么,同時保持內存使用合理?
我想盡可能使用h5py
模塊。
在下面的玩具示例中,我發現將數據寫入HDF5的速度非常慢且非常快。 以10,000行左右的大塊寫入HDF5是最佳做法嗎? 或者有更好的方法將大量數據寫入此類文件?
import h5py
n = 10000000
f = h5py.File('foo.h5','w')
dset = f.create_dataset('int',(n,),'i')
# this is terribly slow
for i in xrange(n):
dset[i] = i
# instantaneous
dset[...] = 42
我會避免分塊數據,並將數據存儲為一系列單個數組數據集(沿着本傑明建議的方式)。 我剛剛完成加載我正在研究HDF5的企業應用程序的輸出,並且能夠將大約4.5億個復合數據類型打包為450,000個數據集,每個數據集包含10,000個數據陣列。 現在寫入和讀取似乎是相當即時的,但是當我最初嘗試分塊數據時,寫入和讀取非常緩慢。
只是一個想法!
更新:
這些是從我的實際代碼中解脫出來的一些片段(我在C與Python編碼,但你應該了解我正在做的事情)並為了清晰而修改。 我只是在數組中編寫長無符號整數(每個數組10,000個值),並在需要實際值時讀回它們
這是我典型的編劇代碼。 在這種情況下,我只是將長無符號整數序列寫入數組序列,並在創建時將每個數組序列加載到hdf5中。
//Our dummy data: a rolling count of long unsigned integers
long unsigned int k = 0UL;
//We'll use this to store our dummy data, 10,000 at a time
long unsigned int kValues[NUMPERDATASET];
//Create the SS adata files.
hid_t ssdb = H5Fcreate(SSHDF, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
//NUMPERDATASET = 10,000, so we get a 1 x 10,000 array
hsize_t dsDim[1] = {NUMPERDATASET};
//Create the data space.
hid_t dSpace = H5Screate_simple(1, dsDim, NULL);
//NUMDATASETS = MAXSSVALUE / NUMPERDATASET, where MAXSSVALUE = 4,500,000,000
for (unsigned long int i = 0UL; i < NUMDATASETS; i++){
for (unsigned long int j = 0UL; j < NUMPERDATASET; j++){
kValues[j] = k;
k += 1UL;
}
//Create the data set.
dssSet = H5Dcreate2(ssdb, g_strdup_printf("%lu", i), H5T_NATIVE_ULONG, dSpace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
//Write data to the data set.
H5Dwrite(dssSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, kValues);
//Close the data set.
H5Dclose(dssSet);
}
//Release the data space
H5Sclose(dSpace);
//Close the data files.
H5Fclose(ssdb);
這是我的讀者代碼的略微修改版本。 有更優雅的方法可以做到這一點(也就是說,我可以使用超平面來獲得價值),但對於我相當自律的敏捷/ BDD開發流程,這是最干凈的解決方案。
unsigned long int getValueByIndex(unsigned long int nnValue){
//NUMPERDATASET = 10,000
unsigned long int ssValue[NUMPERDATASET];
//MAXSSVALUE = 4,500,000,000; i takes the smaller value of MAXSSVALUE or nnValue
//to avoid index out of range error
unsigned long int i = MIN(MAXSSVALUE-1,nnValue);
//Open the data file in read-write mode.
hid_t db = H5Fopen(_indexFilePath, H5F_ACC_RDONLY, H5P_DEFAULT);
//Create the data set. In this case, each dataset consists of a array of 10,000
//unsigned long int and is named according to its integer division value of i divided
//by the number per data set.
hid_t dSet = H5Dopen(db, g_strdup_printf("%lu", i / NUMPERDATASET), H5P_DEFAULT);
//Read the data set array.
H5Dread(dSet, H5T_NATIVE_ULONG, H5S_ALL, H5S_ALL, H5P_DEFAULT, ssValue);
//Close the data set.
H5Dclose(dSet);
//Close the data file.
H5Fclose(db);
//Return the indexed value by using the modulus of i divided by the number per dataset
return ssValue[i % NUMPERDATASET];
}
主要的內容是編寫代碼中的內部循環以及整數除法和mod操作,以獲取數據集數組的索引和該數組中所需值的索引。 讓我知道這是否足夠清楚,以便你可以在h5py中組合類似或更好的東西。 在C中,這很簡單,與分塊數據集解決方案相比,顯着提高了讀/寫時間。 此外,由於我無法使用復合數據集進行壓縮,因此分塊的明顯優勢是有爭議的,所以我的所有化合物都以相同的方式存儲。
使用numpy.loadtxt
的靈活性將從文件中獲取數據到numpy array
,這反過來非常適合初始化hdf5
數據集。
import h5py
import numpy as np
d = np.loadtxt('data.txt')
h = h5py.File('data.hdf5', 'w')
dset = h.create_dataset('data', data=d)
我不確定這是否是最有效的方式(我從來沒有使用它;我只是將我獨立使用的一些工具放在一起),但你可以使用matplotlib將csv文件讀入一個numpy重新組合csv的輔助方法 。
您可以找到一種方法來讀取塊中的csv文件,以避免將整個內容加載到磁盤上。 然后使用重新排列(或其中的切片)將整個(或大塊)寫入h5py數據集。 我不確定h5py如何處理重新排列,但文檔表明它應該沒問題。
基本上,如果可能的話,嘗試一次編寫大塊數據,而不是迭代單個元素。
讀取csv文件的另一種可能性是numpy.genfromtxt
您可以使用關鍵字usecols
獲取所需的列,然后通過正確設置skip_header
和skip_footer
關鍵字來讀取指定的行集。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.