Intel® CilkTM Plus – общая характеристика и ключевые слова
Презентацию к лекции Вы можете скачать здесь.
Intel® CilkTM Plus
- расширение языков C/C++ (ключевые слова, расширенная векторная нотация, гиперобъекты, элементные функции);
- обеспечивает эффективный и безопасный параллелизм типа "fork-join" (операция порождения – spawn, гиперобъекты, диспетчеризация системой исполнения);
- обеспечивает векторный параллелизм (векторизация операций с сечениями массивов и элементных функций);
- Fortran (в настоящее время) не поддерживается.
Intel® CilkTM Plus поддерживается компиляторами:
- Intel (начиная с версии 12);
- GCC (начиная с версии 4.7);
- совместим с Microsoft Visual Studio.
Мультиплатформенность (Windows и Linux).
Ориентирован на "обычные" процессоры Intel, а также на ускоритель MIC (Many-Integrated-Core). GPGPU (графические ускорители) не поддерживаются.
Удобные средства работы с массивами (расширенная индексная нотация – аналог сечений массивов в языке Fortran).
Удобное использование векторных расширений команд, векторизация функций.
В Intel® CilkTM Plus сохраняется семантика последовательной программы.
Программа может выполняться как в последовательном, так и в параллельном режимах.
Параллельное выполнение возможно, если это допускает целевая платформа (достаточное количество ядер).
Пример
#include <cilk/cilk.h> void sample_qsort(int * begin, int * end) { if (begin != end) { --end; int * middle = std::partition(begin, end, std::bind2nd(std::less<int>(),*end)); std::swap(*end, *middle); // pivot to middle cilk_spawn sample_qsort(begin, middle); sample_qsort(++middle, ++end); // Exclude pivot cilk_sync; , } }
Модель программирования Intel® CilkTM Plus
Модель программирования Intel® CilkTM Plus основана на параллелизме задач.
Программа пишется в семантике последовательного программирования. Фрагменты для распараллеливания расщепляются на подзадачи, связанные отношениями подчинения ("родитель"-"потомок"). Такая реализация параллелизма иногда называется "fork-join".
Программист, использующий CilkTM Plus должен думать о том, что следует распараллелить, а не как. В этом – одно из отличий от OpenMP-программирования.
Балансировкой занимается runtime-система. Балансировка выполняется методом захвата работы. Алгоритмы диспетчеризации таковы, что их эффективность, как правило, высока.
Программист
Определяет и описывает потенциальный параллелизм.
Планировщик
Отображает его на реально существующую конфигурацию потоков.
Задачи связаны между собой отношениями подчинения. Конфигурацию приложения во время его выполнения можно изобразить в виде направленного ациклического графа (DAG).
Граф задач в Cilk-программе является динамическим – он создается и изменяется в процессе выполнения программы.
При выполнении параллельной Cilk-программы формируется очередь задач. Выполнением задач занимаются "исполнители" (workers). Это- потоки.
Их число задается с помощью переменной окружения CILK_NWORKERS:
export CILK_NWORKERS=4 (Linux/bash)
Распределение задач между потоками выполняется методом "захвата работы" – освободившийся поток выполняет очередную задачу.
Если доступен только один поток, программа выполняется как последовательная
Сериализация (выполнение программы в последовательном режиме) происходит, если степень параллелизма целевой платформы недостаточно велика.
Сериализация также происходит при использовании заголовочного файла <cilk/cilk_stub.h> и при компиляции с соответствующим ключом:
icc: -cilk-serialize icl: /Qcilk-serialize
В Microsoft Visual Studio сериализовать Cilk-программу можно так:
Properties -> C/C++ -> Language [Intel C++] -> Replace Intel Cilk Plus Keywords with Serial Equivalent
Если доступно несколько потоков, программа выполняется как параллельная.
Диспетчеризация основана на "жадных" (greedy) алгоритмах.