首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python:多处理,8/24内核加载

Python:多处理,8/24内核加载
EN

Stack Overflow用户
提问于 2015-07-09 14:16:59
回答 2查看 2.6K关注 0票数 11

我有一台带有24物理核的机器--(至少有人这么告诉我),运行Debian:Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.68-1+deb7u1 x86_64 GNU/Linux。这似乎是正确的:

代码语言:javascript
复制
usr@machine:~/$ cat /proc/cpuinfo  | grep processor
processor   : 0
processor   : 1
<...>
processor   : 22
processor   : 23

我在尝试用Python的multiprocessing.pool.Pool加载所有内核时遇到了一些问题。我使用了Pool(processes=None);文档说,如果提供None,Python就使用None

唉,只有8个内核100%加载了,其他内核仍然处于空闲状态(我使用htop来监视CPU负载)。我认为我无法正确地编写Pools,并试图“手动”调用24个进程:

代码语言:javascript
复制
print 'Starting processes...'
procs = list()
for param_set in all_params:  # 24 items
    p = Process(target=_wrap_test, args=[param_set])
    p.start()
    procs.append(p)

print 'Now waiting for them.'
for p in procs:
    p.join()

我从我开始的过程中收到了24条“问候”信息:

代码语言:javascript
复制
Starting processes...
Executing combination: Session len: 15, delta: 10, ratio: 0.1, eps_relabel: 0.5, min_pts_lof: 5, alpha: 0.01, reduce: 500
< ... 22 more messages ... >
Executing combination: Session len: 15, delta: 10, ratio: 0.1, eps_relabel: 0.5, min_pts_lof: 7, alpha: 0.01, reduce: 2000
Now waiting for them.

但是,仍然只加载了8个核心

我在这里阅读过,这样可能会出现numpy、OpenBLAS和多核执行方面的问题。我就是这样开始我的代码的:

代码语言:javascript
复制
OPENBLAS_MAIN_FREE=1 python -m tests.my_module

在进口之后,我做到了:

代码语言:javascript
复制
os.system("taskset -p 0xff %d" % os.getpid())

所以,这里有一个问题:我应该怎么做才能使所有的核心都有100%的负载?这只是我糟糕的Python用法,还是与多核计算机上的操作系统限制有关?

更新的:另一个有趣的事情是htop输出中的一些不一致。如果您查看上面的图像,您将看到CPU负载栏下面的表显示了超过8个核心的30-50%的负载,这与加载条的说法完全不同。然后,top似乎同意这些条:8个核心100%加载,其他空闲。

再次更新:

所以,当我在所有导入之后添加os.system("taskset -p 0xff %d" % os.getpid())行时,我都使用了os.system("taskset -p 0xff %d" % os.getpid())。我不得不承认,当我这么做的时候,我没有想太多,尤其是在我读了这篇文章之后:

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

我是个简单的人。我看到“工作像一个魅力”,我复制和粘贴。无论如何,在处理我的代码时,我最终删除了这一行。之后,我的代码开始在所有24个核心上执行,用于“手动”Process启动场景。对于Pool场景,同样的问题仍然存在,不管是否使用了亲和技巧。

我不认为这是一个真正的答案,因为我不知道什么是Pool的问题,但至少我设法使所有的核心满负荷。谢谢!

EN

回答 2

Stack Overflow用户

发布于 2015-07-11 10:59:19

即使你解决了这个问题,我也会尽力解释一下,澄清这些想法。

对于我所读到的,numpy做了很多“魔法”来提高性能。其中一个魔术是设置进程的CPU亲和力。

CPU关联是对OS调度程序的优化。它基本上强制一个给定的进程总是在同一个CPU核心上运行。

这提高了性能,减少了CPU缓存失效的次数,并增加了引用局部性的好处。对于高计算量的任务,这些因素确实很重要。

我不喜欢numpy的一个事实,那就是它暗含着这一切。经常令人困惑的开发人员。

您的进程没有在所有核心上运行,这是因为numpy在导入模块时设置了与父进程的关联。然后,当您生成新进程时,亲缘关系将被继承,从而导致所有进程争夺少数核心,而不是高效地使用所有可用的核心。

os.system("taskset -p 0xff %d" % os.getpid())命令指示操作系统在解决问题的所有核心上设置关联。

如果你想看到它在池上工作,你可以做下面的技巧。

代码语言:javascript
复制
import os
from multiprocessing import Pool


def set_affinity_on_worker():
    """When a new worker process is created, the affinity is set to all CPUs"""
    print("I'm the process %d, setting affinity to all CPUs." % os.getpid())
    os.system("taskset -p 0xff %d" % os.getpid())


if __name__ == '__main__':
    p = Pool(initializer=set_affinity_on_worker)
    ...
票数 4
EN

Stack Overflow用户

发布于 2018-05-01 16:51:56

os.system("taskset -p 0xff %d" % os.getpid())中,0xff本质上是一个十六进制位掩码,对应于111111。位掩码中的每个位对应于CPU核心。位值1表示可以在相应的CPU核上执行该进程。因此,要在24个核上运行,您应该使用0 0xffffff掩码,而不是0 0xff。

正确命令:

代码语言:javascript
复制
os.system("taskset -p 0xffffff %d" % os.getpid())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31320194

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档