Очередь задач teslaq

:!: GPU NVIDIA M2090 устарели и поддерживаются только CUDA до версии 8.0 включительно.


Задачи из очередь teslaq запускаются на серверах HP SL390s G7, у каждого из которых: 12 процессорных ядер, 96 ГБ ОЗУ и 3 графических ускорителя NVIDIA Tesla M2090. Ресурсы каждого ускорителя всегда должны использоваться одним пользователем монопольно. Тем не менее, наличие трёх ускорителей на каждом сервере позволяет одновременно работать 3-м пользователям. Для этого каждый из серверов делится на три виртуальных узла, каждый из которых содержит 4 процессорных ядра, 32 ГБ ОЗУ и 1 ускоритель. Для запроса необходимого количества ускорителей используется ресурс ngpus:

#PBS -l select=1:ngpus=1:ncpus=4:mem=32gb


После запуска задачи она должна узнать, какой виртуальный узел (или узлы) ей выделен и по его названию понять порядковый номер ускорителя, который она должна использовать. Например, виртуальные узлы сервера 'sl002' называются sl002[0], sl002[1] и sl002[2]. Если задаче выделен виртуальный узел sl002[2], значит, она должна использовать на узле sl002 именно ускоритель №2.

Исключение составляют задачи, запрашивающие и использующие все 3 ускорителя сервера - они могут задействовать их по своему усмотрению.

Определить предоставленный виртуальный узел можно с помощью значения параметра 'exec_vnode' в выводе команды 'qstat -f $PBS_JOBID'. Данную операцию можно произвести как из скрипта (примеры приведены ниже), так и из самого запускаемого приложения, если имеется возможность модифицировать его код. Следует учитывать, что при запросе нескольких ускорителей значение 'exec_vnode' может занимать более одной строки.

Графические ускорители нумеруются начиная с '0', индекс соответствует номеру устройства в CUDA (например, в команде cudaSetDevice) или в выводе команды 'nvidia-smi':

nvidia-smi -L
GPU 0: Tesla M2090 (S/N: 0341615011546)
GPU 1: Tesla M2090 (S/N: 0341615011399)
GPU 2: Tesla M2090 (S/N: 0341615011254)


Чтобы предотвратить одновременное использование одного ускорителя несколькими задачами, режим 'Compute mode' всем ускорителям установлен в значение EXCLUSIVE_PROCESS (подробнее про 'Compute mode' см. в описании утилиты 'nvidia-smi').


:!: Автоматического ограничения доступа к остальным ускорителям узла средствами PBS не происходит, пользователь должен сам настраивать свои задачи для использования только предоставленных ему ускорителей.

В случае, если запрашивается ровно один ускоритель, можно быть уверенным, что значение 'exec_vnode' поместится в одну строку. Кроме того, нет необходимости определять, какой физический сервер нам выделен, т.к. именно на нём задача и запустится.

Код, определяющий предоставленный ускоритель, его SN и UUID:

#!/bin/sh

#PBS -q teslaq
#PBS -l walltime=0:01:00
#PBS -l select=1:ngpus=1:ncpus=4:mem=32gb

cd $PBS_O_WORKDIR

vnodes=$(qstat -f $PBS_JOBID|grep exec_vnode|sed -e 's/ *//')
echo "$vnodes"
if [ $(echo $vnodes|grep -c '+') != 0 ] ; then
    echo "Error: several vnodes are provided."
    exit 100
fi
gpu=$(echo $vnodes|sed 's/.*\[//'|sed 's/\].*//')
sn=$(nvidia-smi -q -i $gpu_nbr|grep 'Serial Number'|awk -F\: '{print $2}'|sed -e 's/ *//')
uuid=$(nvidia-smi -q -i $gpu_nbr|grep 'GPU UUID'|awk -F\: '{print $2}'|sed -e 's/ *//')
echo "GPU  = $gpu"
echo "SN   = $sn"
echo "UUID = $uuid"

В результате работы получим в файле стандартного вывода примерно следующее:

exec_vnode = (sl001[0]:ncpus=4:ngpus=1:mem=33554432kb)
GPU  = 0
SN   = 0341615011546
UUID = GPU-df433275cee7fdcd-53619fe0-b727ce0a-4aa635a9-69819036549a1e42288e1692

Может потребоваться использовать в одной задаче несколько графических ускорителей, в том числе принадлежащих разным физическим серверам. Например, для гибридной задачи, использующей как GPGPU, так и MPI. В этом случае анализ предоставленных задаче виртуальных узлов будет немного сложнее.

#!/bin/sh

#PBS -q teslaq
#PBS -l walltime=0:01:00
#PBS -l select=3:mpiprocs=2:ngpus=2:ncpus=8:mem=32gb,place=scatter

cd $PBS_O_WORKDIR
vnodes=$(qstat -f $PBS_JOBID|tr -d '\n'' ''\t'|sed 's/Hold_Types.*//'|sed 's/.*exec_vnode=//'|tr -d \(\)|tr + '\n'|sed 's/:.*//'|sort)
echo "My vnodes:"
for vnode in $vnodes ; do
    node=$(echo $vnode|sed 's/\[.*//')
    gpu=$(echo $vnode|sed 's/.*\[//'|sed 's/\]//')
    echo "$vnode = Node $node, GPU $gpu"
done
echo
echo "PBS_NODEFILE:"
cat $PBS_NODEFILE

В результате работы получим в файле с логом потока стандартного вывода примерно следующее:

My vnodes:
sl001[1] = Node sl001, GPU 1
sl001[2] = Node sl001, GPU 2
sl002[0] = Node sl002, GPU 0
sl002[1] = Node sl002, GPU 1
sl004[0] = Node sl004, GPU 0
sl004[1] = Node sl004, GPU 1

PBS_NODEFILE:
sl001
sl001
sl004
sl004
sl002
sl002