2. MXMACA容器化应用

2.1. 基于Docker的容器化应用

准备步骤

  1. 确认主机已正确安装沐曦通用GPU驱动。正确安装后,可执行 mx-smi 查看沐曦通用GPU设备。

  2. 运行如下命令启动一个容器。

    $ 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镜像的名称。

  3. 进入容器后,执行 mx-smi -L 来验证沐曦通用GPU在容器中是否可以正常使用。

    docker run 的其他选项,可根据需求在创建容器时进行设置。例如,若需要数据持久化,可以使用 -v 挂载卷或本地目录到容器中。

2.1.1. 验证编译和运行环境

在容器中可以使用MXMACA编译器编写一个Hello MACA的程序,验证MXMACA应用程序的编译和运行环境。

操作步骤

  1. 编写hello.maca,代码内容如下:

    #include <stdio.h>
    #include <mc_runtime.h>
    __global__ void hello()
    {
        printf("Hello MACA!\n");
    }
    int main()
    {
        hello<<<1, 1>>>();
        mcDeviceSynchronize();
        return 0;
    }
    
  2. 执行以下命令,编译生成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为例:

  1. 编写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官网

  2. 构建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
    
  3. 运行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。

操作步骤

  1. 从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
    
  2. 将本地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应用程序。

  1. 生成Singularity格式镜像。

    $ singularity build hellomaca.sif docker-daemon://hellomaca:latest
    
  2. 运行Singularity容器应用。

    $ singularity run hellomaca.sif hello
    

程序运行结束,终端输出 Hello MACA!,表明Singularity支持MXMACA应用程序通过启动其容器的方式在沐曦通用GPU上运行。

2.3. 基于Slurm集群的容器化应用

../_images/image2.png

图 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提交作业的方式执行。

  1. 登录Slurm登录节点,上传hellomaca.sif镜像文件。

  2. 在提交作业目录下编写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
    
  3. 提交作业。

    #申请两个计算节点,每个节点需要一张x206 GPU资源
    $ sbatch -J helloMaca -p metax-gpu --gres=gpu:x206:1 -n2 -N2 x206_hellomaca.bash
    

    提交后屏幕会显示job ID:

    Submitted batch job 1
    

    使用squeue查询作业队列,可以看到分配了两个节点snode1snode2

    $ squeue -a
    JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
    1 metax-gpu helloMac root R 0:03 2 snode[1-2]
    
  4. 查看作业结果。在没有格式化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等,用户可以根据不同需求进行选择。