gpt4 book ai didi

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

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

我有一台机器有 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 使用 cpu_count()

唉,只有 8 个核心被 100% 加载,其他核心保持空闲状态(我使用 htop 来监控 CPU 负载)。我认为我无法正确 cooking 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 个核心:

enter image description here

我在这里读到,numpy、OpenBLAS 和多核执行可能存在问题。这就是我开始编写代码的方式:

OPENBLAS_MAIN_FREE=1 python -m tests.my_module

在我完成所有导入之后:

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

那么,问题来了:我应该怎么做才能让所有内核都达到 100% 负载?这仅仅是我对 Python 的不当使用,还是与多核机器上的操作系统限制有关?

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

再次更新:

我用了this rather popular post在 SO 上,当我在所有导入后添加 os.system("taskset -p 0xff %d"% os.getpid()) 行时。我不得不承认,当时我并没有想太多,尤其是在阅读了这篇文章之后:

With this line pasted in after the module imports, my example now runs on all cores

我是一个简单的人。我看到“作品很有魅力”,我复制并粘贴。不管怎样,在玩我的代码时,我最终删除了这一行。之后,我的代码开始在“手动”Process 启动场景的所有 24 个内核上执行。对于 Pool 场景,无论是否使用关联技巧,同样的问题仍然存在。

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

最佳答案

即使您解决了问题,我也会尝试对其进行解释以阐明思路。

就我所读到的内容而言,numpy 做了很多“魔术”来提高性能。魔术技巧之一是设置进程的 CPU 亲和性。

CPU 亲和性是操作系统调度程序的优化。它基本上强制给定进程始终在同一个 CPU 内核上运行。

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

我不喜欢 numpy 的一点是它隐含地完成了所有这些工作。经常让开发人员感到困惑。

您的进程未在所有内核上运行的事实是由于 numpy 在您导入模块时设置了与父进程的关联。然后,当您生成新进程时,亲和性会被继承,导致所有进程争夺少数核心,而不是有效地使用所有可用核心。

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

如果你想看到它在 Pool 上工作,你可以使用以下技巧。

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)
...

关于Python:多处理,8/24 核加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31320194/

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