Здравствуйие! Я хочу пройти курс Введение в принципы функционирования и применения современных мультиядерных архитектур (на примере Intel Xeon Phi), в презентации самостоятельной работы №1 указаны логин и пароль для доступ на кластер и выполнения самостоятельных работ, но войти по такой паре логин-пароль не получается. Как предполагается выполнение самосоятельных работ в этом курсе? |
Самостоятельная работа 1: Компиляция и запуск приложений на Intel Xeon Phi
Скалярное произведение векторов
Рассмотрим следующую простую задачу: необходимо посчитать скалярное произведение двух векторов.
Создадим файл исходного кода main.cpp. Выполним подключение необходимых библиотек:
#include <stdio.h> #include <stdlib.h>
Создадим функцию для подсчета скалярного произведения двух векторов. Вычисление будет производиться параллельно на всех доступных ядрах вычислительного устройства. Обратите внимание, что код функции dot не содержит в себе специальных директив для выполнения на Intel Xeon Phi:
#pragma offload_attribute(push, target(mic)) float dot(float* a, float* b, int n) { float res = 0; #pragma omp parallel for reduction(+: res) for (int i = 0; i < n; ++i) { res += a[i]*b[i]; } return res; } #pragma offload_attribute(pop)
Как и прежде, используем директиву offload_attribute для того, чтобы сообщить компилятору о необходимости создания копии этого участка кода для исполнения на сопроцессоре.
Напишем функцию main для тестирования приведенного выше кода. Прежде всего, объявим используемые переменные и массивы:
int main() { int n = 100; float* a = new float[n]; float* b = new float[n]; float res_cpu, res_mic;
Затем инициализируем вектора a и b случайными числами:
for (int i = 0; i < n; ++i) { a[i] = (float)rand()/RAND_MAX; b[i] = (float)rand()/RAND_MAX; }
Запустим вычисление скалярного произведения на центральном процессоре и выведем результат на консоль:
res_cpu = dot(a, b, n); printf("CPU dot: %f\n", res_cpu);
Далее необходимо запустить функцию dot на сопроцессоре. Для этого воспользуемся уже знакомой нам директивой offload:
#pragma offload target(mic) in(a[0:n], b[0:n]) res_mic = dot(a, b, n); printf("MIC dot: %f\n", res_mic);
Здесь используется дополнительный параметр in для указания того, что массивы a и b размером n элементов необходимо скопировать на сопроцессор перед началом вычислений, обратного копирования при этом делать не нужно. После окончания вычислений выведем результат на консоль. Обратите внимание, что к моменту вызова функции printf сопроцессор гарантированно завершит свою работу.
Далее осталось только удалить используемую память центрального процессора. Память на сопроцессоре в данном случае будет освобождена автоматически по окончании работы функции dot.
delete[] a; delete[] b; return 0; }
Скомпилируем и запустим полученный код:
icc -02 -openmp main.cpp –o lab1_dot_offload mpiexec.hydra –perhost 1 ./lab1_dot_offload
Результаты работы программы приведены на рис. 6.4.
В заключение данного раздела покажем, как осуществить запуск offload программы в пакетном режиме без предварительного выделения ресурсов (сопроцессоров). Этот же способ подходит для запуска MPI программы в режиме offload. Будем использовать возможности системы управления кластером SLURM.
Прежде всего, необходимо написать скрипт запуска. Пусть X – число MPI процессов, выполняемых на одном узле кластера, а Y – числа узлов. Тогда скрипт будет таким:
#!/bin/sh mpiexec.hydra –perhost X –n X*Y ./offload_program
Для постановки задачи в очередь нужно выполнить команды:
module load launcher/intel sbatch –N Y ./run.sh
где run.sh – имя приведенного выше скрипта. После выполнения этих команд задача будет поставлена в очередь, а после выполнения результаты работы программы будут записаны в файл slurm-<номер задачи>.out. Подробнее о работе команды sbatch можно узнать из следующих разделов.