gpt4 book ai didi

python - 导入 scipy 会破坏 Python 中的多处理支持

转载 作者:太空狗 更新时间:2023-10-29 21:37:18 25 4
gpt4 key购买 nike

我遇到了一个我无法解释的奇怪问题。我希望有人能帮忙!

我正在运行 Python 2.7.3 和 Scipy v0.14.0,并尝试实现一些非常简单的多处理器算法,以使用 multiprocessing 模块加速我的代码。我已经设法使一个基本的示例起作用:

import multiprocessing
import numpy as np
import time
# import scipy.special


def compute_something(t):
a = 0.
for i in range(100000):
a = np.sqrt(t)
return a

if __name__ == '__main__':

pool_size = multiprocessing.cpu_count()
print "Pool size:", pool_size
pool = multiprocessing.Pool(processes=pool_size)

inputs = range(10)

tic = time.time()
builtin_outputs = map(compute_something, inputs)
print 'Built-in:', time.time() - tic

tic = time.time()
pool_outputs = pool.map(compute_something, inputs)
print 'Pool :', time.time() - tic

这运行正常,返回

Pool size: 8
Built-in: 1.56904006004
Pool : 0.447728157043

但是如果我取消注释 import scipy.special 行,我会得到:

Pool size: 8
Built-in: 1.58968091011
Pool : 1.59387993813

而且我可以看到只有一个核心在我的系统上工作。事实上,从 scipy 包中导入任何模块似乎都有这种效果(我试过好几种)。

有什么想法吗?我以前从未见过这样的案例,一个看似无害的导入会产生如此奇怪和意想不到的效果。

谢谢!

更新(一)

将 scipy 导入行移动到函数 compute_something 部分改善了问题:

Pool size: 8
Built-in: 1.66807389259
Pool : 0.596321105957

更新(二)

感谢@larsmans 在不同的系统上进行测试。使用 Scipy v.0.12.0 未确认问题。将此查询移动到 scipy 邮件列表并将发布任何答案。

最佳答案

经过大量挖掘和 posting an issue在 Scipy GitHub 网站上,我找到了解决方案。

在我开始之前,这已经很好地记录了 here - 我只给出一个概述。

这个问题与我使用的 Scipy 或 Numpy 版本有关。它起源于 Numpy 和 Scipy 用于各种线性代数例程的系统 BLAS 库。您可以通过运行来判断 Numpy 链接到哪些库

python -c 'import numpy; numpy.show_config()'

如果您在 Linux 中使用 OpenBLAS,您可能会发现 CPU affinity 设置为 1,这意味着一旦将这些算法导入 Python(通过 Numpy/Scipy),您最多可以访问 CPU 的一个核心。要对此进行测试,请在 Python 终端运行中

import os
os.system('taskset -p %s' %os.getpid())

如果 CPU affinity 返回为 f,则 ff,您可以访问多个内核。在我的例子中,它会像那样开始,但是在导入 numpy 或 scipy.any_module 时,它​​会切换到 1,因此我的问题。

我找到了两个解决方案:

更改 CPU 亲和性

你可以在main函数的顶部手动设置master进程的CPU affinity,这样代码看起来是这样的:

import multiprocessing
import numpy as np
import math
import time
import os

def compute_something(t):
a = 0.
for i in range(10000000):
a = math.sqrt(t)
return a

if __name__ == '__main__':

pool_size = multiprocessing.cpu_count()
os.system('taskset -cp 0-%d %s' % (pool_size, os.getpid()))

print "Pool size:", pool_size
pool = multiprocessing.Pool(processes=pool_size)

inputs = range(10)

tic = time.time()
builtin_outputs = map(compute_something, inputs)
print 'Built-in:', time.time() - tic

tic = time.time()
pool_outputs = pool.map(compute_something, inputs)
print 'Pool :', time.time() - tic

请注意,为 taskset 选择一个高于核心数的值似乎无关紧要 - 它只是使用最大可能的数量。

切换 BLAS 库

解决方案记录在 site上面链接。基本上:安装 libatlas 并运行 update-alternatives 将 numpy 指向 ATLAS 而不是 OpenBLAS。

关于python - 导入 scipy 会破坏 Python 中的多处理支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23537716/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com