从https://docs.docker.com/get-started - "基本上,容器只是一个正在运行的进程,加上一些封装功能,以使其与主机和其他容器隔离开来。"
Docker运行在主机上。该主机(或虚拟机)有一定数量的物理(或虚拟)CPU。在您的情况下,multiprocessing.cpu_count()
显示8的原因是这是您系统的CPU数量。使用docker选项,如 --cpus
或 --cpuset-cpus
不会改变您机器的硬件,这就是 cpu_count()
报告的内容。
在我的当前系统上:
$ python -c 'import multiprocessing as mp; print(mp.cpu_count())'
12
$ docker run -it --rm --cpus 1 --cpuset-cpus 0 python python -c 'import multiprocessing as mp; print(mp.cpu_count())'
12
从
https://docs.docker.com/config/containers/resource_constraints/#cpu - “默认情况下,每个容器对主机的CPU周期的访问是无限的。” 但是您可以使用
--cpus
或
--cpuset-cpus
等选项限制容器。
--cpus
可以是浮点数,最多达到可用物理CPU数量。您可以将此数字视为分数中的分子
<--cpus arg>
/
<physical CPU's>
。如果您有8个物理CPU,并指定
--cpus 4
,则告诉docker不要使用超过总CPU数量的50%(4/8)。
--cpus 1.5
将使用18.75%(1.5/8)。
--cpuset-cpus
实际上限制了要使用哪些特定的物理/虚拟CPU。
(还有许多其他与CPU相关的选项在docker文档中有介绍。)
这是一个较小的代码示例:
import logging
import multiprocessing
import sys
import psutil
from joblib.parallel import Parallel, delayed
def get_logger():
logger = logging.getLogger()
if not logger.hasHandlers():
handler = logging.StreamHandler(sys.stdout)
formatter = logging.Formatter("[%(process)d/%(processName)s] %(message)s")
handler.setFormatter(formatter)
handler.setLevel(logging.DEBUG)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
return logger
def fn1(n):
get_logger().debug("fn1(%d); cpu# %d", n, psutil.Process().cpu_num())
if __name__ == "__main__":
get_logger().debug("main")
Parallel(n_jobs=multiprocessing.cpu_count())(delayed(fn1)(n) for n in range(1, 101))
在本地和Docker中运行此程序将记录以下日志行:
[21/LokyProcess-2] fn1(81)
[28/LokyProcess-9] fn1(82)
[29/LokyProcess-10] fn1(83)
[31/LokyProcess-12] fn1(84)
[22/LokyProcess-3] fn1(85)
[23/LokyProcess-4] fn1(86)
[20/LokyProcess-1] fn1(87)
[25/LokyProcess-6] fn1(88)
[27/LokyProcess-8] fn1(89)
[21/LokyProcess-2] fn1(90)
[28/LokyProcess-9] fn1(91)
[26/LokyProcess-7] fn1(92)
[22/LokyProcess-3] fn1(95)
[29/LokyProcess-10] fn1(93)
[24/LokyProcess-5] fn1(94)
[23/LokyProcess-4] fn1(96)
[20/LokyProcess-1] fn1(97)
[23/LokyProcess-4] fn1(98)
[27/LokyProcess-8] fn1(99)
[21/LokyProcess-2] fn1(100)
请注意,我的系统上所有12个CPU均在使用中。请注意:
- 同一物理CPU被多个进程使用(进程#22和25使用cpu#3)
- 一个单独的进程可以使用多个CPU(进程#21使用CPU#11和9)
使用
docker run --cpus 1 ...
运行相同的程序仍然会导致所有12个CPU被所有12个已启动的进程使用,就像--cpus参数不存在一样。它只限制了docker允许使用的总CPU时间的百分比。
使用
docker run --cpusets-cpus 0-1 ...
运行相同的程序将导致所有12个已启动的进程仅使用2个物理CPU:
[11/LokyProcess-2] fn1(35)
[11/LokyProcess-2] fn1(36)
[12/LokyProcess-3] fn1(37)
[11/LokyProcess-2] fn1(38)
[15/LokyProcess-6] fn1(39)
[17/LokyProcess-8] fn1(40)
[11/LokyProcess-2] fn1(41)
[10/LokyProcess-1] fn1(42)
[11/LokyProcess-2] fn1(43)
[13/LokyProcess-4] fn1(44)
[12/LokyProcess-3] fn1(45)
[12/LokyProcess-3] fn1(46)
回答声明"他们总是只使用一个物理CPU" - 只有当
--cpusets-cpus
参数恰好/仅为1个CPU时才为真。
(顺便提一句--本例中设置日志的原因是因为joblib存在一个
未解决的bug。)
docker run
的选项不会覆盖它,您只能使用虚拟机允许使用的数量。 - Graham Dumpletonprint(multiprocessing.cpu_count())
并将结果添加到你的问题中吗? - hansaplast