Running HPL with Volcano on Kubernetes

· 4 min read
文中提到的檔案皆放在 SiriusKoan/hpc-benchmarks-container。
What’s HPL #
HPL (High Performance Linpack) 是一個利用求解多元線性方程組來評估超級電腦效能的程式,主要被用來測試全球的超級電腦的速度 (TOP500)。
超級電腦是由多台小電腦所組成的,程式可以使用 MPI (Message Passing Interface) 來在多台機器之間溝通。HPL 便支援 MPI,所以可以作為評測的工具。
HPL 的設定檔是 HPL.dat,範例如下:
HPLinpack benchmark input file
Innovative Computing Laboratory, University of Tennessee
HPL.out output file name (if any)
6 device out (6=stdout,7=stderr,file)
4 # of problems sizes (N)
29 30 34 35 Ns
4 # of NBs
1 2 3 4 NBs
0 PMAP process mapping (0=Row-,1=Column-major)
1 # of process grids (P x Q)
4 Ps
4 Qs
16.0 threshold
3 # of panel fact
0 1 2 PFACTs (0=left, 1=Crout, 2=Right)
2 # of recursive stopping criterium
2 4 NBMINs (>= 1)
1 # of panels in recursion
2 NDIVs
3 # of recursive panel fact.
0 1 2 RFACTs (0=left, 1=Crout, 2=Right)
1 # of broadcast
0 BCASTs (0=1rg,1=1rM,2=2rg,3=2rM,4=Lng,5=LnM)
1 # of lookahead depth
0 DEPTHs (>=0)
2 SWAP (0=bin-exch,1=long,2=mix)
64 swapping threshold
0 L1 in (0=transposed,1=no-transposed) form
0 U in (0=transposed,1=no-transposed) form
1 Equilibration (0=no,1=yes)
8 memory alignment in double (> 0)
What’s Volcano #
Volcano 是一個 Kubernetes-native 的 batch scheduling 系統,專門設計給 HPC 使用。
他補足了原生 Kubernetes scheduler 的不足,支援更多 HPC 常用的排程方式及 feature,如 Gang Scheduling(讓同一個 job 的 workers 一起被佈署,避免只有部份 workers 上線的狀況)、多層的 queue、preemption、異質裝置支援(如 GPU)等等。
Volcano 也支援許多 HPC、AI/ML 相關的系統,例如前面提到的 MPI、Kubeflow(在 Kubernetes 上的 ML 開發及佈署平台)、TensorFlow 等等。
Containerize HPL #
HPL 目前沒有方便直接用的 Docker image,所以參考了 ExplorerRay/hpc-container-def 的做法,生了一個 Dockerfile 的版本。
FROM debian:trixie-slim AS build
# Environment variables for ignoring some harmless errors (from %environment)
ENV PMIX_MCA_gds="^ds12"
ENV PMIX_MCA_psec="^munge"
# Install dependencies and build HPL
RUN apt-get -y update && \
DEBIAN_FRONTEND=noninteractive apt-get -y install \
make g++ gcc gfortran wget openmpi-bin libopenmpi-dev libopenblas-dev && \
apt-get clean autoclean && \
apt-get autoremove --yes && \
rm -rf /var/lib/apt/lists/*
RUN cd /opt && \
wget https://www.netlib.org/benchmark/hpl/hpl-2.3.tar.gz && \
tar -xzf hpl-2.3.tar.gz && \
cd hpl-2.3/setup && \
cp Make.Linux_PII_CBLAS ../Make.linux && \
cd .. && \
sed -i 's|^TOPdir = $(HOME)/hpl|TOPdir = /opt/hpl-2.3|' Make.linux && \
sed -i 's|^ARCH = .*$|ARCH = linux|' Make.linux && \
sed -i 's|^MPdir = .*$|MPdir = /usr/lib/x86_64-linux-gnu/openmpi|' Make.linux && \
sed -i 's|^MPlib = .*$|MPlib = $(MPdir)/lib/libmpi.so|' Make.linux && \
sed -i 's|^LAdir = .*$|LAdir = /usr/lib/x86_64-linux-gnu/openblas-pthread|' Make.linux && \
sed -i 's|^LAlib = .*$|LAlib = $(LAdir)/libopenblas.a|' Make.linux && \
sed -i 's|^CC = .*$|CC = /usr/bin/mpicc|' Make.linux && \
sed -i 's|^LINKER = .*$|LINKER = /usr/bin/mpicc|' Make.linux && \
echo "Building HPL Benchmarks..." && \
make arch=linux && \
rm /opt/hpl-2.3.tar.gz
FROM debian:trixie-slim
ENV PMIX_MCA_gds="^ds12"
ENV PMIX_MCA_psec="^munge"
WORKDIR /opt/hpl-2.3/bin/linux
RUN apt update && \
apt install -y openmpi-bin libopenmpi-dev libopenblas-dev openssh-server && \
apt-get clean autoclean && \
apt-get autoremove --yes && \
rm -rf /var/lib/apt/lists/*
COPY --from=build /opt/hpl-2.3/bin/linux /opt/hpl-2.3/bin/linux
CMD ["sleep", "infinity"]
此 image 已經上傳至 DockerHub。
Running HPL with Volcano #
為了避免每次修改 HPL 參數都要重新 build container image,可以採用把 HPL.dat 用 ConfigMap 掛進 container 的方法。
$ kubectl create cm hpl --from-file=HPL.dat
接著準備 Volcano Job 的 YAML 檔:
apiVersion: batch.volcano.sh/v1alpha1
kind: Job
metadata:
name: hpl-mpi-job
spec:
minAvailable: 1
schedulerName: volcano
plugins:
mpi: ["--master=mpimaster","--worker=mpiworker","--port=22"] ## MPI plugin register
tasks:
- replicas: 1
name: mpimaster
policies:
- event: TaskCompleted
action: CompleteJob
template:
spec:
volumes:
- name: hpl-config
configMap:
name: hpl
containers:
- command:
- /bin/sh
- -c
- |
mkdir -p /var/run/sshd; /usr/sbin/sshd;
mpirun --allow-run-as-root --host "$MPI_HOST" ./xhpl;
image: siriuskoan/hpl:latest
name: mpimaster
workingDir: /opt/hpl-2.3/bin/linux
volumeMounts:
- name: hpl-config
mountPath: /opt/hpl-2.3/bin/linux/HPL.dat
subPath: HPL.dat
restartPolicy: OnFailure
- replicas: 4
name: mpiworker
template:
spec:
volumes:
- name: hpl-config
configMap:
name: hpl
containers:
- command:
- /bin/sh
- -c
- |
mkdir -p /var/run/sshd; /usr/sbin/sshd -D;
image: siriuskoan/hpl:latest
name: mpiworker
workingDir: /opt/hpl-2.3/bin/linux
volumeMounts:
- name: hpl-config
mountPath: /opt/hpl-2.3/bin/linux/HPL.dat
subPath: HPL.dat
resources:
requests:
cpu: 1
limits:
cpu: 1
restartPolicy: OnFailure
Volcano 的 MPI plugin 會將 MPI_HOST
設定好,讓 MPI master 可以直接知道 topology 裡面有哪些 worker。
另外建議可以設定好 worker 的 resources
,Kubernetes 才會給他比較高的 QoS。
最後使用以下指令就可以看到 job 在跑了:
$ kubectl apply -f job
$ kubectl get vcjob
Multi-cores 的執行 #
雖然 Volcano 會幫忙完成 topology discover 並設定好 MPI_HOST
,但它不會知道使用者和 Kubernetes 要求多少資源給 worker。換句話說,如果把要求的 CPU 加到 4,HPL 依然只會跑在一個 CPU 上。
目前沒有找到 Volcano 提供的解法,但可以直接用 Linux 指令來修改一下 MPI_HOST
來讓它帶有 CPU 核心數的資料。將原本 MPI master 的 mpirun
指令改成以下這行:
mpirun --allow-run-as-root --host "$(echo $MPI_HOST | sed 's/,/:4,/g; s/$/:4/')" ./xhpl;
其中的 4
為 worker 請求的 CPU 核心數。
Todo #
Volcano 本身是為了 HPC 特化的 Kubernetes scheduler,他提供的 MPI 連線方式是最簡單的 SSH,且需要在 worker 上手動開啟 SSH server,較為麻煩。未來可以嘗試用專門做 MPI 的 Kubernetes 的 MPI Operator 跑跑看。