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