Лекция 9. Программирование gpu
DESCRIPTION
Программирование GPU (NVIDIA CUDA)TRANSCRIPT
![Page 1: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/1.jpg)
Курносов Михаил Георгиевич
E-mail: [email protected]: www.mkurnosov.net
Курс “Высокопроизводительные вычислительные системы”Сибирский государственный университет телекоммуникаций и информатики (Новосибирск)Осенний семестр, 2014
Лекция 9Программирование GPU
![Page 2: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/2.jpg)
Graphics Processing Unit (GPU) – графический процессор, специализированный многопроцессорный ускоритель с общей памятью
Большая часть площади чипа занята элементарными ALU/FPU/Load/Store модулями
Устройство управления (Control unit) относительно простое по сравнению с CPU
NVIDIA GeForce GTX 780 (Kepler, 2304 cores, GDDR5 3 GB)
AMD Radeon HD 8970(2048 cores, GDDR5 3 GB)
GPU – Graphics Processing Unit
![Page 3: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/3.jpg)
Гибридные вычислительные узлы
Несколько GPU
CPU управляет GPU через драйвер
Узкое место –передача данных между памятью CPU и GPU
GPU не является bootable-устройством
74 системы из Top500 (Nov. 2014) оснащены ускорителями (NVIDIA, ATI, Intel Xeon Phi, PEZY SC )
CPU1
Core1 Core2 Core3 Core4
GPU1
Cores
GPU Memory
Memory (DDR3) Memory (DDR3)
QPI
I/O Hub
QPI QPI
PCI Express Gen. 2
CPU1
Core1 Core2 Core3 Core4
GPU1
Cores
GPU Memory
![Page 4: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/4.jpg)
Кластер Jet
Три узла с GPU (CUDA, MPI + CUDA):
cngpu1 – NVIDIA GeForce GTX 680
cngpu2 – 2 x NVIDIA GeForce 210
cngpu3 – NVIDIA GeForce GT 630
http://cpct.sibsutis.ru/index.php/Main/CUDAGTX680
![Page 5: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/5.jpg)
NVIDIA CUDA
55
NVIDIA CUDA – программно-аппаратная
платформа для организации параллельных
вычислений на графических процессорах
(Graphic processing unit – GPU)
http://developer.nvidia.com/cuda
NVIDIA CUDA SDK:
o архитектура виртуальной машины CUDA
o компилятор C/C++
o драйвер GPU
ОС: GNU/Linux, Apple Mac OS X, Microsoft Windows
2014 – CUDA 6.5 (+ 64-bit ARM, Unified memory, Multi-GPU)
2006 – CUDA 1.0
![Page 6: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/6.jpg)
Архитектура NVIDIA CUDA
66
CUDA C/C++/Fortran Source
CUDA C/C++/Fortran Compiler(NVIDIA nvcc, PGI pgfortran)
PTX (Parallel Thread Execution)(NVIDA GPU assembly language)
GPU Driver (JIT compiler)
GPU binary code
Host (CPU)
Device (GPU)
CPU Code
![Page 7: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/7.jpg)
Архитектура NVIDIA CUDA
77
NVIDIA C/C++ Compiler (nvcc) – компилятор
c расширений языков C/C++ (основан на LLVM), генерирует
код для CPU и GPU
NVIDA PTX Assembler (ptxas)
Набор команд PTX развивается:
PTX ISA 3.2 (2013), PTX ISA 3.1 (2012), PTX ISA 4.1 (2014)
Архитектуры NVIDIA CUDA
o NVIDIA Tesla (2007)
o NVIDIA Fermi (GeForce 400 Series, 2010)
o NVIDIA Kepler (GeForce 600 Series, 2012)
o NVIDIA Maxwell (GeForce 700 Series, 2014)
http://docs.nvidia.com/cuda/parallel-thread-execution/index.html
![Page 8: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/8.jpg)
Гетерогенные вычислительные узлы
88
CPU1
Core1 Core2 Core3 Core4
GPU1
Cores
GPU Memory
Memory (DDR3) Memory (DDR3)
QPI
I/O Hub
QPI QPI
PCI Express Gen. 2
CPU1
Core1 Core2 Core3 Core4
GPU1
Cores
GPU Memory
![Page 9: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/9.jpg)
Гетерогенные вычислительные узлы
99
NVIDIA Tesla K10 (2 GPU)
Процессорные ядра: 2 GPU NVIDIA GK104 (2 x 1536 ядер)
Архитектура: NVIDIA Kepler
RAM: 8GB GDDR5
PCI Express 3.0
![Page 10: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/10.jpg)
Архитектура NVIDIA Kepler (GK110)
1010
15 SMX – streaming multiprocessor
(возможны конфигурации с 13 и 14 SMX)
6 контроллеров памяти (64-бит)
Интерфейс подключения к хосту PCI Express 3.0
![Page 11: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/11.jpg)
Архитектура NVIDIA Kepler (GK110)
1111
![Page 12: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/12.jpg)
Архитектура NVIDIA Kepler (GK110)
1212
SMX –streaming
multiprocessor
![Page 13: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/13.jpg)
Архитектура SMX (GK110)
1313
192 ядра для выполнения операций с одинарной
точностью (single precision float, integer)
64 модуля двойной точности (double precision, FMA)
32 модуля специальных функций (SFU)
32 модуля чтения/записи (LD/ST)
4 планировщика потоков (warp schedulers)
![Page 14: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/14.jpg)
Архитектура SMX (GK110)
1414
![Page 15: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/15.jpg)
Warp scheduler (GK110)
1515
Планировщик организует потоки в группы по 32 (warps)
Потоки группы выполняются одновременно
Каждый такт потоки группы (warp) выполняют две независимые инструкции (допустимо совмещение инструкций double и float)
![Page 16: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/16.jpg)
Warp scheduler (GK110)
1616
![Page 17: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/17.jpg)
Организация памяти Kepler (GK110)
1717
Каждый SMX имеет 64KB памяти:
o 48KB shared + 16KB L1 cacheo 16KB shared + 48KB L1 cache
L2 Cache 1536KB –общий для всех SMX
Global Memory 8GB
![Page 18: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/18.jpg)
Архитектура NVIDIA Kepler (GK110)
1818
FERMIGF100
FERMIGF104
KEPLERGK104
KEPLERGK110
Compute Capability 2.0 2.1 3.0 3.5
Threads / Warp 32 32 32 32
Max Warps / Multiprocessor 48 48 64 64
Max Thread Blocks / Multiprocessor
8 8 16 16
Max Threads / Thread Block 1024 1024 1024 1024
32‐bit Registers / Multiprocessor
32768 32768 65536 65536
Max Registers / Thread 63 63 63 255
Max X Grid Dimension 2^16‐1 2^16‐1 2^32‐1 2^32‐1
Hyper‐Q No No No Yes
Dynamic Parallelism No No No Yes
![Page 19: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/19.jpg)
NVIDIA Maxwell (2014)
1919
NVIDIA Maxwell = GPU Cores + ARM Core
Интегрированное ядро ARM (64 бит, проект Denver)
o возможность загрузки операционной системы на GPU
o поддержка унифицированной виртуальной памяти (device ←→ host)
![Page 20: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/20.jpg)
Основные понятия CUDA
2020
Хост (host) – узел с CPU и его память
Устройство (device) – графический процессор
и его память
Ядро (kernel) – это фрагмент программы,
предназначенный для выполнения на GPU
Пользователь самостоятельно запускает с CPU
ядра на GPU
Перед выполнением ядра пользователь копирует данные
из памяти хоста в память GPU
После выполнения ядра пользователь копирует данные
из памяти GPU в память хоста
![Page 21: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/21.jpg)
Основные понятия CUDA
2121
CPU (Host) GPU (Device)
void kernelA(){
/* Code */}
void kernelB(){
/* Code */}
/* Serial code */
/* Serial code */
/* Serial code */
kernelA()
kernelB()
![Page 22: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/22.jpg)
Выполнение CUDA-программы
2222
CPU (Host)
CPU
Memory
PCI Express GPU (Device)
Memory
Копирование данных из памяти хоста в память GPU
![Page 23: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/23.jpg)
Выполнение CUDA-программы
2323
CPU (Host)
CPU
Memory
PCI Express GPU (Device)
Memory
Копирование данных из памяти хоста в память GPU
Загрузка и выполнение ядра (kernel) в GPU
![Page 24: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/24.jpg)
Выполнение CUDA-программы
2424
CPU (Host)
CPU
Memory
PCI Express GPU (Device)
Memory
Копирование данных из памяти хоста в память GPU
Загрузка и выполнение ядра (kernel) в GPU
Копирование данных из памяти GPU в память хоста
![Page 25: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/25.jpg)
CUDA HelloWorld!
2525
#include <stdio.h>
__global__ void mykernel() {
/* Parallel GPU code (kernel) */ }
int main() {
mykernel<<<1, 1>>>();
return 0;}
![Page 26: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/26.jpg)
CUDA HelloWorld!
2626
$ nvcc -c -o prog.o ./prog.cu
$ g++ ./prog.o –o prog -L/opt/cuda-5.5/lib64 \
-lcudart
![Page 27: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/27.jpg)
Вычислительные ядра (kernels)
2727
Спецификатор __global__ сообщает компилятору,
что функция предназначена для выполнения на GPU
Компилятор nvcc разделяет исходный код –
ядра компилируются nvcc, а остальной код системным
компилятором (gcc, cl, …)
Тройные угловые скобки “<<< >>>” сообщают о вызове
ядра на GPU и количестве требуемых потоков
Вызов ядра (kernel) не блокирует выполнение потока
на CPU
Функция cudaThreadSynchronize() позволяет реализовать
ожидание завершения ядра
![Page 28: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/28.jpg)
Вычислительные потоки (threads)
2828
Номер потока (thread index) – это трехкомпонентный
вектор (координаты потока)
Потоки логически сгруппированы в одномерный,
двухмерный или трёхмерный блок (thread block)
Количество потоков в блоке ограничено (в Kepler 1024)
Блоки распределяются по потоковым
мультипроцессорам SMX
Предопределенные переменные
o threadIdx.{x, y, z} – номер потока
o blockDim.{x, y, z} – размерность блока
Thread Block
Thread Thread Thread
Thread Thread Thread
![Page 29: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/29.jpg)
Вычислительные потоки (threads)
2929
Блоки группируются одно- двух- и трехмерную
сетку (grid)
Блоки распределяются по потоковым мультипроцессорам
SMX (в Kepler 15 SMX)
Предопределенные переменные
o blockIdx.{x, y, z} – номер блока потока
o gridDim.{x, y, z} – размерность сетки
![Page 30: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/30.jpg)
Вычислительные потоки (threads)
3030
Grid of thread blocks
Thread Block
Thread Thread Thread
Thread Thread Thread
Thread Block
Thread Thread Thread
Thread Thread Thread
Thread Block
Thread Thread Thread
Thread Thread Thread
Thread Block
Thread Thread Thread
Thread Thread Thread
Thread Block
Thread Thread Thread
Thread Thread Thread
Thread Block
Thread Thread Thread
Thread Thread Thread
gridDim.y
gridDim.x
blockDim.xblockDim.z
blockDim.y
![Page 31: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/31.jpg)
CUDA Program
Выполнение CUDA-программы
3131
Block 0 Block 1 Block 2
Block 3 Block 4 Block 5
GPU 1
Block 0 Block 1
Block 2 Block 3
Block 4 Block 5
SMX 1 SMX 2
GPU 2
Block 0 Block 1 Block 2
Block 3 Block 4 Block 5
SMX 1 SMX 2 SMX 3
![Page 32: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/32.jpg)
Пример: сложение векторов
3232
void vecadd(float *a, float *b, float *c, int n){
int i;
for (i = 0; i < n; i++) {c[i] = a[i] + b[i];
}}
![Page 33: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/33.jpg)
Пример: сложение векторов
3333
int main() {
int i, n = 100;float *a, *b, *c;float *deva, *devb, *devc;
a = (float *)malloc(sizeof(float) * n);b = (float *)malloc(sizeof(float) * n);c = (float *)malloc(sizeof(float) * n);for (i = 0; i < n; i++) {
a[i] = 2.0;b[i] = 4.0;
}
![Page 34: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/34.jpg)
Пример: сложение векторов
34
// Выделяем память на GPUcudaMalloc((void **)&deva, sizeof(float) * n);cudaMalloc((void **)&devb, sizeof(float) * n);cudaMalloc((void **)&devc, sizeof(float) * n);
// Копируем из памяти узла в память GPUcudaMemcpy(deva, a, sizeof(float) * n,
cudaMemcpyHostToDevice);cudaMemcpy(devb, b, sizeof(float) * n,
cudaMemcpyHostToDevice);
vecadd_gpu<<<1, n>>>(deva, devb, devc);
cudaMemcpy(c, devc, sizeof(float) * n, cudaMemcpyDeviceToHost);
cudaFree(deva); cudaFree(devb); cudaFree(devc);free(a); free(b); free(c);
return 0;} 34
![Page 35: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/35.jpg)
Пример: сложение векторов
35
__global__ void vecadd_gpu(float *a, float *b, float *c) {
// Каждый поток обрабатывает один элементint i = threadIdx.x;c[i] = a[i] + b[i];
}
35
Запускается один блок из n потоков (n <= 1024)
vecadd_gpu<<<1, n>>>(deva, devb, devc);
Каждый поток вычисляет один элемент массива c
Thread Block
Thread 0 Thread 1 Thread n - 1…
![Page 36: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/36.jpg)
Пример: сложение векторов
3636
Сложение векторов с количеством элементов > 256
int threadsPerBlock = 256; /* Device specific */
int blocksPerGrid = (n + threadsPerBlock - 1) /
threadsPerBlock;
vecadd_gpu<<<blocksPerGrid, threadsPerBlock>>>(deva,
devb, devc, n);
Будет запущена группа блоков, в каждом блоке по фиксированному количеству потоков
Потоков может быть больше чем элементов в массиве
![Page 37: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/37.jpg)
Пример: сложение векторов
3737
__global__ void vecadd_gpu(float *a, float *b,
float *c, int n)
{
int i = threadIdx.x + blockIdx.x * blockDim.x;
if (i < n)
c[i] = a[i] + b[i];
}
Thread Block 0
Thread 0 Thread 1 Thread ……
Thread Block 1
Thread 0 Thread 1 Thread ……
Thread Block 2
Thread 0 Thread 1 Thread ……
Thread Block 3
Thread 0 Thread 1 Thread ……
![Page 38: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/38.jpg)
Двухмерный блок потоков
3838
dim3 threadsPerBlock(N, N);
matrix<<<1, threadsPerBlock>>>(A, B, C);
Двухмерный блок потоков (threadIdx.x, threadIdx.y)
![Page 39: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/39.jpg)
Информация о GPU
3939
cudaSetDevice(0);
cudaDeviceProp deviceProp;
cudaGetDeviceProperties(&deviceProp, 0);
/*
* deviceProp.maxThreadsPerBlock
* deviceProp.warpSize
* devProp.totalGlobalMem
* ...
*/
![Page 40: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/40.jpg)
NVIDIA GeForce GTS 250
4040
CUDA Device Query (Runtime API) version (CUDART static linking)
Device 0: "GeForce GTS 250"
CUDA Driver Version: 3.20
CUDA Runtime Version: 3.20
CUDA Capability Major/Minor version number: 1.1
Total amount of global memory: 1073020928 bytes
Multiprocessors x Cores/MP = Cores: 16 (MP) x 8 (Cores/MP) =
128 (Cores)
Total amount of constant memory: 65536 bytes
Total amount of shared memory per block: 16384 bytes
Total number of registers available per block: 8192
Warp size: 32
Maximum number of threads per block: 512
Maximum sizes of each dimension of a block: 512 x 512 x 64
Maximum sizes of each dimension of a grid: 65535 x 65535 x 1
Maximum memory pitch: 2147483647 bytes
Texture alignment: 256 bytes
Clock rate: 1.91 GHz
Concurrent copy and execution: Yes
Run time limit on kernels: Yes
Support host page-locked memory mapping: Yes
Compute mode: Default (multiple host
threads can use this device simultaneously)
Concurrent kernel execution: No
Device has ECC support enabled: No
![Page 41: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/41.jpg)
Иерархия памяти
41
NVidia GeForce GTS 250
Global memory: 1GB
Shared mem. per block: 16KB
Constant memory: 64KB
Registers per block: 8192
41
![Page 42: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/42.jpg)
Data race
4242
__global__ void race(int* x) {
int i = threadIdx.x + blockDim.x * blockIdx.x; *x = *x + 1; // Data race
}
int main(){
int x;
// ...race<<<1, 128>>>(d_x); // ...
return 0;}
![Page 43: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/43.jpg)
CUDA Atomics
4343
CUDA предоставляет API атомарных операций:
atomicAdd, atomicSub, atomicInc, atomicDec
atomicMax, atomicMin
atomicExch
atomicCAS
atomicAnd, atomicOr, atomicXor
atomicOP(a,b){
t1 = *a; // readt2 = t1 OP b; // modify*a = t2; // writereturn t;
}
![Page 44: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/44.jpg)
CUDA Atomics
4444
__global__ void race(int* x) {
int i = threadIdx.x + blockDim.x * blockIdx.x; int j = atomicAdd(x, 1); // j = *x; *x = j + i;
}
int main(){
int x;
// ...race<<<1, 128>>>(d_x); // ...
return 0;}
![Page 45: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/45.jpg)
Умножение матриц
4545
C = A * B
Результирующая матрица C разбивается на подматрицы
размером 16x16 элементов
Подматрицы параллельно вычисляются блоками потоков
Каждый элемент подматрицы вычисляется отдельным
потоком (в блоке 16x16 = 256 потоков)
Количество потоков = количеству элементов в матрице C
![Page 46: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/46.jpg)
int main(){
int block_size = 16;dim3 dimsA(10 * block_size, 10 * block_size, 1);dim3 dimsB(20 * block_size, 10 * block_size, 1);printf("A(%d,%d), B(%d,%d)\n", dimsA.x, dimsA.y,
dimsB.x, dimsB.y);
unsigned int size_A = dimsA.x * dimsA.y;unsigned int mem_size_A = sizeof(float) * size_A;float *h_A = (float *)malloc(mem_size_A);
unsigned int size_B = dimsB.x * dimsB.y;unsigned int mem_size_B = sizeof(float) * size_B;float *h_B = (float *)malloc(mem_size_B);
dim3 dimsC(dimsB.x, dimsA.y, 1);unsigned int mem_size_C = dimsC.x * dimsC.y *
sizeof(float);float *h_C = (float *) malloc(mem_size_C);
Умножение матриц
4646
![Page 47: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/47.jpg)
Умножение матриц
4747
const float valB = 0.01f;
constantInit(h_A, size_A, 1.0f);
constantInit(h_B, size_B, 0.01f);
float *d_A, *d_B, *d_C;
cudaMalloc((void **) &d_A, mem_size_A);
cudaMalloc((void **) &d_B, mem_size_B);
cudaMalloc((void **) &d_C, mem_size_C);
cudaMemcpy(d_A, h_A, mem_size_A,
cudaMemcpyHostToDevice);
cudaMemcpy(d_B, h_B, mem_size_B,
cudaMemcpyHostToDevice);
![Page 48: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/48.jpg)
Умножение матриц
4848
dim3 threads(block_size, block_size);
dim3 grid(dimsB.x / threads.x,
dimsA.y / threads.y);
matmul_gpu<16><<<grid, threads>>>(d_C, d_A,
d_B, dimsA.x, dimsB.x);
cudaDeviceSynchronize();
cudaMemcpy(h_C, d_C, mem_size_C,
cudaMemcpyDeviceToHost);
![Page 49: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/49.jpg)
Умножение матриц
4949
free(h_A);
free(h_B);
free(h_C);
cudaFree(d_A);
cudaFree(d_B);
cudaFree(d_C);
return 0;
} /* main */
![Page 50: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/50.jpg)
Умножение матриц
5050
template <int BLOCK_SIZE> __global__ void matmul_gpu(float *C, float *A,
float *B, int wA, int wB){
int bx = blockIdx.x;int by = blockIdx.y;int tx = threadIdx.x;int ty = threadIdx.y;
int aBegin = wA * BLOCK_SIZE * by;int aEnd = aBegin + wA - 1;int aStep = BLOCK_SIZE;int bBegin = BLOCK_SIZE * bx;int bStep = BLOCK_SIZE * wB;float Csub = 0;
![Page 51: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/51.jpg)
Умножение матриц
5151
for (int a = aBegin, b = bBegin; a <= aEnd; a += aStep, b += bStep)
{// sub-matrix of A__shared__ float As[BLOCK_SIZE][BLOCK_SIZE];
// sub-matrix of B__shared__ float Bs[BLOCK_SIZE][BLOCK_SIZE];
// Load from device memory to shared memoryAs[ty][tx] = A[a + wA * ty + tx];Bs[ty][tx] = B[b + wB * ty + tx];
// Synchronize (wait for loading matrices)__syncthreads();
![Page 52: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/52.jpg)
Умножение матриц
5252
// Multiply the two matrices
#pragma unroll
for (int k = 0; k < BLOCK_SIZE; ++k) {
Csub += As[ty][k] * Bs[k][tx];
}
__syncthreads();
} /* for aBegin ... */
// Write the block sub-matrix to device memory;
int c = wB * BLOCK_SIZE * by + BLOCK_SIZE * bx;
C[c + wB * ty + tx] = Csub;
}
![Page 53: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/53.jpg)
Reduction
5353
O(log2n)
Mark Harris. Optimizing Parallel Reduction in CUDA // http://www.cuvilib.com/Reduction.pdf
![Page 54: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/54.jpg)
Reduction v1
5454
Условный оператор ifвнутри цикла приводит к сильному ветвлению
Можно перераспределить данные и операции по нитям
![Page 55: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/55.jpg)
Reduction v2
5555
Количество ветвлений сокращено
Большое число конфликтов банков при обращении к разделяемой памяти
![Page 56: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/56.jpg)
Dynamic parallelism (CUDA 5.0)
5656
__global__ ChildKernel(void* data)
{
// Operate on data
}
__global__ ParentKernel(void *data)
{
ChildKernel<<<16, 1>>>(data);
}
// In Host Code
ParentKernel<<<256, 64>>(data);
![Page 57: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/57.jpg)
Dynamic parallelism (CUDA 5.0)
5757
__global__ RecursiveKernel(void* data)
{
if (continueRecursion == true)
RecursiveKernel<<<64, 16>>>(data);
}
![Page 58: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/58.jpg)
Dynamic parallelism (CUDA 5.0)
5858
![Page 59: Лекция 9. Программирование GPU](https://reader030.vdocuments.mx/reader030/viewer/2022020105/5598ba6b1a28abbc4a8b46c5/html5/thumbnails/59.jpg)
Литература
5959
CUDA by Example // http://developer.download.nvidia.com/books/cuda-by-
example/cuda-by-example-sample.pdf
Джейсон Сандерс, Эдвард Кэндрот. Технология CUDA в
примерах. ДМК Пресс, 2011 г.
А. В. Боресков, А. А. Харламов. Основы работы с
технологией CUDA. М.:ДМК, 2010 г.
http://www.nvidia.ru/object/cuda-parallel-computing-books-ru.html