【发布时间】:2018-05-04 08:04:18
【问题描述】:
我知道有很多关于类似问题的主题(例如How do I make processes able to write in an array of the main program?、Multiprocessing - Shared Array 或Multiprocessing a loop of a function that writes to an array in python),但我就是不明白……抱歉再次提问。
我需要用一个巨大的数组做一些事情,并希望通过将它分成块并在这些块上运行我的函数来加速事情,每个块都在自己的进程中运行。问题是:从一个数组中“剪切”块,然后将结果写入一个新的公共数组。这是我到目前为止所做的(最小的工作示例;不要介意数组整形,这对于我的实际情况是必要的):
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
我现在如何实现多处理,即设置多个内核,然后 calcArray 将进程分配给每个块,直到达到 n_cores?
在@Blownhither Ma 的大力帮助下,代码现在看起来像这样:
import time, datetime
import numpy as np
from multiprocessing import Pool
def calculate(array):
return array * 2
if __name__ == '__main__':
start = time.time()
CORES = 4
BLOCKSIZE = 100
ARRAY = np.ones((4000, 4000, 4))
pool = Pool(processes=CORES)
in_shape = (ARRAY.shape[0] * ARRAY.shape[1], ARRAY.shape[2])
input_array = ARRAY[:, :, :ARRAY.shape[2]].reshape(in_shape)
result_array = np.zeros(input_array.shape)
# do it
pix_count = ARRAY.size
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
### OLD APPROACH WITH NO PARALLELIZATION ###
# part = calculate(input_array[position:position + num, :])
# result_array[position:position + num] = part
### NEW APPROACH WITH PARALLELIZATION ###
handle = pool.apply_async(func=calculate, args=(input_array[position:position + num, :],))
handles.append(handle)
# finalize result
### OLD APPROACH WITH NO PARALLELIZATION ###
# final_result = result_array.reshape(ARRAY.shape)
### NEW APPROACH WITH PARALLELIZATION ###
final_result = [h.get() for h in handles]
final_result = np.concatenate(final_result, axis=0)
print 'Done!\nDuration (hh:mm:ss): {duration}'.format(duration=datetime.timedelta(seconds=time.time() - start))
代码运行并真正启动了我分配的数字进程,但比仅使用“原样”循环的旧方法花费的时间要长得多(3 秒与 1 分钟相比)。这里一定少了点什么。
【问题讨论】:
标签: python arrays multiprocessing