Производительность современных графических процессоров растет гораздо быстрее производительности центральных и в настоящее время в некоторых задачах уже превосходит их на порядок. Поэтому для создания приложений с производительностью опережающей решения конкурентов компании все чаще начинают использовать этот ресурс. GPGPU - неспециализированные (т.е. связанные не только с графикой) вычисления на графических процессорах. Рассмотрим актуальные технологии для написания GPGPU приложений (CUDA, OpenCL, OpenACC и не только). В качестве критериев оценки будут выступать - функционал, скорость разработки, спектр поддерживаемых устройств, языков и компиляторов, удобство отладки и профилирования. Примером практического применения GPGPU выступит реализация алгоритма подавления шума на изображениях.
5. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Причины превосходства GPU
В CPU вычислительные блоки занимают меньшую часть
кристалла. Площадь кристалла CPU, как правило,
меньше площади GPU.
(a) i7-5960X (355
мм2, 2.6 млрд.
транзисторов)
(b) GM200 (601 мм2, 8 млрд.
транзисторов)
Рис. 1: Кристаллы CPU и GPU
6. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Причины превосходства GPU
CPU оптимизирован для выполнения однопоточных
приложений с малой задержкой:
• Большой кэш
• Длинный конвейер
• Сложные блоки предсказания ветвлений
Intel и GPGPU
Intel тоже хочет заработать на SIMD устройствах и
выпустила ряд решений на архитектуре MIC (Many
Integrated Core Architecture), который включает в себя и
относительно известный Xeon Phi, представляющий из
себя процессор имеющий до 61 x86 ядра с 16 GB GDDR5
и интерфейс PCI-e (только стоит это ∼$4000).
7. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Общее у CPU и GPU
CPU тоже является SIMD устройством — в нем
содержатся блоки, выполняющие за один такт
арифметические операции над 256-битными векторами,
что эквивалентно 16 операциям над 16-битными
числами.
Также CPU может выполнять несколько независимых
операций одновременно.
Рис. 2: Исполнительное устройство CPU Haswell
8. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
История развития видеокарт
2002-2003 гг. Выход видеокарт на чипах NV30 (NVIDIA
GeForce FX) и R300 (AMD (ATI) Radeon 9500). В
них была реализована программируемая
шейдерная архитектура второй версии,
точность вычислений значительно
повысилась, что заметно расширило область
применения.
2006 г. NVIDIA представила GeForce 8800 — первую
видеокарту с унифицированной шейдерной
архитектурой.
GeForce 8800 имел 128 унифицированных
потоковых процессоров, способных работать
с любыми данными в формате с плавающей
запятой.
9. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
История развития средств разработки
2003 г. BrookGPU — компилятор, позволивший
абстрагироваться от графического API
(OpenGL, Direct3D)
2007 г. релиз публичной бета-версии CUDA SDK
2008 г. AMD официально предоставила доступ к
Stream для массовых пользователей
2009 г. релиз Mac OS X 10.6 с поддержкой OpenCL.
Релиз NVIDIA и ATI SDK с поддержкой OpenCL
2009 г. релиз DirectX 11, включающий DirectCompute
2012 г. релиз Visual Studio с поддержкой C++AMP
2012 г. релиз Android 4.2 с поддержкой ускорения
Renderscript на GPU
2015 г. релиз GCC 5.1 с поддержкой OpenACC
10. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
CUDA
Задачи, выполняемые на GPU, представляют собой
функции со спецификатором __global__, называемые
kernel.
Синтаксис — расширенный C99/C++11.
1 __global__ void SumVectors(float const* a, float const* b, int
size, float* c)→
2 {
3 int const i = threadIdx.x + blockIdx.x * blockDim.x;
4
5 if (i >= size)
6 {
7 return;
8 }
9
10 c[i] = a[i] + b[i];
11 }
11. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Выполнение kernel
Вызов kernel аналогичен любой другой функции.
Отличие — в ”<<<...>>>” указывается конфигурация
потоков выполнения.
1 int main()
2 {
3 // ...
4 int const threadsPerBlock = 512;
5 int const blocksCount = (size - 1) / threadsPerBlock + 1;
6
7 dim3 const dimBlock(threadsPerBlock, 1, 1);
8 dim3 const dimGrid(blocksCount, 1, 1);
9
10 vecAdd<<<dimGrid, dimBlock>>>(deviceA, deviceB, size,
deviceC);→
11 }
12. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Модель выполнения I
Потоки
Выполнением kernel занимаются потоки.
Блоки
Потоки группируются в блоки.
Причина — не все потоки имеют общую быструю
разделяюмую память (shared memory) и могут
синхронизироваться, а лишь те, кто выполняется на
одном мультипроцессоре.
15. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Сборка
Для компиляции используется nvcc.
Код, выполняемый на CPU перенаправляется системному
компилятору (GCC, MS VC++).
nvcc генерирует PTX код и/или cubin.
PTX
”Ассемблер” для GPU. Во время запуска приложения
происходит трансляция в бинарный формат cubin,
подходящий GPU.
cubin
ELF-файл, содержащий код, для выполнения на GPU,
16. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Состав CUDA
Помимо Runtime и Driver API в состав CUDA входят
библиотеки:
cuBLAS реализация BLAS (Basic Linear Algebra
Subprograms)
cuFFT реализация библиотеки быстрого
преобразования Фурье
cuRand библиотека генерации случайных чисел
cuSPARSE библиотека линейной алгебры разреженных
матриц
NPP набор GPU-ускоренных функций для
обработки изображений, видео и сигналов
cuSOLVER набор решателей для плотных и
разреженных матриц
Thrust STL-подобные шаблонные интерфейсы для
некоторых алгоритмов и структур данных
17. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Системные требования I
Аппаратное обеспечение
Видеокарты NVIDIA начиная с G80 (GeForce 8800 GTX)
Спектр поддерживаемых возможностей (compute
capability) отличается для разных поколений
видеокарт.
ОС
• Windows
• Linux
• Mac OS X
Компиляторы
• Visual C++ 10.0 - Visual C++ 12.0
• GCC 4.3.4 - 4.9.2
24. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Продукты использующие CUDA I
• библиотеки
cuDNN библиотека с поддержкой GPU
примитивов для глубинных нейронных
сетей
ArrayFire библиотека C/C++/Java/Fortran,
содержащая сотни функций
используемых в арифметике, линейная
алгебре, статистике, обработке сигналов,
обработке изображений и связанных с
ними алгоритмов
OpenCV библиотека для машинного зрения,
обработки изображений и машинного
обучения
NVBIO C++ фреймворк для анализа
генетических последовательностей
HiPLAR пакеты для R, позволяющие ускорить
функции линейной алгебры
25. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Продукты использующие CUDA II
FFmpeg набор мультимедиа библиотек, которые
позволяют записывать, конвертировать и
передавать цифровые аудио- и
видеозаписи в различных форматах
NVIDIA Video Codec SDK библиотеки для аппаратного
кодирования/декодирования H.264 и
H.265
и множество других
38. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Продукты использующие OpenCL I
• библиотеки
ArrayFire библиотека C/C++/Java/Fortran,
содержащая сотни функций
используемых в арифметике, линейная
алгебре, статистике, обработке сигналов,
обработке изображений и связанных с
ними алгоритмов
Bolt STL-подобная библиотека, использующая
OpenCL или C++AMP для ускорения
алгоритмов
Boost.Compute STL-подобная библиотека,
использующая OpenCL и CUDA
clMath реализации FFT и BLAS
MainConcept SDK библиотеки для аппаратного
кодирования/декодирования H.264, H.265
и MPEG-2
и множество других
39. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
OpenACC I
OpenACC (Open Accelerators) — программный стандарт
для параллельного программирования.
Как и в OpenMP для указания участков кода,
выполняющихся параллельно, используются директивы
компилятора.
Отличие — код может выполняться как на CPU так и на
GPU.
1 void SumVectors(float const * a, float const * b, int size, float
* restrict c) {→
2 #pragma acc kernels copyin(a[0:size],b[0:size]),
copyout(c[0:size])→
3 for (int i = 0; i < size; ++i)
4 {
5 c[i] = a[i] + b[i];
6 }
7 }
40. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
OpenACC II
#pragma acc kernels нижележащий блок кода будет
скомпилирован в kernel
copyin(a[0:size],b[0:size]) данные из массивов a и b
будут скопированы из локальной памяти в
память девайса
[0:size] диапазон индекса массива для
копирования
copyout(c[0:size])) данные из массива с будут
скопированы из памяти девайса в локальную
память
42. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Системные требования I
OpenACC не налагает никаких ограничений на
программное или аппаратное обеспечение.
Дело за разработчиками компиляторов.
Аппаратное обеспечение
• видеокарты NVIDIA Tesla с compute capability 2.0 и
выше
• видеокарты AMD Radeon HD Graphics 7x00
• AMD APU с AMD Radeon HD Graphics R7
• CPU
• Xeon Phi
46. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Что осталось за кадром
Кроме низкоуровневых API таких как OpenCL и CUDA
существуют и вспомогательные библиотеки,
предоставляющие алгоритмы и структуры данных,
способных использовать ресурсы GPU.
C++AMP Обертка над DirectCompute. Есть ”из
коробки” в Visual Studio с версии 2012
Thrust Входит в состав CUDA
Bolt Поддерживает OpenCL и C++AMP
Boost.Compute использует OpenCL
ArrayFire CUDA, OpenCL
47. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Реализация Гауссова сглаживания на CUDA
Гауссово сглаживание заключается в суммировании
значения цветовых каналов соседних пикселей с
коэффициентами равными значению функции Гаусса.
0.195
0.078 0.078
0.0780.078
0.123
0.123
0.123
0.123
Рис. 6: Коэффициенты Гаусcова сглаживания
52. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Простейшее ядро - профилирование II
Проблема
Время, затраченное на аллокацию памяти в видеокарте
(200 мс) значительно больше времени затраченного на
вычисления и передачу данных (79 мс).
Решение
Причина — инициализация контекста CUDA занимает
много времени
Инициализацию контекста можно провести
принудительно во время запуска приложения, например
вызовом cudaFree(nullptr).
54. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Ядро с использованием кэша I
Проблема
Среди наших данных есть 2 не модифицирующихся
массива — mask и src. Они, хотя и помечены как float
const *, но компилятор не может быть уверенным, что эти
массивы или их части не модифицируется (например,
из-за перекрывающихся областей). Поэтому
кэшироваться данные в них не будут.
Решение
Пометить аргумент как __restrict__
NVIDIA Visual Profiler позволяет получить подробную
информацию об использовании ресурсов (и даже дать
советы по поводу оптимизации производительности).
56. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Ядро с использованием кэша III
Время выполнения ядра снизилось с 9 мс до 1.6 мс
Суммарное время выполнения — с 79 мс до 56 мс.
1 __global__ void GaussianGpuKernel(float const * __restrict__ src,
float const * __restrict__ mask, int width, int height, float
*dst)
→
→
2 {
3 // ...
4 }
57. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Ядро с асинхронным выполнением I
Проблема
Во время копирования данных в девайс или из девайса
GPU не выполняет следующее ядро.
В итоге вычислительная мощность простаивает.
Решение
CUDA (и видеокарты на аппаратном уровне)
поддерживает параллельное копирование и выполнение
ядер (нескольких параллельно, если позволяет
мощность).
Для этого необходимо использовать стримы плюс
пометить область памяти на хосте как non pageable.
61. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Оптимизация ядра. Итоги I
Что еще можно оптимизировать:
Частота обращения к глобальной памяти Нужно
использовать shared memory, т.к. для
каждого пикселя мы запрашиваем значения
9 пикселей. А скорость памяти у видеокарты
хоть и высока (∼330 GB/s), но полной
загрузки всех ядер мы не получим.
Выравнивание доступа к памяти Оперативная память
может за один запрос отдавать до 128 байт.
Для получения максимальной пропускной
способности потоки внутри warp-а должны
обращаться к регионам памяти выровненным
на величину транзакции и последовательно.
62. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Оптимизация ядра. Итоги II
Оптимизация алгоритма Вместо использования
двухмерной матрицы с коэффициентами
можно применить последовательно 2
одномерные, что снизит число операций с
k2
wh до 2kwh, где k — ширина матрицы, w —
ширина изображения, h — высота
изображения.
Плохому алгоритму и на топовом железе
мало места.
63. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Оптимизация ядра. Итоги III
Таблица 4: Результаты выполнения асинхронного ядра
Операция Время, мс.
MemcpyAsync HostToDevice 20
MemcpyAsync DeviceToHost 18
Compute 4.8 (3 * 1.6)
Total 43 мс
CPU 500 мс (OpenMP)
Если еще раз взглянуть на результаты, то можно
заметить, что в нашем случае оптимизация ядра ничего
не даст — мы упираемся в копирование данных между
хостом и девайсом.
Задача для GPU оказалась слишком простой.
64. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Пролог Мотивация История CUDA OpenCL OpenACC Реализация Гауссова сглаживания на CUDA
Итого
Использование GPU может дать большой прирост
производительности. Но при разработке требуется
учитывать особенности программно-аппаратной
архитектуры.
Не все задачи смогут выполниться на GPU быстрее чем
на CPU (имеющие, например, множество ветвлений).
Однако GPGPU уже нашло широкое применение в
различных приложениях от научных и до мультимедиа.
И чтобы быть не хуже конкурентов необходимо уже
сегодня начать рассматривать GPGPU как реальный
способ увеличить производительность.