Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Исследование параллелизма при решении двухточечной краевой задачи на графических ускорителях NVIDIA (магистерская диссертация).docx
Скачиваний:
66
Добавлен:
28.06.2014
Размер:
1.59 Mб
Скачать

1.3.OpenAcc. Новейший стандарт разработкиGpgpu-приложений

OpenACC– открытый стандарт, описывающий набор директив компилятору, процедур и переменных среды для выгрузки участков кода программ, написанных на языкахC/C++ иFortran, с хоста на ускоритель.OpenACCпредоставляет высокоуровневую модель программирования, не зависящую от ОС и модели ускорителя. Модель программированияOpenACCпозволяет программисту с помощью директив увеличить информацию, доступную компилятору и касающуюся выполняемых на ускорителе участков кода и выделения памяти.

1.3.1. Возможности стандарта

Благодаря многообещающему соотношению производительности на ватт потребляемой энергии и привлекательной цене, архитектура высокопроизводительных вычислений (high-performancecomputing,HPC) сегодня развивается в сторону гетерогенных вычислительных систем, содержащих ускорители с ядрами общего назначения. Однако, программирование ускорителей с использованием низкоуровневыхAPIявляется трудной задачей, может осложнить проектирование программного обеспечения и, обычно, удваивает код для ускорителя конкретного производителя. Это приводит к непродуктивному процессу разработки, подверженному ошибкам программированию задач и узким аппаратно-специфичным реализациям, что неприемлемо для крупных проектов с длительным сроком жизни кода.

Последние разработки обещают возложить на компилятор ответственность за многие низкоуровневые задачи, предлагая основанные на директивах высокоуровневые API. Нахождение частей алгоритма, которые могут быть эффективно выполнены на ускорителе, по-прежнему возложено на программиста, новые подходы не упрощают программирование ускорителей в целом. Однако, они повышают продуктивность процесса разработки и упрощают поддержку кода. Унифицировав синтаксис различных подходов на основе директив с намерением сделать его доступным для различных производителей, группа членов сообществаOpenMPLanguageCommitteeопубликовала стандартOpenACCв ноябре 2011 года [7]. СтандартOpenACC, разработка которого была инициирована компаниямиCPAS,CRAY,NVIDIAиPGI, позволяет выгружать участки кода, написанного на языкахC/C++ иFortran, на ускоритель.

Основанный на директивах OpenACCAPIдляC/C++ иFortranвозлагает на компилятор ответственность на низкоуровневые задачи программированияGPU, обеспечивая совместимость между различными ОС, центральными процессорами и графическими ускорителями. Однако, что касается ускорителей, на данный момент существующие реализацииOpenACCподдерживают толькоNVIDIAGPU.

OpenACCAPIпредлагает программную модель, в которой главная программа запускается на хосте и участки кода с высокой вычислительной интенсивностью выгружаются на ускоритель. Модель памяти основана на раздельной памяти хоста и ускорителя.GPUреализуют слабую модель памяти (weakmemorymodel), которая запрещает когерентность памяти между операциями для различных вычислительных блоков и разрешает когерентность в одном и том же вычислительном блоке только с помощью явной синхронизации.

1.3.2. Модель выполнения

Большая часть GPGPU‑программы выполняется на хосте. Те участки кода, где идут объёмные и затратные по времени вычисления, выгружаются на ускоритель; это происходит под контролем и управлением хоста. Ускоритель выполняет параллельные участки программы, которые, обычно, содержат циклы. Даже на этих участках хост может инициировать выделение памяти на ускорителе, передачу данных на ускоритель, передачу аргументов, передачу результатов вычислений обратно на хост, освобождение памяти.

Большинство современных ускорителей поддерживают два или три уровня параллелизма. Большинство ускорителей поддерживают крупнозернистый параллелизм, полностью распараллеливая выполнение между вычислительными блоками. При крупнозернистом параллелизме может присутствовать ограниченная поддержка синхронизации между операциями. Многие ускорители также поддерживают мелкозернистый параллелизм, часто реализованный через множество нитей внутри одного вычислительного блока. Наконец, большинство ускорителей также поддерживают SIMDили векторные операции внутри каждого вычислительного блока. Модель выполнения [8] комбинирует эти уровни параллелизма на ускорителе. Полностью параллельный цикл (без зависимостей между итерациями) может быть запрограммирован для крупнозернистого параллельного выполнения. Циклы с зависимостями либо программируются для выполнения на одном вычислительном блоке, используя мелкозернистый параллелизм, векторный параллелизм или последовательно, либо эти зависимости должны быть разрешены.

В OpenACCэти три уровня параллелизма обозначаются какгрупповой- (gang),вокер- (worker) ивекторный (vector) параллелизм. Групповой – это крупнозернистый параллелизм. Множество групп запускается на ускорителе. Вокер – это мелкозернистый параллелизм. Каждая группа может содержать один или больше вокеров. Векторный параллелизм применяется дляSIMDили векторных операций внутри вокера.

Во время выполнения участка кода на ускорителе одна или более групп запущены, каждая группа с одним или более вокером, где каждый вокер может иметь возможность векторного выполнения с одной или более векторными полосами (vectorlanes) [8]. Группа начинает выполнение в режимеgang-redundant(GRmode), подразумевающий одну векторную полосу в одном вокере и по одному вокеру в каждой группе, выполняющей один и тот же код. Когда выполнение программы доходит до цикла, помеченного для распараллеливания на уровне групп (gang-levelwork-sharing), выполнение программы переходит в режимgang-partitioned (GPmode), в котором итерации цикла или циклов разбиваются между группами для параллельного выполнения, но всё ещё только с одной векторной полосой в каждом вокере и одним вокером на группу.

Когда только один вокер активен, в GRилиGPрежиме, выполнение программы находится вworker-singleрежиме (WSmode). Когда только одна векторная полоса активна, выполнение программы находится вvector-singleрежиме (VSmode). Если группа достигает цикла, помеченного для распараллеливания на уровне вокеров (worker-levelwork-sharing), группа переходит в режимworker-partitioned(WPmode), который активирует все вокеры в группе. Итерации цикла разделяются между вокерами в группе. Если один цикл помечен дляGPиWPрежимов, тогда итерации цикла распределяются между всеми вокерами всех групп. Если вокер достиг цикла, помеченного для распараллеливания на векторном уровне (vector-levelwork-sharing), он переходит вvector- partitioned (VPmode). Переход вVPрежим активирует все векторные полосы вокера. Итерации цикла или циклов будут разделены между векторными полосами, используя векторные илиSIMDоперации. Один цикл может быть помечен для одного, двух или всех трёх видов параллелизма, и итерации этого цикла могут быть распределены по группам, вокерам и векторным полосам в случае необходимости.

Программа начинает своё выполнение с единственной нити. Нить может порождать другие нити, например, с помощью OpenMPAPI. На ускорителе одна векторная полоса одного вокера одной группы называется нитью. При выполнении программы на устройстве, контекст параллельного выполнения создаётся и может содержать множество таких нитей.

При написании программ на OpenACCпрограммист не должен пытаться реализовывать барьерную синхронизацию и блокировки, будь то при групповом-, вокер- и векторном параллелизме. Модель выполнения позволяет реализации, которая выполняет несколько групп, завершить их перед началом выполнения других групп. Это означает, что попытка реализовать синхронизацию между группами, скорее всего, закончится неудачей. В частности, барьерная синхронизация между группами не может быть реализована, так как все группы не всегда могут быть активными одновременно. Аналогично, модель выполнения позволяет реализации, которая выполняет несколько вокеров внутри группы или несколько векторных полос внутри вокера, завершить их перед началом выполнения других вокеров или векторных полос, или приостановить выполнение некоторых вокеров или векторных полос, ожидая завершения других вокеров или векторных полос. Это означает, что попытка реализовать синхронизацию между вокерами или векторными полосами, скорее всего, приведёт к неудаче.

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

Большинство ускорителей могут работать асинхронно по отношению к нити хоста (hostthread). В таких случаях, ускоритель имеет одну или несколько очередей активности (activityqueues). Нить хоста будет ставить в очередь активности на ускорителе такие операции, как перемещение данных и выполнение процедур. После того, как операция поставлена в очередь, нить хоста может продолжать своё выполнение, в то время, как ускоритель работает независимо и асинхронно. Нить хоста может запрашивать очередь (или очереди) активности ускорителя и ждать завершения всех операций в очереди. Одна операция из очереди активности ускорителя должны быть завершена перед началом выполнения следующей операции из той же очереди; операции из разных очередей активности могут выполняться одновременно и могут быть завершены в любом порядке.