使用scatter / gather进行Ipyparallel缓慢执行

时间:2016-03-26 18:48:14

标签: python ipython mpi jupyter-notebook ipython-parallel

上下文:我有一个分散在我的引擎中的数组(此时有4个引擎),想要将一个函数应用于数组中的每个点,以进行任意数量的迭代并收集来自引擎的结果数组并对其进行分析。

例如,我有分散的数据点数组和每个数据点的迭代次数:

data_points = range(16)
iterations = 10
dview.scatter('points', data_points)

我有一个用户提供的功能,它被推送到引擎:

def user_supplied_function(point):
    return randint(0, point)

dview.push(dict(function_one = user_supplied_function))

我的结果列表和并行执行:

result_list = []
for i in range(iterations):
    %px engine_result = [function_one(j) for j in points]
    result_list.append(dview.gather('engine_result'))

问题:这是有效的,我从引擎中得到了我想要的结果,但随着迭代次数的增加,循环执行的时间越来越长。到50点的1000次迭代需要超过15秒才能完成。而此任务的顺序版本只需不到一秒钟。

知道可能导致这种情况的原因是什么?可能是来自gather()的消息的开销吗?如果是这样,任何人都可以建议任何解决方案?

1 个答案:

答案 0 :(得分:0)

想出来。毕竟,这是gather().append()的开销。最简单的解决方法是在引擎完成工作后gather(),而不是每次迭代都这样做。

<强>解决方案

%autopx
engine_result = []
for i in xrange(iterations):
    engine_result += [[function_one(j) for j in points]]
%autopx
result_list = list(dview.gather('engine_result'))

然而,这会导致结果列表格式不正确的列表,其中每个引擎的结果彼此相邻放置,而不是按迭代次数排序。以下命令分发列表并展平每次迭代的子列表。

gathered_list = [None] * iterations
gathered_list = [[result_list[j * iterations + i] for j in xrange(len(result_list) / iterations)] for i in xrange(iterations)]
gathered_list = [reduce(lambda x, y: x.extend(y) or x, z) for z in gathered_list]