Графические процессоры от Nvidia соревнуются с конкурентами не только на рынке ускорителей — компания пытается потеснить поставщиков традиционных серверных процессоров, применяемых в высокопроизводительных вычислениях (High Performance Computing, HPC), где GPU, как следует, например, из списка TOP500, стали весьма популярны. Кроме того, Nvidia пропагандирует замену традиционных процессоров на GPU, сопоставляя их с процессорами х86-64 и предлагая сократить число CPU в гибридных архитектурах.

Типовые для узлов кластера двухпроцессорные серверы строятся, например, на базе Intel Xeon cемейства E5-2600 v.2 (Ivy Bridge EP), имеющих до 12 ядер, обеспечивающих работу с короткими векторами (AVX-расширение) и выдающих до 8 результатов (чисел с двойной точностью — DP, получаемых после выполнения арифметических операций с плавающей точкой) за такт. В результате в режиме Turbo Boost на частоте 3 ГГц двухпроцессорный сервер с E5-2697 v.2 может иметь пиковую производительность чуть ниже 0,6 TFLOPS против 1,4 TFLOPS в Nvidia GK110B (GPU K40) (K40 в терминологии компании — это плата, а GK110B — процессор). При этом Intel использует технологию 22 нм, а Nvidia — 28 нм при энергопотреблении (Thermal Design Power, TDP) у Intel — до 130 Вт, у К40 — до 235 Вт. Топовый процессор AMD Opteron 6386 SE имеет 16 ядер с частотой 2,8 ГГц (в режиме TurboCore половина ядер работает на частоте до 3,5 ГГц). Каждое ядро выдает четыре DP-результата на каждом такте благодаря поддержке векторных команд «умножить-и-сложить» (FMA4), что дает пиковую производительность двухпроцессорного сервера в 0,4 TFLOPS. Выигрыш GK110B в обоих случаях в 2–3 раза — на реальных традиционных приложениях может возникать конкуренция GPU и СPU. Правда, у K40 имеется ускоренный (boost) режим, и теоретическая пиковая DP-производительность достигает 1,7 TFLOPS (табл. 1). Кроме того, новейшая среда программного обеспечения GPU CUDA-6 упрощает программирование и способствует росту производительности за счет создания более эффективных программ.

Таблица 1. Технические характеристики GPU  на базе GK110/GK110B
Таблица 1. Технические характеристики GPU на базе GK110/GK110B

 

А какая ситуация с видеоплатами? Новая архитектура AMD GCN (Graphics Core Next) применяется в видеоплатах cемейства R9 для настольных приложений — от R9-270 до старшей R9-290X (ядро Hawaii XT). У Nvidia уже были ответы на базе процессора GK104, первого поколения Kepler. GK104 специально не ориентирован на HPC — его мультипроцессоры имеют гораздо меньше исполнительных устройств, чем GK110. Процессор GK110 также представлен в семействе GeForce (например, старшая модель GTX780Ti). Что касается графики для рабочих станций, то пока AMD остается на платформе FirePro S9000 (0,8 TFLOPS DP) и FirePro S10000 (двухпроцессорная, 1,5 TFLOPS). Их процессоры сильно уступают GK110.

Корпорация Intel, предлагая свои GPU, ориентируется на рынок HPC. Процессор Xeon Phi содержит до 61 ядра с частотой до 1,2 ГГц, но каждое поддерживает 512-разрядное векторное расширение, а пиковая производительность превысила 1 TFLOPS. Xeon Phi и GPU Nvidia Fermi/Kepler применяются в суперкомпьютерах.

CUDA

Одной из причин успеха линейки GPU от Nvidia была виртуальная аппаратно-программная архитектура CUDA (Compute Unified Device Architecture) [1], близкая к реальным архитектурам, поэтому использующие ее программы (в частности, на языках Си, Си++ и Фортран) могут эффективно отображаться на реальную аппаратуру GPU.

Как и сама эта аппаратура, CUDA является высокопараллельной. В ее описании используется оригинальная терминология, отражающая иерархическое построение логики выполнения на GPU.

CUDA-программа вызывает параллельные функции (kernels, ядра), включающие множество параллельно выполняемых нитей (threads). Программист или компилятор организует эти нити в блоки и решетки блоков. Каждая нить в блоке имеет личную локальную память и выполняет экземпляр ядра. Нить имеет идентификатор, знает идентификатор своего блока и решетки блоков нитей, а кроме этого, имеет программный счетчик и регистры. Локальная память нитей применяется для сохранения регистров, при вызове функций и работе с автоматическими массивами. Нити CUDA весьма «легкие» — расходы на их создание и переключение контекста очень низки.

Блок нитей включает параллельно выполняемые нити, которые синхронизируются через разделяемую память (shared memory), используемую для межнитевых коммуникаций, и через барьерную синхронизацию. Блок нитей имеет идентификатор в своей решетке блоков нитей.

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

Есть еще один, чисто программный, термин CUDA — stream, поток (очередь команд), которым управляет не планировщик GPU, а сам программист. Потоки применимы только к запуску ядер (параллельных функций) и обменам данными хоста с GPU. Их есть смысл использовать, если время расчета на GPU сопоставимо со временем обмена данными [2].

Рассмотрим теперь, как иерархия CUDA-нитей отображается в иерархию процессорных устройств CUDA [1]. Команды нитей выполняются в потоковых мультипроцессорах (SMX в Kepler, SM в Fermi), содержащих различные исполнительные устройства: CUDA-ядра (cores, не путать с ядрами — параллельными функциями), DP-устройства с плавающей запятой и др. GPU выполняет одну или более решетку блоков нитей, в которую отображаются ядра — параллельные функции. Потоковый мультипроцессор может выполнять несколько блоков нитей, а исполнительные устройства мультипроцессора (CUDA-ядра и др.) выполняют команды нитей. Мультипроцессоры являются массово-параллельными и сами работают одновременно.

Они выполняют нити в группах планирования1. Kepler SMX поддерживает группы по 32 нити. Такие группы связаны с планированием выполнения на аппаратном уровне. У различных групп планирования нити могут находиться на разных стадиях выполнения. Но только нити одной группы могут выполняться физически одновременно. Нити в составе группы планирования выполняют параллельно одну и ту же команду. Когда выполнение группы планирования задерживается из-за ожидания выполнения операции с памятью, мультипроцессор переключается на работу с другой, готовой к выполнению группы планирования.

Архитектура Kepler

На сегодня имеется три процессора GPU данной архитектуры: GK104, GK110 и GK110B.

Общая архитектура GPU Kepler достаточно близка к Fermi [2,3], а сам GPU подобен современным многоядерным микропроцессорам и содержит от 13 до 15 потоковых мультипроцессоров (SMX).

Процессорные мощности GPU cосредоточены в мультипроцессорах, содержащих каждый 192 CUDA-ядра, выполняющих целочисленные операции и операции с плавающей запятой одинарной точности. Кроме того, SMX включает 64 DP-устройства, которые, как и CUDA-ядра, поддерживают команду «умножить-и-сложить» и выдают два результата на каждом такте. Наконец, для сверхбыстрого вычисления некоторых трансцендентных функций имеются 32 специальных блока (в мультипроцессоре Fermi SM их было в восемь раз меньше). В процессоре Kepler GK104 DP-устройств в SMX в 8 раз меньше, чем в GK110, и пиковая производительность равна 0,19 TFLOPS, поэтому GK104 следует применять в первую очередь на одинарной точности.

Возросшее в разы по сравнению с Fermi число исполнительных блоков в SMX сопровождается увеличением вдвое (до 32) числа устройств загрузки/записи регистров. Пиковая производительность GPU определяется частотой их ядер и количеством SMX, точнее, для DP она определяется общим числом DP-устройств, а для SP — общим числом CUDA-ядер (табл. 1).

В SMX, кроме исполнительных устройств, имеется кэш команд (I-кэш), откуда команды через четыре планировщика групп планирования попадают в одно из восьми устройств диспетчеризации (по два на планировщик) и далее в исполнительные устройства.

Файл регистров SMX содержит 65 536 регистров размерностью 4 байта. Имеются также разделяемая память и кэш первого уровня регулируемой емкости, кэш данных «только на чтение» емкостью 48 Кбайт и 16 блоков текстур. Взаимодействие различных SMX в GPU осуществляется через межсоединение. Кроме того, общим для всех SMX является кэш второго уровня, пропускная способность которого возросла вдвое относительно Fermi. Также вдвое, до 1,5 Мбайт, увеличилась емкость этого кэша.

Внешний интерфейс у GPU — это PCI-E x16 v.2.0, что до недавнего времени ограничивало рост производительности некоторых программ. К сожалению, поддержка в два раза более высокоскоростной PCI-E x16 v.2.0 появилась только недавно в K40/GK110B. Из внешнего интерфейса команды поступают в устройство планирования на уровне блоков нитей (GigaThread Engine), а уже оттуда — в различные SMX.

GPU Kepler имеет память DRAM GDDR5 из пяти или шести банков с собственными каналами шириной 8 байт, работающими на частоте 2,6 или 3 ГГц в зависимости от модели GPU. Соответственно, поддерживается разная емкость DRAM-памяти (от 5 до 12 Гбайт) и разная пропускная способность (от 208 до 288 Гбайт/с). Эти числа относятся к выключенной поддержке режима ECC, а если его включить, то уменьшается и доступная емкость DRAM, и ее пропускная способность. Для иллюстрации: в применяемой автором плате K20c из общей емкости DRAM 5 Гбайт под обслуживание ECC уходит 0,2 Гбайт, поэтому важно достигнутое в Kepler существенное увеличение эффективности реализации ECC. Разница между производительностью с включенным и отключенным ECC на некоторых тестах разработчиков уменьшилась в среднем на 66% [1].

Ясно, что DRAM имеет большие задержки по обращению, они составляют сотни тактов. SMX выполняет много групп планирования, и пока одни группы ждут готовности данных из памяти, другие считаются, что позволяет скрыть задержки обращения в память. Данные из памяти хоста в DRAM (и обратно) попадают используя DMA (Direct Memory Access).

DRAM-память GPU выделяется в CUDA под различные специальные типы памяти: локальную память нитей, глобальную память, константную и текстурную память. Эти виды памяти в Fermi и Kepler кэшируются. Как и в Fermi, память в Kepler имеет три уровня — DRAM, кэш L2, кэш верхнего уровня L1 плюс общая для блока нитей разделяемая память и кэш только на чтение. Кэш L1 в Kepler используется только для доступа в локальную память. Загрузка из глобальной памяти может применять только кэш L2 или кэш только на чтение.

Выделенная в SMX память емкостью 64 Кбайт может быть сконфигурирована программно как разделяемая с объемом 48, 32 (этого значения в Fermi нет) или 16 Кбайт, а остальное отдается в кэш L1. Как и в L1, задержки разделяемой памяти в Kepler малы, а ее пропускная способность удвоена относительно Fermi — до 256 байт загрузки за такт CUDA-ядра. Длина строки кэшей L1 и L2 равна 128 байт [2].

Кэш «только на чтение» применяется для константной памяти, используемой для размещения небольшого объема неизменяемых данных, доступных для всех нитей. В константную память можно писать (и читать) из хоста.

В архитектуре GPU Nvidia под кэш отводится меньше площади микросхемы, чем в CPU; больше транзисторов отводится для вычислительных устройств, что позволяет быстрее наращивать производительность. В общем случае GPU оказываются эффективны при параллелизме данных, когда доля времени обращения к памяти мала по сравнению с расчетами. Зато, в отличие от обычных микропроцессоров, где программист может управлять кэшем только через команды предварительной выборки, кэш-память Kepler программно управляемая. Блоки текстур содержат текстурную память и аппаратные средства интерполяции, осуществляя аппаратную фильтрацию координат текстур, кэширование и т. п. [2].

В Kepler проведен ряд доработок в системе команд ISA. Прежде всего кардинально, примерно в четыре раза, увеличилось число доступных в каждой нити регистров — до 255, что позволяет программам, активно использующим много регистров, избегать излишнего их сохранения в локальной памяти и возможного последующего их восстановления. Так, в программе для квантовой хромодинамики это расширение позволило добиться ускорения в пять раз.

Появились в Kepler и новые команды: например, команда Shuffle позволяет передавать данные между нитями из группы планирования — ранее для этого использовалась разделяемая память, и в одной нити требовалось записать в эту память данные, а в другой — прочитать. Теперь это делается за один шаг, что попутно экономит разделяемую память. На кодах быстрого преобразования Фурье за счет использования команды Shuffle удалось поднять производительность на 6% [1].

Серьезные доработки проведены и для атомарных операций (сложение, вычитание, нахождение минимума и максимума из пары чисел, сравнение-обмен), особо важные для параллельного программирования и применяемые для корректной работы с разделяемыми ресурсами параллельных программ. Например, выполнение параллельной нитью операции чтение-модификация-запись над разделяемыми данными должно осуществляться без прерывания другими нитями. Пропускная способность атомарных операций за такт в GK110 для некоторых команд возросла почти на порядок. Атомарные операции часто могут выполняться на скорости загрузки из глобальной памяти, поэтому их можно использовать во внутренних циклах ядер (параллельных функций). Появились и новые атомарные операции, например побитовые (and, or, xor) [1,2].

Особую актуальность приобрела проблема энергопотребления/тепловыделения, и одной из целей разработки Kepler как раз и было снижение энергопотребления — в частности, была снижена тактовая частота CUDA-ядер и повышен параллелизм. При этом в Nvidia стремились не просто к снижению энергопотребления, но к максимизации производительности на ватт. При большом общем увеличении числа исполнительных устройств и возможностей SMX (табл. 1, 2) по сравнению с Fermi, тактовая частота ядер SMX (706 МГц для К20) равна частоте исходного тактогенератора, а в Fermi SM работали на его удвоенной частоте. В результате производительность на ватт возросла по сравнению с Fermi до трех раз. Для уменьшения энергопотребления были внесены усовершенствования в различные блоки GK110. В списке green500 первые по производи тельности на ватт 10 систем применяют GPU Nvidia Tesla. Например, в системе, установленной в организации автора Fermi (С2050) имел температуру около 60 градусов в режиме простоя и до 90 градусов при загрузке, то K20c без нагрузки нагревается до 29 градусов. Между тем при низкой рабочей температуре растет надежность — средний межсбойный промежуток (MTBF) в K20 составляет свыше 200 тыс. часов (табл. 1), а у К40 — почти 300 тыс.

Таблица 2. Некоторые технические характеристики GPU Fermi и Kepler
Таблица 2. Некоторые технические характеристики GPU Fermi и Kepler

 

Усовершенствования в Kepler

В Кеpler имеется еще ряд новых решений.

Динамический параллелизм. Динамический параллелизм допускает возможность для GPU генерировать работу для себя самого без вмешательства CPU. Ранее работа всегда завершалась в CPU, а результат возвращался туда же, и лишь потом CPU мог снова запускать задание в GPU. В GK110 ядро (параллельная функция) может запустить другое ядро, создать нити и управлять ими, что удобно, например, для рекурсивных алгоритмов. Программист может управлять балансировкой нагрузки, а ресурсы процессора высвобождаются.

Hyper-Q. Загрузка большого количества параллельно работающих исполнительных устройств в GPU — крайне сложная задача. Для увеличения утилизации GPU и уменьшения возможных простоев CPU блок Hyper-Q позволяет многим ядрам процессоров одновременно работать с GPU. Hyper-Q увеличивает полное число одновременных аппаратно-управляемых соединений (очередей работ) между CPU и GK110 до 32. В Fermi такое соединение было одно. Логикой одновременного выполнения очередей работ в Kepler управляет CUDA Work Distributor (CWD). Типичное применение Hyper-Q — средства распараллеливания MPI, когда n MPI-процессов могут вызвать в GPU n решеток нитей, что вполне естественно, например, в случае многоядерных процессоров.

Grid Management Unit (GMU). Модуль призван повысить утилизацию ресурсов GPU, однако в условиях динамического параллелизма эта задача усложнилась — возникла необходимость гибкого управления и диспетчеризации решеток нитей. GMU управляет как решетками, созданными CUDA (за счет динамического параллелизма), так и исходящими из хоста. Из GMU решетки передаются в блок CWD. В нем обрабатываются до 32 активных решеток нитей, готовых к диспетчеризации, что увеличивает утилизацию GPU, позволяет выполнять одновременно больше работы.

Nvidia GPUDirect. Для работы с большими объемами данных и уменьшения задержек передачи в GK110 были добавлены средства GPUDirect с поддержкой RDMA (удаленный DMA), который хорош для прямого доступа в память GPU устройств третьих поставщиков (сетевых адаптеров, адаптеров Infiniband, твердотельных дисков). GPUDirect позволяет, например, осуществлять DMA-обмен данными сетевого адаптера и GPU без использования ресурсов CPU. RDMA может применяться в кластерах для повышения эффективности посылки и получения сообщений MPI. GPUDirect обеспечивает также эффективную работу с видео при операциях Peer-to-Peer [1].

Оценки производительности

Условно тесты производительности можно разделить на три уровня. Нижний включает характеристики аппаратуры: измеренные пропускные способности, например, обменов данными между GPU и хостом, задержки и т. п. Второй уровень включает универсальные математические алгоритмы, которые часто применяются в различных приложениях, а к третьему относятся собственно приложения.

Измерения нижнего уровня — пропускной способности обменов данными между GPU и хостом — были проведены автором для GPU Fermi (С2050) и Kepler (K20c). Для Fermi использован двухпроцессорный Linux-сервер с четырехъядерными Xeon E5520/2,3 ГГц [3], а K20c работал в среде СUDA-5.5 под управлением OpenSUSE-12.3. В сервере-хосте применялся четырехъядерный Хeon E3-1240/3,3 ГГц. В K20c использован тест из состава СUDA Samples (бывший Computing SDK), для Fermi — соответствующий модуль тестовой системы SHOC. В обоих случаях применялась закрепленная (pinned) память хоста в GPU [2], поскольку иначе результаты были бы вдвое хуже. Пропускная способность передачи данных между GPU и хостом для Kepler оказалась около 6,4 Гбайт/с в каждую сторону, у Fermi — 6 Гбайт/с [3]. Это недалеко от пиковой пропускной способности PCI-E v2.0 x16 (8 Гбайт/с).

Вероятно, большинство проведенных тестов второго уровня включали умножение матриц (dgemm); достигнутая на dgemm производительность составила 1,2 и 1,1 TFLOPS для K20Х и K20 соответственно, что близко к пиковой. Эффективность GPU (доля достигнутой производительности от пиковой) возросла в Kepler до 93% против 60–65% у Fermi.

Отметим еще тесты LU-декомпозиции на К40, выполненные в известном пакете MAGMA. На размерности матрицы 36K GPU обгоняет двухпроцессорный сервер с двумя восьмиядерными процессорами Xeon E5-2670/2,6 ГГц примерно в 4 раза, при размерности 2K быстродействие уже близко к нему. Это одна из ярких иллюстраций зависимости достигаемой производительности от размера системы.

На уровне приложений, например на известной программе молекулярной динамики AMBER, ускорение K20 относительно Intel Xeon E5-2687W (два GPU, два процессора) составило 8 раз, а относительно Tesla M2090 — около 80%. Из квантово-химических приложений можно привести данные выполнения программы PDM прямого расчета матрицы плотности. Лимитирующим здесь является умножение блочно-разреженных матриц (выполняется на GPU). Расчет молекулы полиглицина с базисом около 2,8 тыс. орбиталей на K20c оказался примерно вдвое быстрее, чем на Fermi C2050 (ускорение зависит от размера блока). Однако время обменов данными GPU — хост составляет до 40% общего времени выполнения (для блоков размерностью 200).

***

Графические процессоры Nvidia быстро развиваются, и, возможно, будущая архитектура Maxwell станет очередным шагом к реализации идеи замены традиционных CPU на GPU, а для этого в GPU будет включено облегченное энергоэффективное СPU-ядро. Приведенные архитектурные и технические данные, как и результаты измерений производительности, говорят о высоких потребительских качествах GPU Kepler. Свидетельством этому стала и анонсированная недавно интеграция в системах IBM процессоров Power8 и GPU Nvidia, что вполне можно расценивать как очередное подтверждение высокого уровня зрелости технологий GPU.

Литература

  1. NVIDIA Next Generation CUDA Compute Architecture: Kepler GK110, Nvidia whitepaper, v.1.0, 2012
  2. Боресков А. В. и др. Параллельные вычисления на GPU. Архитектура и программная модель CUDA, М., МГУ, 2012, 333 с.
  3. Михаил Кузьминский. GPU для HPC — время пришло // Открытые системы. — 2011. — № 6. — С. 12-15.

Михаил Кузьминский (kus@free.net) — сотрудник ИОХ РАН (Москва). Работа поддержана РФФИ, проект 11-07-00470.

1 Термин warp  в русскоязычной литературе часто используется без перевода и пишется либо латиницей, либо кириллице. Термин применяется исключительно для продукции компании Nvidia. Аналогичные аппаратные средства в GPU AMD именуются разработчиком «wave front». В статье применяется словосочетание «группа планирования», точнее отражающее суть термина. — Прим. автора.