我想了解multiprocessing.Pool是如何工作的,并且我开发了一个说明我的问题的最小例子。简而言之,我使用pool.map通过以下示例Dead simple example of using Multiprocessing Queue, Pool and Locking并行化在阵列上运行的CPU绑定函数。当我遵循这种模式时,我只获得了4核心的适度加速,但是如果我将数组手动分块为num_threads,然后在分块上使用pool.map,我发现加速因子大大超过了4x,这使得无感觉到我。要遵循的细节。使用python多重处理优化一个简单的CPU绑定函数
一,函数定义。
def take_up_time():
n = 1e3
while n > 0:
n -= 1
def count_even_numbers(x):
take_up_time()
return np.where(np.mod(x, 2) == 0, 1, 0)
现在定义我们将进行基准测试的函数。
首先,在连续运行的功能:
def serial(arr):
return np.sum(map(count_even_numbers,arr))
现在使用Pool.map在“标准”的方式功能:
def parallelization_strategy1(arr):
num_threads = multiprocessing_count()
pool = multiprocessing.Pool(num_threads)
result = pool.map(count_even_numbers,arr)
pool.close()
return np.sum(result)
def split_padded(a,n):
""" Simple helper function for strategy 2
"""
padding = (-len(a))%n
if padding == 0:
return np.split(a, n)
else:
sub_arrays = np.split(np.concatenate((a,np.zeros(padding))),n)
sub_arrays[-1] = sub_arrays[-1][:-padding]
return sub_arrays
def parallelization_strategy2(arr):
num_threads = multiprocessing_count()
sub_arrays = split_padded(arr, num_threads)
pool = multiprocessing.Pool(num_threads)
result = pool.map(count_even_numbers,sub_arrays)
pool.close()
return np.sum(np.array(result))
这里是我的阵列输入:
npts = 1e3
arr = np.arange(npts)
现在我用的IPython%timeit函数运行我的计时,并为1E3点我得到以下几点:
串行:10个循环,最好的3:98.7毫秒每循环
parallelization_strategy1:10个循环,最好的3:每次循环77.7毫秒
parallelizat ion_strategy2:10个循环,最好的3:22毫秒每循环
由于我有4个内核,策略1是令人失望的适度的加速,和策略2是可疑大于最大4倍加速比更大。
当我增加NPTS到1E4,结果是更加令人困惑:
串行:1个循环,最好的3:每圈967毫秒
parallelization_strategy1:1个循环,最好的每循环3:596毫秒
parallelization_strategy2:10循环,最好是3:22。每个环路9毫秒
所以混乱的两个来源是:
策略2比幼稚理论极限
出于某种原因方式更快,%timeit与NPTS = 1E4仅触发1循环为串行和策略1,但10策略2循环。
2016-03-16
aph
+0
你比较了不同策略的结果吗? –