spr*_*ksh 0 python multiprocessing gil
假设我在多核 CPU(比如 4)上运行多个 python 进程(不是线程)。GIL 是流程级别,因此特定流程中的 GIL 不会影响其他流程。
我的问题是,一个进程中的 GIL 是只占用 4 个内核中的一个内核,还是会占用所有 4 个内核?
如果一个进程同时锁定所有内核,那么多处理应该不会比 Python 中的多线程更好。如果不是,如何将内核分配给各种进程?
作为观察,在我的 8 核系统中(由于超线程是 4*2),当我运行单个 CPU 绑定进程时,8 个核中有 4 个的 CPU 使用率上升。
简化这个:
在 4 核 CPU 上运行的 4 个 python 线程(在一个进程中)将比执行相同工作的单线程花费更多时间(考虑到工作完全受 CPU 限制)。4 个不同的进程做这么多的工作会减少近 4 倍的时间吗?
Python 不做任何事情来将进程或线程绑定到核心;它只是将事情留给操作系统。当您生成一堆独立的进程(或线程,但在 Python 中很难做到)时,操作系统的调度程序将快速有效地将它们分散到您的内核中,而无需您或 Python 做任何事情(除非非常糟糕的病态案例)。
GIL 在这里不相关。稍后我会讨论这个问题,但首先让我们解释一下什么是相关的。
你没有8核。您有 4 个内核,每个内核都是超线程的。
现代内核具有大量“超标量”容量。通常,在流水线中排队的指令不够独立,无法充分利用该容量。超线程的作用是允许内核在发生这种情况时从第二条流水线中获取其他指令,这实际上保证是独立的。但它只允许,而不是要求,因为在某些情况下(CPU 通常可以比你更好地决定),缓存局部性的成本会比并行性的收益更糟糕。
因此,根据您运行的实际负载,使用四个超线程内核,您可能会获得 800% 的 CPU 使用率,或者您可能只会获得 400%,或者(通常)介于两者之间。
我假设您的系统配置为向用户空间报告 8 个核心而不是 4 个核心,因为这是默认设置,并且您至少有 8 个进程或一个具有默认 proc 计数和至少 8 个任务的池 - 显然,如果没有确实如此,您不可能获得 800% 的 CPU 使用率……
我还假设您没有使用显式锁、其他同步、Manager对象或其他任何会序列化您的代码的东西。如果这样做,显然您无法获得完全并行性。
而且我还假设您没有使用(可变的)共享内存,就像multiprocessing.Array每个人都写入的那样。这可能会导致缓存和页面冲突,这几乎与显式锁一样糟糕。
那么,与 GIL 有什么关系呢?好吧,如果你在一个进程中运行多个线程,并且它们都是 CPU 密集型的,并且它们大部分时间都在运行 Python 代码(而不是花费大部分时间运行 numpy 操作来释放GIL),一次只能运行一个线程。你可以看到:
但是您不是在运行多个线程,而是在运行单独的进程,每个进程都有自己完全独立的 GIL。这就是为什么您会看到 100% 的四个内核而不是一个内核。
| 归档时间: |
|
| 查看次数: |
3347 次 |
| 最近记录: |