Опубликован: 30.05.2014 | Уровень: для всех | Доступ: платный | ВУЗ: Нижегородский государственный университет им. Н.И.Лобачевского

Лекция 3: Выполнение программ на Intel Xeon Phi. Модели организации вычислений с использованием Intel Xeon Phi

< Лекция 2 || Лекция 3: 123 || Лекция 4 >

Создание приложений для Intel Xeon Phi

Разработка приложений для архитектуры Intel Xeon Phi требует наличия тех же знаний и навыков, что и разработка параллельных приложений для распределенных многоядерных систем. Можно использовать следующие программные инструменты:

  • средства разработки "Intel Parallel Studio XE 2013", "Intel Cluster Studio XE 2013", "Intel(R) SDK for OpenCL Applications XE 2013 Beta", gcc (в настоящий момент не поддерживает векторные инструкции) и др.;
  • библиотеки Intel Math Kernel Library (Intel MKL), Intel Threading Building Blocks (Intel TBB), Intel Integrated Performance Primitive (Intel IPP), входящие в состав средств разработки Intel, а также Intel MPI for Linux, MPICH2, Boost и др.
  • отладчики (Intel Debugger, gdb, totalview), профилировщики (входят в состав средств разработки Intel), средства виртуализации (xen) и т.д.

Компиляция гетерогенных приложений производится в базовой системе. В случае использования режима Offload, для всех offload-блоков создается две версии кода – для базовой системы и для сопроцессора. Компилятор создает исполняемые файлы и/или библиотеки, содержащие весь код для процессора и сопроцессора. Во время исполнения программы при первом вызове offload-кода проверяется наличие сопроцессора Intel Xeon Phi. В случае его наличия и незанятости происходит загрузка на него двоичного исполняемого файла и инициализация необходимых библиотек, после чего выполняется вызов offload-кода. В случае отсутствия сопроцессора происходит вызов версии функции для базовой системы. Таким образом, приложение будет работать как при наличии сопроцессора, так и при его отсутствии.

Рассмотрим несколько версий программы сложения элементов массива для различных моделей выполнения.

Программы для режима выполнения Offload

При использовании режима Offload порядок использования сопроцессора определяется посредством директив компилятора – pragma в языках C/C++, директив в FORTRAN.

Последовательное синхронное выполнение

Блок программы, который следует выполнить на сопроцессоре, указывается посредством директивы #pragma offload target(mic). Операторы in, out, inout определяют необходимость и направление передачи данных между памятью хоста и сопроцессора. По умолчанию все переменные, объявленные вне offload-блока, перед началом его выполнения копируются на сопроцессор, а по окончании выполнения копируются назад в память базовой системы.

float Sum(float *Data, int Size){
   float Ret = 0.0f;
#pragma offload target(mic) in(Data:length(Size))
   for (int i = 0; i < Size; i ++){
      Ret += Data[i];
   }
   return Ret;
}

В данном примере переменная Ret перед началом выполнения offload-кода будет скопирована из памяти хост-системы в память сопроцессора, а по окончании – назад из памяти сопроцессора в основную память системы.

Offload-код данной версии будет выполняться последовательно на одном ядре сопроцессора.

Последовательное синхронное выполнение с векторизацией

Компилятор Intel по умолчанию выполняет векторизацию кода. Можно облегчить ему задачу, используя операции с массивами в формате Intel Cilk Plus Extended Array Notation.

float Sum(float *Data, int Size){
   float Ret = 0.0f;
#pragma offload target(mic) in(Data:length(Size))
   //Intel Cilk Plus Extended Array Notation
   Ret = __sec_reduce_add(Data[0:Size]);
   return Ret;
}

Offload-код данной версии будет выполняться последовательно на одном ядре сопроцессора с использованием векторных вычислений, выполняя по 16 операций сложения за одну операцию.

Последовательное асинхронное выполнение

При использовании режима Offload можно использовать технику двойной буферизации, обеспечивающую одновременное выполнение offload-функции и передачу на сопроцессор входных данных для следующего вызова и/или передачу выходных данных в память основной системы для предыдущего вызова (подробнее см. [2]). Пример программы, использующей двойную буферизацию, имеется в составе средств разработки Intel (…/C++/mic_samples/intro_sampleC/sampleC13.c)

Явное копирование памяти

Для передачи между хостом и сопроцессором сложных структур данных, например, использующих указатели, в языках C/C++ реализована модель "разделяемой памяти". Она обеспечивает размещение специальным образом маркированных переменных (квалификатор типа _Cilk_shared) по одним и тем же виртуальным адресам на хост-системе и сопроцессоре, а также включает специальные функции для динамического выделения памяти по одним и тем же адресам на хост-системе и сопроцессоре.

"Разделяемая память" не может быть реализована непосредственным отображением адресов памяти сопроцессора на адреса памяти хост-системы, эти подсистемы памяти являются полностью независимыми. Этот механизм является вариацией обычного вызова offload-кода – при выполнении вызова функции с использованием квалификатора _Cilk_offload определяется, какие изменения произошли в копии, хранящейся в памяти хост-системы, и изменения передаются в память сопроцессора (аналогично при возврате из функции).

float * _Cilk_shared Data;

_Cilk_shared float MIC_Sum(int Size) {
   float Result;

   for (int i = 0; i < Size; i++){
      Result += Data[i];
   }
   return Result;
}

int main(){
   size_t Size = 1000000;
   int MemSize;

   MemSize = Size * sizeof(float);
   Data = (_Cilk_shared float *) _Offload_shared_malloc (MemSize);
   for (int i = 0; i < Size; i++){
      Data[i] = i;
   }
   _Cilk_offload MIC_Sum(Size);
   _Offload_shared_free(Data);
   return 0;
}

Offload-код данной версии будет выполняться последовательно на одном ядре сопроцессора.

Параллельное программирование для сопроцессора Intel Xeon Phi

Большинство возможностей, доступных для хост-системы, реализованы и для Intel Xeon Phi. Вы можете использовать:

  • Intel Threading Building Blocks (Intel® TBB)
  • OpenMP*
  • Intel® Cilk Plus
  • pthreads*
  • MPI

Необходимо помнить, что потоки программ, выполняющихся на хост-системе и на сопроцессоре, являются совершенно независимыми, и можно использовать, например, OpenMP только в части программы, выполняющейся на хосте, или только в части, выполняющейся на сопроцессоре, или в обоих частях сразу.

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

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Svetlana Svetlana
Svetlana Svetlana

Здравствуйие! Я хочу пройти курс Введение в принципы функционирования и применения современных мультиядерных архитектур (на примере Intel Xeon Phi), в презентации самостоятельной работы №1 указаны логин и пароль для доступ на кластер и выполнения самостоятельных работ, но войти по такой паре логин-пароль не получается. Как предполагается выполнение самосоятельных работ в этом курсе?

Егор Кузьмин
Егор Кузьмин
Россия, г. Москва
Вера Борисова
Вера Борисова
Россия