ang*_*lly 6 python docker python-multiprocessing
我正在尝试在docker容器中测试python的多处理功能,但是即使成功创建了进程(我有8个CPU并创建了8个进程),它们也始终只占用一个物理CPU。这是我的代码:
from sklearn.externals.joblib.parallel import Parallel, delayed
import multiprocessing
import pandas
import numpy
from scipy.stats import linregress
import random
import logging
def applyParallel(dfGrouped, func):
retLst = Parallel(n_jobs=multiprocessing.cpu_count())(delayed(func)(group) for name, group in dfGrouped)
return pandas.concat(retLst)
def compute_regression(df):
result = {}
(slope,intercept,rvalue,pvalue,stderr) = linregress(df.date,df.value)
result["slope"] = [slope]
result["intercept"] = [intercept]
return pandas.DataFrame(result)
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logging.info("start")
random_list = []
for i in range(1,10000):
for j in range(1,100):
random_list.append({"id":i,"date":j,"value":random.random()})
df = pandas.DataFrame(random_list)
df = applyParallel(df.groupby('id'), compute_regression)
logging.info("end")
Run Code Online (Sandbox Code Playgroud)
当我像--cpus或--cpuset这样启动时,我尝试了多个docker选项,但它始终仅使用1个物理CPU。在Docker,python和OS中有问题吗?Docker版本为1.13.1
结果cpu_count():
>>> import multiprocessing
>>> multiprocessing.cpu_count()
8
Run Code Online (Sandbox Code Playgroud)
sna*_*hoe 10
来自https://docs.docker.com/get-started - “从根本上说,容器只不过是一个正在运行的进程,并对其应用了一些附加的封装功能,以使其与主机和其他容器隔离。”
Docker 在主机上运行。该主机(或虚拟机)具有一定数量的物理(或虚拟)CPU。multiprocessing.cpu_count()在您的情况下显示 8的原因是因为这是您的系统拥有的 CPU 数量。使用 docker 选项,例如--cpus或--cpuset-cpus不改变您机器的硬件,这cpu_count()就是报告的内容。
在我当前的系统上:
# native
$ python -c 'import multiprocessing as mp; print(mp.cpu_count())'
12
# docker
$ docker run -it --rm --cpus 1 --cpuset-cpus 0 python python -c 'import multiprocessing as mp; print(mp.cpu_count())'
12
Run Code Online (Sandbox Code Playgroud)
来自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。
(Docker 的文档中还介绍了许多其他与 CPU 相关的选项。)
这是一个较小的代码示例:
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))
Run Code Online (Sandbox Code Playgroud)
在本地和在 docker 中运行它会记录如下行:
[21/LokyProcess-2] fn1(81); cpu# 11
[28/LokyProcess-9] fn1(82); cpu# 6
[29/LokyProcess-10] fn1(83); cpu# 2
[31/LokyProcess-12] fn1(84); cpu# 0
[22/LokyProcess-3] fn1(85); cpu# 3
[23/LokyProcess-4] fn1(86); cpu# 1
[20/LokyProcess-1] fn1(87); cpu# 7
[25/LokyProcess-6] fn1(88); cpu# 3
[27/LokyProcess-8] fn1(89); cpu# 4
[21/LokyProcess-2] fn1(90); cpu# 9
[28/LokyProcess-9] fn1(91); cpu# 10
[26/LokyProcess-7] fn1(92); cpu# 11
[22/LokyProcess-3] fn1(95); cpu# 9
[29/LokyProcess-10] fn1(93); cpu# 2
[24/LokyProcess-5] fn1(94); cpu# 10
[23/LokyProcess-4] fn1(96); cpu# 1
[20/LokyProcess-1] fn1(97); cpu# 9
[23/LokyProcess-4] fn1(98); cpu# 1
[27/LokyProcess-8] fn1(99); cpu# 4
[21/LokyProcess-2] fn1(100); cpu# 5
Run Code Online (Sandbox Code Playgroud)
请注意,所有 12 个 CPU 都在我的系统上使用。请注意
运行相同的程序docker run --cpus 1 ...仍然会导致所有 12 个进程都使用所有 12 个 CPU,就像不存在 --cpus 参数一样。它只是限制了 docker 允许使用的总 CPU 时间的百分比。
运行相同的程序docker run --cpusets-cpus 0-1 ...将导致所有 12 个启动的进程只使用 2 个物理 CPU:
[11/LokyProcess-2] fn1(35); cpu# 0
[11/LokyProcess-2] fn1(36); cpu# 0
[12/LokyProcess-3] fn1(37); cpu# 1
[11/LokyProcess-2] fn1(38); cpu# 0
[15/LokyProcess-6] fn1(39); cpu# 1
[17/LokyProcess-8] fn1(40); cpu# 0
[11/LokyProcess-2] fn1(41); cpu# 0
[10/LokyProcess-1] fn1(42); cpu# 1
[11/LokyProcess-2] fn1(43); cpu# 1
[13/LokyProcess-4] fn1(44); cpu# 1
[12/LokyProcess-3] fn1(45); cpu# 0
[12/LokyProcess-3] fn1(46); cpu# 1
Run Code Online (Sandbox Code Playgroud)
要回答“他们总是只占用一个物理 CPU”这一说法——只有当--cpusets-cpusarg 恰好/只有 1 个 CPU 时,这才是正确的。
(作为旁注 - 以示例中的方式设置日志记录的原因是因为joblib 中的一个开放错误。)
multiprocessing.cpu_count()在我的机器上给出2而不通过--cpu选项
前往https://docs.docker.com/engine/admin/resource_constraints/#cpu了解有关docker容器资源的更多信息
| 归档时间: |
|
| 查看次数: |
4957 次 |
| 最近记录: |