用Python多处理编写分块数组
我知道有很多关于类似问题的话题,比如,或者,但我就是不明白。。。很抱歉再次询问 我需要用一个巨大的数组来做一些事情,并希望通过将它拆分成块并在这些块上运行我的函数来加快速度,每个块都在自己的进程中运行。问题是:从一个数组中剪切块,然后将结果写入一个新的公共数组。这就是我迄今为止所做的最起码的工作示例;不要介意阵列成形,这对于我的实际情况是必要的:用Python多处理编写分块数组,python,arrays,multiprocessing,Python,Arrays,Multiprocessing,我知道有很多关于类似问题的话题,比如,或者,但我就是不明白。。。很抱歉再次询问 我需要用一个巨大的数组来做一些事情,并希望通过将它拆分成块并在这些块上运行我的函数来加快速度,每个块都在自己的进程中运行。问题是:从一个数组中剪切块,然后将结果写入一个新的公共数组。这就是我迄今为止所做的最起码的工作示例;不要介意阵列成形,这对于我的实际情况是必要的: import numpy as np import multiprocessing as mp def calcArray(array, block
import numpy as np
import multiprocessing as mp
def calcArray(array, blocksize, n_cores=1):
in_shape = (array.shape[0] * array.shape[1], array.shape[2])
input_array = array[:, :, :array.shape[2]].reshape(in_shape)
result_array = np.zeros(array.shape)
# blockwise loop
pix_count = array.size
for position in range(0, pix_count, blocksize):
if position + blocksize < array.shape[0] * array.shape[1]:
num = blocksize
else:
num = pix_count - position
result_part = input_array[position:position + num, :] * 2
result_array[position:position + num] = result_part
# finalize result
final_result = result_array.reshape(array.shape)
return final_result
if __name__ == '__main__':
start = time.time()
img = np.ones((4000, 4000, 4))
result = calcArray(img, blocksize=100, n_cores=4)
print 'Input:\n', img
print '\nOutput:\n', result
代码运行并真正启动了我分配的数字进程,但与旧方法相比,只使用循环需要3秒,而不是1分钟。这里肯定缺少一些东西。核心函数是pool.apply\u async和handler.get
我最近一直在研究相同的函数,发现制作一个标准的实用函数很有用。平衡_parallel以并行方式将函数fn应用于矩阵a。在每个元素上显式应用函数。
我我分割数组的方式是np.array\u split。您可以改为使用块方案。
二,。在收集结果时,我使用concat而不是分配给空矩阵。没有共享内存
from multiprocessing import cpu_count, Pool
def balanced_parallel(fn, a, processes=None, timeout=None):
""" apply fn on slice of a, return concatenated result """
if processes is None:
processes = cpu_count()
print('Parallel:\tstarting {} processes on input with shape {}'.format(processes, a.shape))
results = assigned_parallel(fn, np.array_split(a, processes), timeout=timeout, verbose=False)
return np.concatenate(results, 0)
def assigned_parallel(fn, l, processes=None, timeout=None, verbose=True):
""" apply fn on each element of l, return list of results """
if processes is None:
processes = min(cpu_count(), len(l))
pool = Pool(processes=processes)
if verbose:
print('Parallel:\tstarting {} processes on {} elements'.format(processes, len(l)))
# add jobs to the pool
handler = [pool.apply_async(fn, args=x if isinstance(x, tuple) else (x, )) for x in l]
# pool running, join all results
results = [handler[i].get(timeout=timeout) for i in range(len(handler))]
pool.close()
return results
在你的情况下,fn是
后续行动:
为了实现并行化,您的循环应该如下所示
handles = []
for position in range(0, pix_count, BLOCKSIZE):
if position + BLOCKSIZE < ARRAY.shape[0] * ARRAY.shape[1]:
num = BLOCKSIZE
else:
num = pix_count - position
handle = pool.apply_async(func=calculate, args=(input_array[position:position + num, :], ))
handles.append(handle)
# multiple handlers exist at this moment!! Don't `.get()` yet
results = [h.get() for h in handles]
results = np.concatenate(results, axis=0)
好吧,至少它似乎起作用了:现在我必须理解它,给我一些时间让我的头脑清醒一下,然后我会接受它。谢谢大家!@s6hebern抱歉,如果它太长了:我已经多次遇到这个问题,所以我决定制定一个通用的解决方案。你可以只接受我根据你的答案编辑的基本代码,你看到我遗漏了什么吗?对我来说,代码看起来根本不起作用all@s6hebern在应用下一个作业之前,您会得到作业的结果,从而强制一个接一个地完成作业。只需应用所有作业,然后获得所有results@s6hebernaka一个循环用于apply,另一个循环用于get
def _fn(matrix_part): return matrix_part * 2
result = balanced_parallel(_fn, img)
handles = []
for position in range(0, pix_count, BLOCKSIZE):
if position + BLOCKSIZE < ARRAY.shape[0] * ARRAY.shape[1]:
num = BLOCKSIZE
else:
num = pix_count - position
handle = pool.apply_async(func=calculate, args=(input_array[position:position + num, :], ))
handles.append(handle)
# multiple handlers exist at this moment!! Don't `.get()` yet
results = [h.get() for h in handles]
results = np.concatenate(results, axis=0)