4

我有一个函数,说它fun(a,b)非常昂贵,并返回一组数据。

我目前的方法如下:

a = np.linspace(0,100,300)
b = np.linspace(0,100,300)
A,B = np.meshgrid(a,b)
Y = np.zeros(A.shape)

for i,av in enumerate(a):
  for j, bv in enumerate(b):
    Y[i,j] = fun(av,bv)

(有点,我不得不把事情弄得一团糟以使它适合)。无论如何,这个过程需要很长时间,我想知道是否有一种直接的方法可以使用我的多核处理器来加快速度。

4

1 回答 1

8

有一个很棒的模块叫做multiprocessing,它是 python 标准库的一部分。它将在尽可能多的内核上生成进程,以利用其他 CPU。文档中有一个使用Pool对象的示例,下面是该示例的简化版本。它将计算 10 个数字的平方,为工作流程分配工作负载并显示结果。

简单的工作池

from multiprocessing import Pool

def f(x):
    return x*x

pool = Pool(processes=4)
print pool.map(f, range(10))

输出

[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

将您的问题分解为相同的结构,我遇到了更大的挑战。我必须创建一些中介功能来完成这项工作。我没有 numpy,所以我只是使用列表和字典来代替您输入的内容。您可以替换它们并试用代码。

更多涉及的场景

from multiprocessing import Pool
import time, pprint

def fun(av, bv):
    time.sleep(0.1)
    return (av, bv)

def data_stream(a, b):
    for i, av in enumerate(a):
        for j, bv in enumerate(b):
            yield (i, j), (av, bv)

def proxy(args):
    return args[0], fun(*args[1])

a = range(100, 400, 100)
b = range(100, 400, 100)
Y = {}

pool = Pool(processes=4)
results = pool.map(proxy, data_stream(a, b))
for k,v in results:
    Y[k] = v

pprint.pprint(Y)

输出

{(0, 0): (100, 100),
 (0, 1): (100, 200),
 (0, 2): (100, 300),
 (1, 0): (200, 100),
 (1, 1): (200, 200),
 (1, 2): (200, 300),
 (2, 0): (300, 100),
 (2, 1): (300, 200),
 (2, 2): (300, 300)}

表现

在示例中,我只是设置了一个 0.1 秒的虚拟延迟来模拟繁重的工作。但即使在这个例子中,如果你运行一个池,processes=1它在 0.950 秒内processes=4运行,它在 0.352 秒内运行。您可以通过多种不同方式使用多处理库 Pool 只是一种方式。您可能想要探索示例和实验。

在下面的评论之一中,提到了使用 pool.map 的 chunksize 参数来帮助提高性能。重要的是要大致了解幕后发生的事情,以真正掌握性能。基本上,您传递给其他进程的所有数据都需要经过腌制传递给未腌制使用的其他进程,然后结果通过相同的过程返回到主进程。这种进程间通信存在开销。实验时请记住这一点。

于 2012-12-02T19:45:02.720 回答