2. MXMACA容器化应用
2.1. 基于Docker的容器化应用
准备步骤
确认主机已正确安装沐曦通用GPU驱动。正确安装后,可执行
mx-smi查看沐曦通用GPU设备。运行如下命令启动一个容器。
$ sudo docker run -it --device=/dev/mxcd --device=/dev/dri --group-add video maca:[tag] bash
每个选项的含义如下:
docker run是启动容器的命令。-it选项告诉Docker在交互模式下运行容器,即在终端中打开容器的shell。--device=/dev/mxcd和--device=/dev/dri选项允许容器访问计算机上的沐曦通用GPU设备。--group-add video选项添加用户到video用户组,以便容器可以访问计算机上的视频设备。maca:[tag]是包含MXMACA的Docker镜像的名称。
进入容器后,执行
mx-smi -L来验证沐曦通用GPU在容器中是否可以正常使用。docker run的其他选项,可根据需求在创建容器时进行设置。例如,若需要数据持久化,可以使用-v挂载卷或本地目录到容器中。
2.1.1. 验证编译和运行环境
在容器中可以使用MXMACA编译器编写一个Hello MACA的程序,验证MXMACA应用程序的编译和运行环境。
操作步骤
编写hello.maca,代码内容如下:
#include <stdio.h> #include <mc_runtime.h> __global__ void hello() { printf("Hello MACA!\n"); } int main() { hello<<<1, 1>>>(); mcDeviceSynchronize(); return 0; }
执行以下命令,编译生成hello可执行程序,验证运行时环境。
#编译 $ mxcc hello.maca -o hello #运行 $ ./hello Hello MACA!
备注
打印Hello MACA表明该容器下基于MXMACA的编译和运行环境均是正常的。
2.1.2. 发布MXMACA的应用程序
使用容器可以隔离开发环境与主机环境,这使得用户可以通过使用同一Docker镜像在不同的主机环境中运行相同的程序,避免了环境差异导致的问题。
构建Docker镜像有两种方式:容器提交和Dockerfile。
2.1.2.1. 容器提交构建方式
可以在启动的容器中安装程序依赖,编译运行程序。验证无误后通过以下命令将容器提交成镜像。
docker commit [CONTAINER] [REPOSITORY[:TAG]]
其中,[CONTAINER]为要提交的容器的ID或名字,[REPOSITORY]是要创建的新镜像的名称,可以指定TAG。
需要注意的是,使用 docker commit 提交容器创建镜像可能会导致镜像不可重构,因为在容器中进行的所有配置最终只是以diff的形式加到镜像层组成最终的镜像。
因此,建议另外一种构建方式,即使用Dockerfile来构建和管理Docker镜像。
2.1.2.2. Dockerfile构建方式
这种方式可以通过Dockerfile重复构建,使镜像支持重构。以 2.1.1 验证编译和运行环境 的Hello MACA为例:
编写Dockerfile。
FROM maca RUN apt update && apt install build-essential -y && apt clean COPY hello.maca /tmp RUN cd /tmp && mxcc hello.maca -o ./hello
Dockerfile支持的语法,可以参见 Docker官网 。
构建Docker镜像。
ls docker build -t hellomaca . $ ls Dockerfile hello.maca #通过Dockerfile构建镜像。-t后参数为将构建的docker镜像名 $ docker build -t hellomaca .
当终端打印Successfully tagged hellomaca:latest,表示构建完成。此时通过
docker images命令可以查看到生成的镜像。docker images docker run --device=/dev/mxcd --device=/dev/dri --group-add video hellomaca:latest /tmp/hello $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hellomaca latest 9912c6afdb3b 39 seconds ago 5.86GB maca latest fba8ade0ecf4 2 weeks ago 5.62GB
运行Docker镜像中的Hello MACA程序。
$ docker run --device=/dev/mxcd --device=/dev/dri --group-add video hellomaca:latest /tmp/hello #终端输出: Hello MACA!
2.2. 基于Singularity的容器化应用
Singularity是一个开源的容器化方案,使用场景主要集中在科学计算和高性能计算领域。 与Docker不同,Singularity容器可以在没有root权限或加入特定用户组(如docker组)的情况下运行,因此非常适合在集群和超算环境中使用。 用户通过Singularity可以直接运行HPC应用程序,支持MPI和InfiniBand等高性能通讯技术。 同时,Singularity支持多种容器格式,包括Docker、OCI和Singularity等自定义格式,因此也可以与其他容器平台和工具集成使用。
本节主要介绍使用Singularity将Docker镜像转换为Singulairty镜像格式SIF。
操作步骤
从Docker Hub或第三方私有仓库获取镜像并转换为SIF镜像文件格式。
$ singularity pull docker://<registry>/<image>:<tag>
或
$ singularity build <imagename.sif> docker://<registry>/<image>:<tag>
<registry>一般是私有仓库的地址。如果不指定,则默认使用Docker Hub作为registry。<image>是镜像名称。<tag>是镜像标签。imagename指定通过singularity build生成的镜像名,镜像以.sif后缀结尾。两种方式都会在格式转换过程中进行build生成SIF格式的镜像。
例如,使用Ubuntu 20.04的Docker镜像生成Singularity镜像:
$ singularity pull docker://ubuntu:20.04 #当前目录会生成ubuntu_20.04.sif $ singularity build ubuntu_20.04.sif docker://ubuntu:20.04 #也会在当前目录生成ubuntu_20.04.sif
将本地Docker镜像转换成SIF镜像文件。
$ singularity build <imagename.sif> docker-daemon://<image>:<tag>
docker-daemon://<image>:<tag>表示本地的Docker镜像名和标签。
另外,与Dockerfile类似,Singularity使用的是recipe文件,其中包含了构建Singularity镜像所需的指令和参数。 通过执行recipe文件中的指令,可以自动化地构建Singularity镜像,具体用法参见 Singularity官方文档 。
2.2.1. 示例
以 2.1 基于Docker的容器化应用 中发布的Docker应用镜像hellomaca:latest为例,以下演示通过Singularity转换为SIF镜像格式文件,并启动Singularity容器运行Hello MACA应用程序。
生成Singularity格式镜像。
$ singularity build hellomaca.sif docker-daemon://hellomaca:latest
运行Singularity容器应用。
$ singularity run hellomaca.sif hello
程序运行结束,终端输出 Hello MACA!,表明Singularity支持MXMACA应用程序通过启动其容器的方式在沐曦通用GPU上运行。
2.3. 基于Slurm集群的容器化应用
图 2.1 Slurm集群调度示意图
Slurm下提交非容器化的作业一般都是在分配资源节点后通过module environment的方式先加载依赖包,再执行作业的计算程序。 当某个特定APP的依赖包在集群module environment中未提供,或者提供了依赖的module包但编译选项并不是APP所期待的场景,可以将APP的完整运行依赖环境构建成Singularity镜像的方式,在Slurm计算节点启动容器中的APP进程。 这样可以不依赖集群计算节点的环境。
若程序需要在拥有沐曦通用GPU的环境下运行,只要在申请作业时使用 --gres 指定沐曦通用GPU(如X206)为申请资源类型即可。
2.3.1. 示例
以hellomaca为例,使用 2.2 基于Singularity的容器化应用 生成的hellomaca.sif镜像,以Slurm提交作业的方式执行。
登录Slurm登录节点,上传hellomaca.sif镜像文件。
在提交作业目录下编写sbatch作业脚本(x206_hellomaca.bash)。
#!/bin/bash # Submit as follows: # sbatch -J helloMaca -p metax-gpu --gres=gpu:x206:1 -n2 -N2 x206_hellomaca.bash module load singularity srun --gres=gpu:x206:1 -n2 -N2 --exclusive singularity run hellomaca.sif hello module unload singularity & wait
提交作业。
#申请两个计算节点,每个节点需要一张x206 GPU资源 $ sbatch -J helloMaca -p metax-gpu --gres=gpu:x206:1 -n2 -N2 x206_hellomaca.bash
提交后屏幕会显示job ID:
Submitted batch job 1
使用squeue查询作业队列,可以看到分配了两个节点snode1和snode2。
$ squeue -a JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON) 1 metax-gpu helloMac root R 0:03 2 snode[1-2]
查看作业结果。在没有格式化log输出文件时,默认生成
slurm-<jobID>.out格式的log文件。#在作业结束后,查看作业结果 $ cat slurm-<jobID>.out Hello MACA! Hello MACA!
可以看到sbatch作业脚本(x206_hellomaca.bash)中只是依赖了计算节点的Singularity module,因为需要调用Singularity命令启动容器中的计算程序;而对于其他模块的依赖,已经集成在Singularity容器中。 这样减轻了集群包管理的任务量,也让作业提交摆脱环境依赖,用户可更灵活地使用沐曦通用GPU计算资源。
在提交MPI作业时,由Slurm调度和管理MPI进程。
用户可以在构建镜像时,安装pmi2,并在MPI(如openmpi等)编译时增加 --with-pmi=${mpi2_path} 选项的方式,以便让Slurm获得MPI作业调度和管理的能力。
Slurm集群默认支持mpi2选项来调度MPI进程;也可以通过 slurm --mpi=list 的方式查看Slurm集群支持管理的MPI进程接口类型和版本,如pmi2、pmix等。
这些MPI管理接口可能还会有可用的具体版本,如pmix_v3、pmix_v4等,用户可以根据不同需求进行选择。