我有一台带有24物理核的机器--(至少有人这么告诉我),运行Debian:Linux 3.2.0-4-amd64 #1 SMP Debian 3.2.68-1+deb7u1 x86_64 GNU/Linux。这似乎是正确的:
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个进程:
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条“问候”信息:
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和多核执行方面的问题。我就是这样开始我的代码的:
OPENBLAS_MAIN_FREE=1 python -m tests.my_module在进口之后,我做到了:
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的问题,但至少我设法使所有的核心满负荷。谢谢!
发布于 2015-07-11 10:59:19
即使你解决了这个问题,我也会尽力解释一下,澄清这些想法。
对于我所读到的,numpy做了很多“魔法”来提高性能。其中一个魔术是设置进程的CPU亲和力。
CPU关联是对OS调度程序的优化。它基本上强制一个给定的进程总是在同一个CPU核心上运行。
这提高了性能,减少了CPU缓存失效的次数,并增加了引用局部性的好处。对于高计算量的任务,这些因素确实很重要。
我不喜欢numpy的一个事实,那就是它暗含着这一切。经常令人困惑的开发人员。
您的进程没有在所有核心上运行,这是因为numpy在导入模块时设置了与父进程的关联。然后,当您生成新进程时,亲缘关系将被继承,从而导致所有进程争夺少数核心,而不是高效地使用所有可用的核心。
os.system("taskset -p 0xff %d" % os.getpid())命令指示操作系统在解决问题的所有核心上设置关联。
如果你想看到它在池上工作,你可以做下面的技巧。
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)
...发布于 2018-05-01 16:51:56
在os.system("taskset -p 0xff %d" % os.getpid())中,0xff本质上是一个十六进制位掩码,对应于111111。位掩码中的每个位对应于CPU核心。位值1表示可以在相应的CPU核上执行该进程。因此,要在24个核上运行,您应该使用0 0xffffff掩码,而不是0 0xff。
正确命令:
os.system("taskset -p 0xffffff %d" % os.getpid())https://stackoverflow.com/questions/31320194
复制相似问题