簡體   English   中英

使用Python編寫HDF5文件的最快方法?

[英]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_headerskip_footer關鍵字來讀取指定的行集。

暫無
暫無

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

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