如何限制Docker容器可识别的CPU核心数量
问题原因
你之前使用的--cpus参数仅配置了CPU CFS带宽配额,本质是限制容器进程最多可使用的CPU时间片总和,不会修改容器内/proc/cpuinfo、/sys/devices/system/cpu等系统文件的内容,因此容器内的所有进程仍能识别到宿主机全部CPU核心,OpenBLAS等科学计算库默认会读取系统核心数启动对应数量的线程,最终触发CFS限流导致性能下降。
解决方案
1. 绑定固定CPU核心(最推荐,完全解决核心识别问题)
使用--cpuset-cpus参数指定容器可使用的物理核心编号,容器内将仅能看到你指定的核心,所有读取系统CPU信息的工具、类库都会自动识别到正确的核心数:
# 示例:限制容器仅使用0、1号核心,此时容器内只能看到2个核心 docker run --rm -it --cpuset-cpus="0,1" ubuntu:20.04
如果需要分配连续的核心,也可以写成--cpuset-cpus="0-3"的格式,代表使用0到3号共4个核心。
2. 无需绑定核心,直接限制科学计算库线程数
如果不希望把容器绑定到固定物理核心上,可以直接在启动容器时传入常用科学计算库的线程数环境变量,即使容器能看到所有核心,类库也只会启动指定数量的线程:
docker run --rm -it --cpus=2 \ -e OPENBLAS_NUM_THREADS=2 \ -e OMP_NUM_THREADS=2 \ -e MKL_NUM_THREADS=2 \ -e NUMEXPR_NUM_THREADS=2 \ ubuntu:20.04
上述环境变量覆盖了OpenBLAS、OpenMP、Intel MKL、NumExpr等绝大多数Python、R生态常用的科学计算库的默认线程配置。
3. 集群场景通用无侵入方案
如果是批量部署容器的场景,可以在宿主机部署lxcfs,通过lxcfs为容器挂载虚拟的/proc文件系统,容器会自动根据配置的CPU配额显示对应的核心数,无需修改容器启动命令或传入额外环境变量。
内容的提问来源于stack exchange,提问作者Craig
相关产品推荐
相关产品推荐

