Поддержка вычислений на Xeon Phi прекращена в связи с отсутствием интереса со стороны пользователей и отсутствием поддержки MPSS современных операционных систем.
#PBS -q xl250g9q
#PBS -l select=1:ncpus=4:mem=12gb:nmics=1
Пример 1:
#!/bin/sh #PBS -q xl250g9q #PBS -l walltime=0:01:00 #PBS -l select=1:nmics=1:ncpus=1:mem=1gb 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 mic=$(echo $vnodes|sed 's/.*\[//'|sed 's/\].*//') echo "mic=$mic" micinfo -deviceInfo $mic|grep 'Device Name'
exec_vnode = (cn332[0]:ncpus=1:mem=102400kb:nmics=1) mic=0 Device No: 0, Device Name: mic0
В данном случае задаче был предоставлен сопроцессор с номером '0' и именем 'mic0'
Пример 2:
#!/bin/sh #PBS -q xl250g9q #PBS -l walltime=0:01:00 #PBS -l select=3:nmics=2:ncpus=4:mem=4gb 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/\[.*//') mic=$(echo $vnode|sed 's/.*\[//'|sed 's/\]//') echo "$vnode = Node $node, mic $mic" done
My vnodes: cn332[0] = Node cn332, mic 0 cn332[1] = Node cn332, mic 1 cn333[0] = Node cn333, mic 0 cn333[1] = Node cn333, mic 1 cn334[0] = Node cn334, mic 0 cn334[1] = Node cn334, mic 1
source /opt/intel/composerxe/bin/compilervars.sh intel64
Для изучения возможных нюансов будет полезно просмотреть вывод комадны 'man' на используемый компилятор (icc / icpc / ifort) и изучить параметры компиляции и переменные окружения, влияющие на генерацию кода и работу приложений для архитектуры Intel MIC.
#pragma offload target(mic:номер)
, где 'номер' - номер используемого сопроцессора (в нашем случае это '0' или '1', в зависимости от виртуального узла, выделенного PBS ). Параметр 'номер' не является обязательным с точки зрения синтаксиса, но при работе на нашем кластера он должен указываться и сответствовать номеру сопроцессора, предоставленному планировщиком задач. Также эта директива может содержать дополнительные параметры, например, указывающие, значения каких переменных должны передаваться между ОЗУ узла и собственной памятью сопроцессора:#pragma offload
, а при помощи переменной окружения 'OFFLOAD_DEVICES'. Подробности смотрите в выводе команды 'man' на используемый компилятор.#pragma offload
. Также можно делать offload из MPI-процессов, работающих на хосте.
Пример:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> int main(int argc, char** argv) { int cores; char host[32]; char * endptr; long mic_number; if (argc < 2) { printf("ERROR: MIC number absent!\n"); exit(1); } mic_number = strtol (argv[1], &endptr, 10); if (endptr == argv[1] || (mic_number != 0 && mic_number != 1) ) { printf("ERROR: incorrect MIC number!\n"); exit(2); } printf("mic = %i\n",mic_number); gethostname(host,32); cores = sysconf( _SC_NPROCESSORS_ONLN ); printf("hostname = %s, logical cores = %d\n",host,cores); #pragma offload target(mic:mic_number) out(host,cores) { gethostname(host,32); cores = sysconf( _SC_NPROCESSORS_ONLN ); } printf("micname = %s, logical cores = %d\n",host,cores); return 0; }
#!/bin/sh #PBS -q xl250g9q #PBS -l walltime=0:01:00 #PBS -l select=1:ncpus=1:mem=100mb:nmics=1 cd $PBS_O_WORKDIR vnodes=$(qstat -f $PBS_JOBID|grep exec_vnode|sed -e 's/ *//') if [ $(echo $vnodes|grep -c '+') != 0 ] ; then echo "Error: several vnodes are provided." exit 100 fi mic=$(echo $vnodes|sed 's/.*\[//'|sed 's/\].*//') source /opt/intel/composerxe/bin/compilervars.sh intel64 icc -o show_cores show_cores.c ./show_cores $mic
mic = 0 hostname = cn332, logical cores = 24 micname = cn332-mic0, logical cores = 244
Пример:
#include <stdio.h> #include <unistd.h> int main(int argc, char** argv) { int cores; char host[32]; gethostname(host,32); cores = sysconf( _SC_NPROCESSORS_ONLN ); printf("micname=%s, logical cores=%d\n",host,cores); return 0; }
#!/bin/sh #PBS -q xl250g9q #PBS -l walltime=0:01:00 #PBS -l select=1:ncpus=1:mem=100mb:nmics=1 cd $PBS_O_WORKDIR vnodes=$(qstat -f $PBS_JOBID|grep exec_vnode|sed -e 's/ *//') if [ $(echo $vnodes|grep -c '+') != 0 ] ; then echo "Error: several vnodes are provided." exit 100 fi mic="mic$(echo $vnodes|sed 's/.*\[//'|sed 's/\].*//')" source /opt/intel/composerxe/bin/compilervars.sh intel64 icc -mmic -o show_cores_natively show_cores_natively.c ssh -q $mic "cd $PBS_O_WORKDIR ; ./show_cores_natively"
micname=cn333-mic0, logical cores=244
mpi-selector --set intel_mpi-5.0.1.035
#include <mpi.h> #include <stdio.h> #include <unistd.h> int main(int argc, char** argv) { int size, rank; char host[32]; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&size); MPI_Comm_rank(MPI_COMM_WORLD,&rank); gethostname(host,32); printf("Hello, MPI world! I'm number %d from %d and I run on host %s\n",rank,size,host); MPI_Finalize(); return 0; }
#!/bin/sh #PBS -l select=1:ncpus=1:mem=1g #PBS -l walltime=00:01:00 #PBS -q xl250g9q cd $PBS_O_WORKDIR source /opt/intel/composerxe/bin/compilervars.sh intel64 mpiicc hello_mpi_world.c -o hello_mpi_world mpiicc -mmic hello_mpi_world.c -o hello_mpi_world.mic
cn331 cn331 cn331-mic0:3
Первая строка соответствует процессу с рангом '0'. При использовании MPI на обычных серверах, без сопроцессоров, этот файл создаётся PBS на основе запроса 'select=' и путь до него находится в переменной окружения PBS_NODEFILE. Но при использовании MPI на сопроцессорах в запросе не указывается, сколько процессов будет запускаться на сопроцессоре. Поэтому файл надо будет создать самостоятельно, взяв за основу предоставленный PBS и добавив к нему нужное количество строк, соответствующих сопроцессору.
export I_MPI_MIC=enable
export I_MPI_MIC_POSTFIX=.mic
Пример:
#!/bin/sh #PBS -l select=2:ncpus=1:mpiprocs=1:mem=2g:nmics=2 #PBS -l walltime=00:01:00 #PBS -q xl250g9q cd $PBS_O_WORKDIR source /opt/intel/composerxe/bin/compilervars.sh intel64 ## Create machinefile: machinefile=$PBS_O_WORKDIR/machinefile.$(echo $PBS_JOBID|awk -F. '{print $1}') cat $PBS_NODEFILE > $machinefile vnodes=$(qstat -f $PBS_JOBID|tr -d '\n'' ''\t'|sed 's/Hold_Types.*//'|sed 's/.*exec_vnode=//'|tr -d \(\)|tr + '\n'|sed 's/:.*//'|sort) for vnode in $vnodes ; do node=$(echo $vnode|sed 's/\[.*//') mic="mic$(echo $vnode|sed 's/.*\[//'|sed 's/\]//')" # Add 2 MPI processes for each Xeon Phi: echo "${node}-${mic}:2" >> $machinefile done export I_MPI_MIC=enable export I_MPI_MIC_POSTFIX=.mic mpirun -genv I_MPI_FABRICS=shm:tcp -machinefile $machinefile $PBS_O_WORKDIR/hello_mpi_world rm $machinefile
Hello, MPI world! I'm number 0 from 10 and I run on host cn331 Hello, MPI world! I'm number 1 from 10 and I run on host cn332 Hello, MPI world! I'm number 8 from 10 and I run on host cn332-mic1 Hello, MPI world! I'm number 6 from 10 and I run on host cn332-mic0 Hello, MPI world! I'm number 4 from 10 and I run on host cn331-mic1 Hello, MPI world! I'm number 2 from 10 and I run on host cn331-mic0 Hello, MPI world! I'm number 9 from 10 and I run on host cn332-mic1 Hello, MPI world! I'm number 3 from 10 and I run on host cn331-mic0 Hello, MPI world! I'm number 5 from 10 and I run on host cn331-mic1 Hello, MPI world! I'm number 7 from 10 and I run on host cn332-mic0