簡體   English   中英

如何在python中安全地將單個hdf5文件中的數據並行寫入多個文件?

[英]how do I safely write data from a single hdf5 file to multiple files in parallel in python?

我正在嘗試將我的數據(從hdf5格式的單個文件)寫入多個文件,並且在串行執行任務時它可以正常工作。 現在我想提高效率並使用multiprocessing模塊修改代碼,但輸出有時會出錯。 這是我的代碼的簡化版本。

import multiprocessing as mp
import numpy as np
import math, h5py, time
N = 4  # number of processes to use
block_size = 300
data_sz = 678
dataFile = 'mydata.h5'

# fake some data
mydata = np.zeros((data_sz, 1))
for i in range(data_sz):
    mydata[i, 0] = i+1
h5file = h5py.File(dataFile, 'w')
h5file.create_dataset('train', data=mydata)

# fire multiple workers
pool = mp.Pool(processes=N)
total_part = int(math.ceil(1. * data_sz / block_size))
for i in range(total_part):
    pool.apply_async(data_write_func, args=(dataFile, i, ))
pool.close()
pool.join()

data_write_func()的結構是:

def data_write_func(h5file_dir, i, block_size=block_size):
    hf = h5py.File(h5file_dir)
    fout = open('data_part_' + str(i), 'w')
    data_part = hf['train'][block_size*i : min(block_size*(i+1), data_sz)]  # np.ndarray
    for line in data_part:
        # do some processing, that takes a while...
        time.sleep(0.01)
        # then write out..
        fout.write(str(line[0]) + '\n')
    fout.close()

當我設置N=1 ,它運作良好。 但是當我設置N=2N=4 ,結果有時會混亂(不是每次都!)。 例如在data_part_1中我期望輸出為:

301,
302,
303,
...

但有時我得到的是

0,
0,
0,
...

有時我會

379,
380,
381,
...

我是多處理模塊的新手,發現它很棘手。 如果有任何建議,請欣賞它!

修復fout.writemydata=... ,Andriy建議您的程序按預期工作,因為每個進程都寫入自己的文件。 這些過程無法相互融合。

probaby想做的使用是multiprocessing.map()其削減你的迭代你(所以你不需要做block_size一樣的東西),再加上它保證了結果的順序進行。 我重寫了你的代碼以使用多處理映射:

import multiprocessing
from functools import partial
import pprint

def data_write_func(line):
  i = multiprocessing.current_process()._identity[0]
  line = [i*2 for i in line]
  files[i-1].write(",".join((str(s) for s in line)) + "\n")

N = 4
mydata=[[x+1,x+2,x+3,x+4] for x in range(0,4000*N,4)] # fake some data
files = [open('data_part_'+str(i), 'w') for i in range(N)]

pool = multiprocessing.Pool(processes=N)
pool.map(data_write_func, mydata)
pool.close()
pool.join()

請注意:

  • 我是從這個過程中取出來的,它是1或2
  • 因為現在為每一行調用data_write_func ,所以需要在父進程中完成文件打開。 另外:你不需要手動close()文件,操作系統會在退出你的python程序時為你做這件事。

現在,我想最后你想要將所有輸出都放在一個文件中,而不是放在單獨的文件中。 如果您的輸出行在Linux上低於4096字節(或在OSX上低於512字節,對於其他操作系統,請參見此處 ),您實際上只需打開一個文件(在附加模式下)並讓每個進程只寫入該文件,如下所述,這些大小保證是Unix的原子。

更新

“如果數據作為數據集存儲在hdf5文件中怎么辦?”

根據hdf5 doc,自2.2.0版以來,它開箱即用

並行HDF5是HDF5庫的一種配置,允許您跨多個並行進程共享打開的文件。 它使用MPI(消息傳遞接口)標准進行進程間通信

因此,如果您在代碼中執行此操作:

h5file = h5py.File(dataFile, 'w')
dset = h5file.create_dataset('train', data=mydata)

然后你可以從你的進程中訪問dset並讀取/寫入它而不需要采取任何額外的措施。 另請參閱h5py中使用多處理的此示例

這個問題無法復制。 這是我的完整代碼:

#!/usr/bin/env python

import multiprocessing

N = 4
mydata=[[x+1,x+2,x+3,x+4] for x in range(0,4000*N,4)] # fake some data

def data_write_func(mydata, i, block_size=1000):
    fout = open('data_part_'+str(i), 'w')
    data_part = mydata[block_size*i: block_size*i+block_size]
    for line in data_part:
        # do some processing, say *2 for each element...
        line = [x*2 for x in line]
        # then write out..
        fout.write(','.join(map(str,line))+'\n')
    fout.close()

pool = multiprocessing.Pool(processes=N)
for i in range(2):
      pool.apply_async(data_write_func, (mydata, i, ))
pool.close()
pool.join()

data_part_0示例輸出:

2,4,6,8
10,12,14,16
18,20,22,24
26,28,30,32
34,36,38,40
42,44,46,48
50,52,54,56
58,60,62,64

多處理不能保證不同線程之間代碼執行的順序,2個進程按其創建順序的相反順序執行是完全合理的(至少在windows和主流linux上)

通常當您使用並行化時,您需要工作線程生成數據然后將數據聚合到線程安全的數據結構並將其保存到文件,但是您在這里寫入一個文件,可能是在一個硬盤上,您有任何理由嗎?相信你會通過使用多個線程獲得任何額外的性能?

暫無
暫無

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

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