为什么在导入numpy之后,多处理只使用一个核心?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (27)

我不确定这是否更多地被视为操作系统问题,但我想在这里问一下,以防有人从Python端了解一些情况。

我一直在尝试并行处理一个CPU很重的for循环使用joblib但我发现,与其将每个工作进程分配到不同的核心,不如将它们分配到相同的核心上,而没有提高性能。

这里有一个很小的例子。

from joblib import Parallel,delayed
import numpy as np

def testfunc(data):
    # some very boneheaded CPU work
    for nn in xrange(1000):
        for ii in data[0,:]:
            for jj in data[1,:]:
                ii*jj

def run(niter=10):
    data = (np.random.randn(2,100) for ii in xrange(niter))
    pool = Parallel(n_jobs=-1,verbose=1,pre_dispatch='all')
    results = pool(delayed(testfunc)(dd) for dd in data)

if __name__ == '__main__':
    run()

我在这里看到的是htop当此脚本运行时:

我在一个有4个核心的笔记本电脑上运行Ubuntu12.10(3.5.0-26)。显然joblib.Parallel是否为不同的工作人员生成单独的进程,但我是否可以让这些进程在不同的核心上执行?

提问于
用户回答回答于

事实证明,某些Python模块(numpyscipytablespandasskimage...)。据我所知,这个问题似乎是由它们与多线程OpenBLAS库的链接具体造成的。

解决方法是使用以下方法重置任务关联

os.system("taskset -p 0xff %d" % os.getpid())

在模块导入之后粘贴了这一行,我的示例现在运行在所有核心上:

到目前为止,我的经验是,这似乎并没有对numpy的性能,尽管这可能是机器和任务的特定特性。

还有两种方法可以禁用OpenBLAS本身的CPU关联重置行为。在运行时,可以使用环境变量。OPENBLAS_MAIN_FREE(或GOTOBLAS_MAIN_FREE),例如

OPENBLAS_MAIN_FREE=1 python myscript.py

或者,如果要从源代码编译OpenBLAS,则可以在构建时通过编辑Makefile.rule包含行

NO_AFFINITY=1
用户回答回答于

Python 3如下:

>>> import os
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}
>>> os.sched_setaffinity(0, {1, 3})
>>> os.sched_getaffinity(0)
{1, 3}
>>> x = {i for i in range(10)}
>>> x
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
>>> os.sched_setaffinity(0, x)
>>> os.sched_getaffinity(0)
{0, 1, 2, 3}

扫码关注云+社区