在Python2.7中,我必须构建一个二维数组(arrayFullCross_final[u][u]
),其中包含16个块,每个块的大小为100x100元素。首先,我使用4D数组(arrayFullCross
),然后将其重塑为400x400 2D数组。
我有一个第一个版本(顺序版本),其中我正在使用经典的python函数“ map”和一个这样的“生成器”(buildCrossMatrix_loop
是我要应用生成器generatorCrossMatrix
的函数):
# Build all big matrix with N total blocks = dimBlock*dimBlock = 16 here
arrayFullCross = np.zeros((dimBlocks, dimBlocks, arrayCross_k.size, arrayCross_mu.size))
def buildCrossMatrix_loop(params_array):
# rows indices
xb = params_array[0]
# columns indices
yb = params_array[1]
# Current redshift
z = zrange[params_array[2]]
# Loop inside block
for ub in range(dimPoints):
for vb in range(dimPoints):
# Diagonal terms
if (xb == yb):
#arrayFullCross[u][u][w][t] = 2*P_bgs**2 * N_bgs**2
if (xb == 0):
N_bgs = (1+1/(n[params_array[2]]*P_obs_cross(arrayCross_k[ub], arrayCross_mu[vb] , z, 10**P_m(np.log10(arrayCross_k[ub])), 10**P_m_NW(np.log10(arrayCross_k[ub])), bias2D_array*sig_8_fid, growth_f[params_array[2]]*sig_8_fid, H_orig(z), H_orig(z), D_A_orig(z), D_A_orig(z), params_array[2], 0, 0)))
arrayFullCross[xb][xb][ub][vb] = 2*P_obs_cross(arrayCross_k[ub], arrayCross_mu[vb] , z, 10**P_m(np.log10(arrayCross_k[ub])), 10**P_m_NW(np.log10(arrayCross_k[ub])), bias2D_array*sig_8_fid, growth_f[params_array[2]]*sig_8_fid, H_orig(z), H_orig(z), D_A_orig(z), D_A_orig(z), params_array[2], 0, 0)**2 * N_bgs**2
...
...
##### MAIN LOOP to fill, at each index i, the array "arrayFullCross" #####
while i < len(zrange):
...
...
def generatorCrossMatrix(index):
for igen in range(dimBlocks):
for lgen in range(dimBlocks):
yield igen, lgen, index
if __name__ == '__main__':
map(buildCrossMatrix_loop, generatorCrossMatrix(i))
...
...
i = i+1
i
只是“ while”主循环的索引。
使用此顺序方法,一切正常,我得到了预期的大输出数组arrayFullCross[u][v][x][y]
(我检查了其中的值,并以400x400的形状进行了整形,这很好)。
现在,我尝试用multiprocessing import Pool
做同样的事情。我做到了:
from multiprocessing import Pool
def buildCrossMatrix_loop(params_array):
...
while i < len(zrange):
...
if __name__ == '__main__':
pool = mp.Pool(16)
pool.map(buildCrossMatrix_loop, generatorCrossMatrix(i))
pool.terminate()
# Reshape 4D array to 2D global array
arrayFullCross2D_final = arrayFullCross.swapaxes(1,2).reshape(dimMatCovCross,dimMatCovCross)
print 'arrayFullCross2D_final = ', arrayFullCross2D_final
但是当我打印最终输出的2D数组arrayFullCross2D_final
时,系统地得到了一个仅填充零值的数组。
arrayFullCross2D_final = [[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
也许我必须在不同进程之间共享4D数组arrayFullCross
?我该如何执行呢?
每个过程如何才能同时修改4D数组的不同部分?
似乎循环的每个i
索引都覆盖了这个4D全局数组。
更新1:我忘了说我已经声明了这样的完整数组(在主数组的开始,即在while
循环之外):
# Build all big matrix with N total blocks = dimBlock*dimBlock = 16 here
arrayFullCross = np.zeros((dimBlocks, dimBlocks, arrayCross_k.size, arrayCross_mu.size))
我如何使用给出答案的解决方案和我对arrayFullCross的声明,即:
manager = Manager()
arrayFullCross = manager.list()
??
更新2:虽然我通过将ThreadPool
与from multiprocessing.dummy import Pool as ThreadPool
结合使用以这种方式找到了一个好的解决方案:
pool = ThreadPool(16)
pool.map(buildCrossMatrix_loop, generatorCrossMatrix(i))
pool.close()
pool.join()
但是性能似乎很差:确实,我只看到一个用top
或htop
命令运行的进程,这很正常吗?
似乎大部分时间都是通过锁定全局数组来写的:这是没有必要的,因为我将全局数组填充在独立的子数组上。
有人已经测试过此解决方案(ThreadPool
)吗?
欢迎您使用其他任何替代方法
答案 0 :(得分:0)
代码似乎确实是正确的。但是,当您在池模式下运行它时,每个工作线程将拥有自己的阵列副本。然后,它们将写回到您从未接触过的共享内存副本,因此表中填充了0。
通过使用multiprocessing
模块中的共享内存变量,您应该能够与主线程共享结果。您可以使用c型数组,但这会大大增加代码的复杂性。 multiprocessing
模块通过Manager
子模块提供类似python的列表。将arrayFullCross
设为Manager
列表就足够了:
from multiprocessing import Manager, Pool
manager = Manager()
arrayFullCross = manager.list()
def buildCrossMatrix_loop(params_array):
...
while i < len(zrange):
...
if __name__ == '__main__':
pool = mp.Pool(16)
pool.map(buildCrossMatrix_loop, generatorCrossMatrix(i))
pool.terminate()
# Reshape 4D array to 2D global array
arrayFullCross2D_final = arrayFullCross.swapaxes(1,2).reshape(dimMatCovCross,dimMatCovCross)
print 'arrayFullCross2D_final = ', arrayFullCross2D_final
值得注意的是,利用manager
对象会产生一定程度的开销。如果性能不满意,请尝试使用multiprocessing
中的Array类型。
有关这些资源的更多信息,请参见multiprocessing docs。