Автор:
Евгений Петренко (https://vk.com/mrevgenx)
Описание:
В докладе расскажу, как добиться дополнительного ускорения сложных вычислений. Будут разобраны подводные камни многопоточности в CUDA, перечислены особенности оптимизиции программ для графического процессора и представлены полезные средства отладки и профилирования. Дополнительно приведу примеры из собственного опыта распараллеливания и оптимизации такого рода программ.
2. Содержание
1. Обзор технологии
2. PyCUDA + примеры
3. Процесс разработки
4. Модель памяти и исполнения
5. Особенности оптимизации программ
6. Типичные задачи
7. Мой опыт
8. Средства отладки и профилирования
9. Мотивация для использования
5. Обзор технологии - Почему CUDA?
Скажи холивару «Нет!»
Prons:
1. Soft & Hard – подогнаны друг под
друга.
2. Производительность выше до 30%
3. Есть специализированные
вычислительные платы: Tesla K80
4. Множество обучающих материалов и
разных работ выполненных на CUDA.
Cons:
1. Только железо Nvidia
9. PyCUDA + Примеры
$pip install pycuda
Полезные ссылки:
Wiki по установке PyCUDA
Неофициальные сборки PyCUDA
10. PyCUDA + Примеры
import pycuda.autoinit
import pycuda.driver as drv
import numpy
from pycuda.compiler import SourceModule
mod = SourceModule(“””
__global__ void add_vect(float *dest, float *a, float *b){
const int i = threadIdx.x;
dest[i] = a[i] * b[i];
}
“””)
func = mod.get_function(“add_vec”)
func(drv.Out(dest), drv.In(a), drv.In(b), block=(400,1,1), grid=(1,1))
11. PyCUDA + Примеры
import pycuda.autoinit
import pycuda.driver as drv
import numpy
from pycuda.compiler import SourceModule
mod = SourceModule(“””
__global__ void mult_matrix(float *dest, float *a, float *b, int N){
const int tx = threadIdx.x;
const int ty = threadIdx.y;
const int i = tx*N + ty;
dest[i] = 0;
for(int k = 0; k < n; k++){
dest[i] = a[tx*N + k] * b[k*N + ty];
}
}
“””)
func = mod.get_function(“mult_matrix”)
func(drv.Out(dest), drv.In(a), drv.In(b), block=(40,40,1), grid=(1,1))
12. PyCUDA + Примеры
__global__ void kernelBlur(uchar4* in_image, uchar4* out_image, int w, int h){
int i = blockIdx.y*blockDim.y + threadIdx.y;//row
int j = blockIdx.x*blockDim.x + threadIdx.x;//colomn
if(i >= h || j >= w) return;
if(i == 0 || i == h-1 || j == 0 || j == w-1){
out_image[i*w+j].x = in_image[i*w+j].x;
…
return;
}
int red = 0, green = 0, blue = 0;
for(int k = -1; k < 2; ++k){
for(int m = -1; m < 2; ++m){
red += Blur[(k+1)*3+(m+1)]*in_image[(i+k)*w+j+m].x;
}
}
out_image[i*w+j].x = red/blurSumm;
…
out_image[i*w+j].w = in_image[i*w+j].w;
}
13. Процесс разработки
Основные термины: блок, сетка (grid),
import pycuda.autoinit
import pycuda.driver as drv
import numpy
from pycuda.compiler import SourceModule
mod = SourceModule(“””
__global__ void kernel(/*parameters*/){
//your code
}
“””)
func = mod.get_function(“kernel”)
func(…)
14. Модель памяти и исполнения
Несложно написать программу, очень сложно написать ее эффективно
Полезные ссылки:
Документация CUDA
15. Модель памяти и исполнения
Сетка и блоки - самое важное
Как это все ложится на физическую архитектуру – важно для
эффективности.
Распределение потоков по физическим ядрам
Обработка ветвлений
16. Модель памяти и исполнения
Много видов памяти
Важно знать для написания
эффективных программ
18. Особенности оптимизации программ
__global__ mult_matrix(float *C, float *A, float *B, int wA, int wB){
//Конфигурации
float Csub = 0;
for (int a = aBegin, b = bBegin;
a <= aEnd;
a += aStep, b += bStep){
__shared__ float As[BLOCK_SIZE][BLOCK_SIZE];
__shared__ float Bs[BLOCK_SIZE][BLOCK_SIZE];
As[ty][tx] = A[a + wA * ty + tx];
Bs[ty][tx] = B[b + wB * ty + tx];
__syncthreads();
for (int k = 0; k < BLOCK_SIZE; ++k){
Csub += As[ty][k] * Bs[k][tx];
}
__syncthreads();
}
int c = wB * BLOCK_SIZE * by + BLOCK_SIZE * bx;
C[c + wB * ty + tx] = Csub;
}
19. Типичные задачи – map/reduce
Map – реализуется довольно просто
С reduce возникают сложности
20. Типичные задачи – Обработка
сигналов
Изображения
Аудио
Видео
Фильтрация
Кодирование
Декодированиe
21. Типичные задачи – Big Data
Анализ больших данных
Классификация
Кластеризация
Регрессия
Машинное обучение
Алгоритмы требующие обучения
Нейросети
Полезные ссылки:
Theano
22. Типичные задачи – Трассировка лучей
Пример кода:
mod = SourceModule(“””
__device__ void distance(float3 point, float3 ray_orig, float3 ray_dir,
Scene* scene){
//code
}
__device__ void calc_color(float3 point, float3 normal,
Material* mat, Scene* scene){
//code
}
__global__ void kernel(…, uchar4 out_imate, int w, int h){
//your code
}
“””)
31. Мотивация для использования
Утилизация (абсолютно) всех ресурсов компьютера
Чтобы не усложнять процесс, есть оптимизированные библиотеки
GPUArrays (вместо CUBLAS)
CURAND
…