如何在多处理中将CPU内核分配给python进程?

时间:2018-04-24 04:53:51

标签: python multiprocessing gil

让我们说我在多核CPU(比如4)上运行多个python进程(而不是线程)。 GIL是流程级别,因此特定流程中的GIL不会影响其他流程。

我的问题是,如果一个进程中的GIL只占用4个内核中的单个内核,还是会占用所有4个内核?

如果一个进程一次锁定所有核心,那么多处理不应该比python中的多线程更好。如果不是如何将核分配给各种进程?

  

作为一个观察,我的系统是8核(4 * 2因为   超线程),当我运行单个CPU绑定进程时,CPU使用率   8个核心中有4个上升。

简化:

在4核CPU上运行的4个python线程(在一个进程中)将花费比单线程执行相同工作更多的时间(考虑到工作完全受CPU限制)。将4个不同的过程完成这项工作量会减少4倍的时间吗?

2 个答案:

答案 0 :(得分:1)

Python对bind processes or threads to cores没有任何作用;它只是留给操作系统。当你产生一堆独立的进程(或线程,但在Python中更难做)时,操作系统的调度程序将快速有效地将它们分散到你的核心,而不需要你或Python需要做任何事情(除了非常糟糕的病态)例)。

GIL与此无关。我稍后会谈到这一点,但首先让我们解释 相关的内容。

您没有8个核心。您有4个核心,每个核心都是hyperthreaded

现代核心拥有大量“超标量”容量。通常,在管道中排队的指令不够独立,无法充分利用该容量。超线程的作用是允许内核在发生这种情况时从第二个管道获取其他指令,这实际上保证是独立的。但它只允许,而不是要求,因为在某些情况下(CPU通常可以比你更好地决定),缓存局部性的成本将比并行性的收益更差。

因此,根据您运行的实际负载,使用四个超线程内核,您可能会获得800%的CPU使用率,或者您可能只能获得400%,或者(经常)介于两者之间。

我假设您的系统配置为向用户空间报告8个内核而不是4个,因为这是默认设置,并且您至少有8个进程或具有默认进程计数的池和至少8个任务 - 显然如果没有一个是真的,你就不可能获得800%的CPU使用率......

我还假设您没有使用显式锁,其他同步,Manager对象或其他任何可以序列化代码的对象。如果你这样做,显然你无法获得完全的并行性。

而且我还假设你没有使用(可变的)共享内存,就像每个人写的multiprocessing.Array一样。这可能导致缓存和页面冲突几乎与显式锁定一样糟糕。

那么,与GIL的交易是什么?好吧,如果你在一个进程中运行多个线程,并且它们都受CPU限制,并且它们都花费大部分时间来运行Python代码(相反,比如说,花费大部分时间来运行numpy操作来释放GIL),一次只能运行一个线程。你可以看到:

  • 单核上100%持续,其余为0%。
  • 两个或多个核心之间100%乒乓,其余核心为0%。
  • 两个或多个核心之间100%乒乓,而其余核心为0%,但有一些明显的重叠,其中两个核心同时超过0%。最后一个可能看起来像并行,但它不是 - 这只是切换开销变得可见。

但是你没有运行多个线程,你正在运行单独的进程,每个进程都有自己完全独立的GIL。这就是为什么你看到四个核心是100%而不是一个核心。

答案 1 :(得分:0)

CPU / CPU核心分配的处理由操作系统处理。