Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Технология NVIDIA CUDA Денис Демидов <[email protected]> МСЦ РАН, КФУ 01.12.2010 Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Параллельные вычисления на GPU GPU – мультиядерные чипы, предназначенные для параллельных вычислений Сотни скалярных процессоров Десятки тысяч одновременно выполняемых потоков Пиковая производительность 1 TFLOPS (единичная точность), 0.5 TFLOPS (двойная точность) Вычисления с параллелизмом данных Научные и инженерные расчеты на GPU получают прирост производительности в десятки и сотни раз Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Причины производительности В отличие от CPU, большая часть транзисторов отведена под арифметику/логику, а не под инструкции/кэш GPU сконструированы для одновременного применения одной и той же шейдерной функции к большому числу пикселей Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Причины производительности В отличие от CPU, большая часть транзисторов отведена под арифметику/логику, а не под инструкции/кэш GPU сконструированы для одновременного применения одной и той же шейдерной функции к большому числу пикселей объему данных Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Причины производительности В отличие от CPU, большая часть транзисторов отведена под арифметику/логику, а не под инструкции/кэш GPU сконструированы для вычислительных задач c параллелизмом данных Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Производительность CPU и GPU 1500 NVIDIA GPU (single) NVIDIA GPU (double) Intel CPU 1000 GTX 480 GFLOPS GT200 G80 500 Tesla C2050 G71 G70 NV35 NV40 NV30 0 2002 2005 Westmere Harpertown Core2 Duo 2007 2010 Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Пропускная способность 200 NVIDIA GPU Intel CPU GTX 480 GTX 285 GB/sec 150 G80 Ultra 100 G80 G71 50 NV40 NV30 Northwood 0 2004 Harpertown Woodcrest 2006 2008 Westmere 2010 Обзор NVIDIA CUDA Top500.org Программная модель Примеры программ Библиотеки Собственный опыт Обзор NVIDIA CUDA Green500.org Программная модель Примеры программ Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Прирост производительности (nvidia.com/cuda) Interactive visualization of volumetric white matter connectivity Ionic placement for molecular dynamics simulation on GPU Transcoding HD video stream to H.264 Simulation in Matlab using .mex file CUDA function Financial simulation of LIBOR model with swaptions GLAME@lab: An M-script API for linear algebra operations on GPU Ultrasound medical imaging for cancer diagnostics Highly optimized object oriented molecular dynamics Astrophysics N-body simulation Cmatch exact string matching to fins similar proteins and gene sequences Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Быстрее 6= «просто быстрее» 2-3x – «просто быстрее» Чуть больше работы, чуть меньше ожидания Не меняет ход работы 5-10x – «значительно быстрее» Стоит аппаратного обновления Стоит (частичного) переписывания программы 50-100x – «фундаментальная разница» Стоит перехода на новую платформу Стоит полного переписывания программы Уменьшает «время до открытия», приносит фундаментальные изменения в исследованиях Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ 1 Обзор NVIDIA CUDA 2 Программная модель CUDA 3 Примеры программ 4 Библиотеки 5 Собственный опыт Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Compute Unified Device Architecture Новая программно-аппаратная архитектура для вычислений на GPU CUDA Предоставляет вычислительные мощности чипов NVIDIA Минимальные расширения языка C/C++ Иерархия групп потоков Разделяемая память Барьерная синхронизация Прозрачная масштабируемость Гетерогенная последовательно-параллельная программная модель Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Гетерогенные вычисления Допустим, полноценный CPU содержит миллион транзисторов Как наиболее эффективно использовать 10 миллионов транзисторов? Код 1 CPU Последовательный Параллельный Итого Последовательный Параллельный Итого 1 сек 199 сек 200 сек 150 сек 50 сек 200 сек В основном параллельный код В основном последовательный код Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Гетерогенные вычисления Допустим, полноценный CPU содержит миллион транзисторов Как наиболее эффективно использовать 10 миллионов транзисторов? Код 1 CPU 500 ядер Последовательный Параллельный Итого Последовательный Параллельный Итого 1 сек 199 сек 200 сек 150 сек 50 сек 200 сек 5 сек 0.4 сек 5.4 сек 750 сек 0.1 сек 750 сек 1 CPU равен 50 простым паралл. ядрам В 40 раз быстрее В 3.5 раза медленнее Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Гетерогенные вычисления Допустим, полноценный CPU содержит миллион транзисторов Как наиболее эффективно использовать 10 миллионов транзисторов? Код 1 CPU 500 ядер 10 CPU Последовательный Параллельный Итого Последовательный Параллельный Итого 1 сек 199 сек 200 сек 150 сек 50 сек 200 сек 5 сек 0.4 сек 5.4 сек 750 сек 0.1 сек 750 сек 1 сек 19.9 сек 20.9 сек 150 сек 5 сек 155 сек ≈ 10x ≈ 1.3x Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Гетерогенные вычисления Допустим, полноценный CPU содержит миллион транзисторов Как наиболее эффективно использовать 10 миллионов транзисторов? Код 1 CPU 500 ядер 10 CPU 1 CPU + 450 ядер Последовательный Параллельный Итого Последовательный Параллельный Итого 1 сек 199 сек 200 сек 150 сек 50 сек 200 сек 5 сек 0.4 сек 5.4 сек 750 сек 0.1 сек 750 сек 1 сек 19.9 сек 20.9 сек 150 сек 5 сек 155 сек 1 сек 0.4 сек 1.4 сек 150 сек 0.1 сек 150 сек Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Задачи, поставленные перед CUDA Простота использования Позволить программистам сосредоточиться на параллельных алгоритмах, а не на деталях реализации языка программирования Масштабируемость Прозрачная масштабируемость на сотни ядер, тысячи параллельных потоков Возможность использования гетерогенной архитектуры CPU и GPU – различные устройства с независимой памятью Обзор NVIDIA CUDA Программная модель Примеры программ Программная модель CUDA Массивно-параллельные части кода выполняются на GPU как ядра (kernels) В каждый момент времени выполняется одно ядро Каждое ядро обрабатывается множеством потоков Отличия потоков CPU и GPU Потоки на GPU очень «легкие» Очень малое время создания Мгновенное переключение между потоками Для полноценной загрузки GPU нужны тысячи потоков Многоядерные CPU могут использовать небольшое число потоков Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Массивы параллельных потоков Ядро CUDA исполняется массивом потоков Каждый поток выполняет один и тот же код Каждый поток имеет идентификатор, который позволяет вычислить позицию в памяти и осуществлять ветвления Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Взаимодействие потоков Взаимодействие потоков необходимо Разделение результатов, чтобы избежать ненужных вычислений Совместный доступ к памяти Снижает требования к пропускной способности Взаимодействие между всеми потоками снижает масштабируемость Взаимодействие потоков внутри небольших независимых групп — масштабируемо Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Взаимодействие потоков Взаимодействие потоков необходимо Разделение результатов, чтобы избежать ненужных вычислений Совместный доступ к памяти Снижает требования к пропускной способности Взаимодействие между всеми потоками снижает масштабируемость Взаимодействие потоков внутри небольших независимых групп — масштабируемо Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Объединение потоков в блоки Ядро запускает на выполнение решетку (grid) блоков потоков (thread blocks) Потоки внутри блока взаимодействуют посредством разделяемой памяти Потоки внутри блока могут синхронизироваться Потоки, находящиеся в различных блоках, не могут взаимодействовать Такая модель позволяет прозрачно масштабировать программы на различные GPU Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Прозрачная масштабируемость Ядро масштабируется на различные GPU Блоки потоков назначаются для выполнения на любой из доступных мультипроцессоров Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Архитектура 10-го поколения (GT200) 240 потоковых процесcоров (thread processors) выполняют потоки ядра Каждый потоковый процессор может одновременно выполнять до 96 потоков (240 × 96 = 23 040) 30 мультипроцессоров; каждый содержит: 8 потоковых процессоров Блок двойной точности Разделяемую память Текстурный процессор Обзор NVIDIA CUDA Программная модель Доступ к памяти в CUDA На уровне потока На уровне блока На уровне ядра Примеры программ Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Исполнение кода Потоки выполняются потоковыми процессорами Блоки потоков выполняются мультипроцессорами Блоки не мигрируют между мультипроцессорами Число блоков, одновременно выполняющихся на мультипроцессоре, ограничено ресурсами (регистры и разделяемая память) Ядро выполняется как решетка блоков потоков Устройство в каждый момент времени может выполнять только одно ядро Обзор NVIDIA CUDA Программная модель Примеры программ 1 Обзор NVIDIA CUDA 2 Программная модель CUDA 3 Примеры программ 4 Библиотеки 5 Собственный опыт Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Умножение вектора на число Последовательный код Функция 1 2 3 4 5 void vecmul(float *vec, float a, int n) { for(int i = 0; i < n; i++) { vec[i] *= a; } } Вызов функции 1 2 3 4 5 int n = 1000; float a = 2.0; float *vec = new float[n]; ... vecmul(vec, a, n); Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Умножение вектора на число Код на CUDA Ядро 1 2 3 4 global void vecmul(float *vec, float a, int n) { int i = blockIdx.x * blockDim.x + threadIdx.x; if (i < n) vec[i] *= a; } Вызов ядра 1 2 3 4 5 6 7 8 9 int n = 1000; float a = 2.0; float *vec h = new float[n]; ... float *vec d; cudaMalloc((void**)&vec d, n * sizeof (float)); cudaMemcpy(vec d, vec h, n * sizeof (float), cudaMemcpyHostToDevice); vecmul<<<4, 256>>>(vec d, a, n); cudaMemcpy(vec h, vec d, n * sizeof (float), cudaMemcpyDeviceToHost); Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Подсчет невязки Невязка уравнения −∆h u = f ri,j = fi,j − (4ui,j − ui,j−1 − ui−1,j − ui,j+1 − ui+1,j ) /h2 Простейшая реализация 1 2 3 4 5 6 7 8 9 10 global int i int j int k void resid(float *u, float *f, float *r, int n) { = blockIdx.x * blockDim.x + threadIdx.x; = blockIdx.y * blockDim.y + threadIdx.y; = j * n + i; if ((i > 0) && (i < n−1) && (j > 0) && (j < n−1)) { float h = 1.0 / (n−1); r[k] = f[k] − (4 * u[k] − u[k−n] − u[k−1] − u[k+1] − u[k+n]) / (h*h); } } Обзор NVIDIA CUDA Программная модель Примеры программ Подсчет невязки Конфигурация и вызов ядра 1 2 3 4 5 6 7 8 9 10 11 12 n = 32; block size(8, 8); grid size( n / block size.x, n / block size.y ); float *u, *f, *r; cudaMalloc((void**)&u, n * n * sizeof (float)); cudaMalloc((void**)&f, n * n * sizeof (float)); cudaMalloc((void**)&r, n * n * sizeof (float)); ... resid<<<grid size, block size>>>(u, f, r, n); int dim3 dim3 Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Подсчет невязки Использование разделяемой памяти 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #define BLOCK DIM 8 global void resid(float *u, float *f, float *r, int n) { shared float buf[BLOCK DIM+2][BLOCK DIM+2]; int i = blockIdx.x * blockDim.x + threadIdx.x; int j = blockIdx.y * blockDim.y + threadIdx.y; int tx = threadIdx.x + 1; int ty = threadIdx.y + 1; int k = j * n + i; if ((i < n) && (j < n)) { buf[tx][ty] = u[k]; if ((tx == 1) && (i > 0)) buf[tx−1][ty] if ((tx == BLOCK DIM) && (i < n−1)) buf[tx+1][ty] if ((ty == 1) && (j > 0)) buf[tx][ty−1] if ((ty == BLOCK DIM) && (j < n−1)) buf[tx][ty+1] } syncthreads(); if ((i > 0) && (i < n−1) && (j > 0) && (j < n−1)) { float h = 1.0 / (n−1); r[k] = f[k] − (4 * buf[tx][ty] − buf[tx][ty−1] − buf[tx−1][ty] − buf[tx+1][ty] − buf[tx][ty+1]) / (h*h); } } = = = = u[k−1]; u[k+1]; u[k−n]; u[k+n]; Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Результаты оптимизации Время выполнения снизилось в два раза Реальная конфигурация Матрица 1024 × 1024 Блок 16 × 16 потоков Решетка 64 × 64 блоков Простейшая реализация Доступ к глобальной памяти/блок 16 × 16 × 7 = 1792 Время выполнения 12763 µsec Использование разделяемой памяти Доступ к глобальной памяти/блок 16 × 16 × 3 + 16 × 4 = 832 Время выполнения 6326 µsec Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Библиотеки и программные пакеты CUBLAS CUFFT CURAND CUSPARSE CUDPP (code.google.com/p/cudpp) Thrust (code.google.com/p/thrust) HOOMD (codeblue.umich.edu/hoomd-blue) MAGMA (icl.cs.utk.edu/magma) CULA (www.culatools.com) Matlab Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ 1 Обзор NVIDIA CUDA 2 Программная модель CUDA 3 Примеры программ 4 Библиотеки 5 Собственный опыт Библиотеки Собственный опыт Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Задачи вычислительной гидродинамики1 Сеточные методы Реализован алгебраический многосеточный метод. Ускорение при использовании 3х GPU Tesla C1060 — 40 раз (сетка — 42 млн. узлов) Метод частиц Ускорение при использовании 3х GPU Tesla C1060 — 950 раз (число вихрей — 16384) 1 Д. Е. Демидов, А. Г. Егоров, А. Н. Нуриев. Решение задач вычислительной гидродинамики с применением технологии NVIDIA CUDA // Ученые записки Казанского государственного университета. Серия Физико-математические науки. — 2010. — Т. 152, No 1. — С. 142–154. Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Моделирование микросейсмического поля2 Проведены вычислительные эксперименты как на суперкомпьютере МСЦ РАН МВС100К, так и с использованием технологии CUDA. Производительность 1 Tesla C1060 соответствует ≈ 40 − 50 узлам МВС100К Использовался Java-интерфейс JCuda (www.jcuda.org) 2 М. Р. Галимов, Е. В. Биряльцев. Некоторые технологические аспекты применения высокопроизводительных вычислений на графических процессорах в прикладных программных системах // Вычислительные методы и программирование — 2010. — Т. 11. — Стр. 77–93. Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Моделирование аэрозольных течений с учетом броуновского движения частиц3 Используется 1 GPU Tesla C1060 3 Т. Ш. Зарипов, НИИММ им. Н. Г. Чеботарева, отдел гидромеханики Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Собственный опыт Гранты РФФИ В 2009, 2010 получены гранты РФФИ на развитие МТБ GPU кластер 4 узла: CPU: Intel Core i7 920 ОЗУ: 24 ГБ DDR3 GPU: 3x Nvidia Tesla C2070 (6 ГБ) NVIDIA: Пиковая производительность 12 GPU Fermi в двойной точности составляет 6.18 ТФлопс, производительность по Linpack будет на 35-45% ниже. Российский Top50? Обзор NVIDIA CUDA Программная модель Примеры программ Библиотеки Курс лекций: http://193.232.252.98:3000 Собственный опыт