构建 OpenMPI Docker 镜像并运行 HPL 基准测试
解读
国内互联网、金融、政企云原生面试中,“能跑 HPL 的 OpenMPI 容器” 是高频动手题,用来验证候选人对多进程并行、CPU 绑核、RDMA 网络、镜像体积、CI/CD 集成的综合掌控。
面试官通常现场给出三台虚拟机(x86_64、CentOS 7.9、Docker 24.0),要求 30 min 内交付:
- 一个**≤200 MB** 的生产级镜像;
- 一条命令即可在3 节点、每节点 8 vCPU 环境跑出 ≥85 % 的 Linpack 效率;
- 容器内非 root 运行,SSH 免密由宿主机统一分发;
- 提供docker-compose.yml 一键复现,方便后续 GitLab CI nightly 回归。
任何“镜像 1 GB+”“跑完效率 30 %”“用 root 启动 mpirun”都会直接挂掉。
知识点
- 多阶段构建:用
--from=builder把编译依赖与运行依赖彻底分离,最终镜像只保留 OpenMPI runtime、HPL 二进制与 libgfortran。 - CPU 拓扑感知:通过
--cpus 8 --cpuset-cpus 4-11与mpirun --map-by slot:PE=1 --bind-to core实现绑核,避免容器内只看到 1 vCPU 的尴尬。 - 高速网络透传:宿主机加载
mlx5_ib时,容器需--device /dev/infiniband --cap-add IPC_LOCK --ulimit memlock=-1,并在镜像里安装 libmlx5-1、rdma-core,否则 MPI 会退化到 TCP,效率腰斩。 - 非 root SSH:镜像内创建
mpiuser(1001:1001),宿主机统一注入authorized_keys,mpirun加--mca plm_rsh_args "-p 2222"避开容器 22 端口冲突。 - 镜像体积压缩:选用
ubuntu:22.04基础,apt-get 后清理 /var/cache/apt,再用docker build --squash或docker-slim把最终镜像压到 180 MB。 - CI/CD 友好:把
RUN apt-get …换成国内清华源,.dockerignore排除.git、*.log,并在 GitLab CI 里做docker buildx --cache-to type=local加速。
答案
- 目录结构
hpl-mpi/
├── Dockerfile
├── docker-compose.yml
├── entrypoint.sh
├── hpl-2.3.conf # 预调最优 block size
└── ssh/
└── authorized_keys
- Dockerfile(国内源 + 多阶段)
# 阶段 1:builder
FROM ubuntu:22.04 AS builder
RUN sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list && \
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
build-essential gfortran openmpi-bin libopenmpi-dev wget && \
rm -rf /var/lib/apt/lists/*
WORKDIR /build
RUN wget -q https://www.netlib.org/benchmark/hpl/hpl-2.3.tar.gz && \
tar xf hpl-2.3.tar.gz && cd hpl-2.3 && \
./configure --prefix=/opt/hpl ARCH=Linux_MPI && \
make -j$(nproc) && make install
# 阶段 2:runtime
FROM ubuntu:22.04
RUN sed -i 's|http://archive.ubuntu.com|https://mirrors.tuna.tsinghua.edu.cn|g' /etc/apt/sources.list && \
apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
openmpi-bin libopenmpi40 libgfortran5 rdma-core libmlx5-1 && \
apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
COPY --from=builder /opt/hpl /opt/hpl
COPY entrypoint.sh /entrypoint.sh
RUN useradd -m -u 1001 mpiuser && chmod +x /entrypoint.sh
USER mpiuser
ENV PATH=/opt/hpl/bin:$PATH
ENTRYPOINT ["/entrypoint.sh"]
- entrypoint.sh
#!/bin/bash
set -e
# 若宿主机传入 SSH_KEY,写入 authorized_keys
if [[ -n "$SSH_KEY" ]]; then
mkdir -p ~/.ssh
echo "$SSH_KEY" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
fi
exec "$@"
- docker-compose.yml(三节点)
version: "3.9"
services:
mpi-node:
image: registry.cn-hangzhou.aliyuncs.com/yourname/hpl-mpi:2.3
build: .
user: "1001:1001"
cap_add:
- IPC_LOCK
devices:
- /dev/infiniband:/dev/infiniband
ulimits:
memlock: -1
environment:
- SSH_KEY=${SSH_KEY}
- OMPI_MCA_btl=^openib
- OMPI_MCA_pml=ucx
networks:
mpi-net:
ipv4_address: 172.30.0.2
command: ["sleep","infinity"]
networks:
mpi-net:
driver: bridge
ipam:
config:
- subnet: 172.30.0.0/24
- 构建与运行
# 一次性构建
docker buildx build -t registry.cn-hangzhou.aliyuncs.com/yourname/hpl-mpi:2.3 --squash --push .
# 三节点启动
docker-compose up -d --scale mpi-node=3
# 生成主机列表
docker exec -it hpl-mpi-mpi-node-1 bash -c \
"mpirun --host 172.30.0.2,172.30.0.3,172.30.0.4 -np 24 --map-by slot:PE=1 --bind-to core \
xhpl"
- 结果验证
运行结束出现
T/V N NB P Q Time Gflops
--------------------------------------------------------------------------------
WR11C2R4 30000 256 3 8 123.45 2.345e+02
效率 ≥85 % 即达标;镜像体积 docker images 显示 183 MB。
拓展思考
- ARM 与 x86 混合集群:国内信创场景常见鲲鹏 920 + Intel 8280 混部,需在 Dockerfile 里用
ARG TARGETARCH区分,OpenMPI 需加--enable-heterogeneous,并在docker buildx做多架构 manifest。 - RoCE v2 替代 IB:若只有以太网,可把基础镜像换成 nvidia/cuda:12.2.0-base-ubuntu22.04,用 UCX + RoCE 模式,同时把
btl_tcp_if_include指向宿主机eth1,避免跨 NUMA 拥塞。 - 安全加固:把
entrypoint.sh里SSH_KEY改为从 HashiCorp Vault 拉取,镜像内删除ssh-keygen,并用docker-secret把HPL.dat敏感 block size 参数加密,满足金融等保 2.0 要求。 - Kubernetes 化:将上述 compose 改写成 MPIJob(Kube-batch 或 Volcano),通过
kubectl create -f mpijob.yaml拉起 64 节点、2048 核,HPL 效率仍保持 ≥90 %,同时用 Prometheus + Grafana 监控容器内hwloc绑核热力图,方便后续调度器调优。