Cборку программ, использующих ускорители NVidia A100, нужно осуществлять с помощью средств CUDA Toolkit начиная с версии 10.0. В настоящий момент у нас установлены версии 11.2 и 11.3, их можно использовать, загрузив модули cuda/cuda-11.2 или cuda/cuda-11.3:
user@master ~$ module load cuda/cuda-11.2 # или user@master ~$ module load cuda/cuda-11.3
Если программа содержит не-CUDA модули или использует MPI, то необходимо дополнительно загрузить соответствующие модули для компилятора или MPI-библиотеки.
Компиляция и линковка программы, содержащей код CUDA, производится командой следующего вида:
user@master ~$ echo '#include <stdio.h> #include <cuda.h> __global__ void mykernel(void){ printf("Hello World from thread %d block %d on device\n", threadIdx.x , blockIdx.x); } int main (void ) { mykernel<<<2,2>>>(); cudaDeviceSynchronize(); return 0; }' >helloCUDA.cu user@master ~$ nvcc -o helloCUDA --gpu-architecture=sm_80 -lcudart helloCUDA.cu
Для запуска программы в интерактивном режиме на одном узле кластера (ускорители NVidia A100 установлены на узлах node238 и node239) нужно выполнить команду следующего вида:
user@master ~$ srun -N 1 -n 3 -p a100 --gres=gpu:3 ./helloCUDA Hello World from thread 0 block 1 on device Hello World from thread 1 block 1 on device Hello World from thread 0 block 0 on device Hello World from thread 1 block 0 on device Hello World from thread 0 block 0 on device Hello World from thread 1 block 0 on device Hello World from thread 0 block 1 on device Hello World from thread 1 block 1 on device Hello World from thread 0 block 1 on device Hello World from thread 1 block 1 on device Hello World from thread 0 block 0 on device Hello World from thread 1 block 0 on device
Здесь «-N 1» — запрос на выделение для запуска одного узла, «-n 3» — число создаваемых процессов (значение более одного обычно используется для запуска mpi-программ, для одного процесса параметр можно не указывать), «-p a100» — выбор раздела для запуска (обязательный параметр для запуска на узлах с A100), «—gres=gpu:3» — запрос на выделение 3 ускорителей NVidia A100 (с точки зрения вашей программы ускорители будут иметь номера 0,1,2).
В нашем случае запустилось 3 копии программы, все они использовали одно устройство (для использования различных нужно добавить в код вызов cudaSetDevice()), каждая копия запустила на устройстве код в 2 блока по 2 потока.
Для запуска в пакетном режиме необходимо подготовить файл задания и поставить его в очередь заданий:
user@master ~$ echo '#!/bin/sh #SBATCH -N 1 #SBATCH --gres=gpu:3 #SBATCH --time=10 #SBATCH --partition=a100 ./helloCUDA' >batch_helloCUDA.sh user@master ~$ sbatch batch_helloCUDA.sh Submitted batch job 2420539
Параметры запуска задания (time, partition, N etc) могут быть указаны как в файле задания, так и в командной строке sbatch. Номер задания может быть использован для просмотра его состояния. После завершения выполнения задания стандартный вывод и стандартный вывод ошибки записываются в файлы slurm-JOBID.out и slurm-JOBID.err (можно задать файлы с другими именами).
user@master ~$ scontrol show job 2420539 JobId=2420539 JobName=batch_helloCUDA.sh UserId=user(userid) GroupId=Users(10000) MCS_label=N/A Priority=1052937772 Nice=0 Account=user QOS=normal JobState=PENDING Reason=Nodes_required_for_job_are_DOWN,_DRAINED_or_reserved_for_jobs_in_higher_priority_partitions Dependency=(null) ... user@master ~$ cat slurm-2420539.out Hello World from thread 0 block 1 on device Hello World from thread 1 block 1 on device Hello World from thread 0 block 0 on device Hello World from thread 1 block 0 on device
Если вы запускаете ранее собранную программу, необходимо предварительно загрузить тот модуль CUDA, который использовался при ее компиляции и линковке.