Модель программирования CUDA - Центр микро

advertisement
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Центр микро- и наномасштабной динамики дисперсных систем
Модель программирования CUDA
Марьин Д. Ф.
Уфа, 2011г.
1
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Архитектура Tesla 10
Архитектура Tesla 20
Вычислительная конфигурация
Общая архитектура GPU Tesla 10 series
SPA (Streaming Processor Array) — набор TPC.
2
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Архитектура Tesla 10
Архитектура Tesla 20
Вычислительная конфигурация
Архитектура TPC (Texture Processing Cluster) Tesla 10
TEX — Texture
block
SM — Streaming
Multiprocessor
SP — Scalar
Processor
(CUDA–ядро)
SFU — Super
Function Unit
3
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Архитектура Tesla 10
Архитектура Tesla 20
Вычислительная конфигурация
Архитектура Tesla 20
Объединенный L2 кэш (768 Kb)
До 1 Tb памяти (64-битная адресация)
Общее адресное пространство памяти
Одновременное исполнение ядер, копирования памяти
(CPU→GPU, GPU→CPU)
Одновременное исполнение ядер (до 16)
4
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Архитектура Tesla 10
Архитектура Tesla 20
Вычислительная конфигурация
Архитектура SM Tesla 20
32 ядра на SM
Одновременное исполнение
2х варпов
48 Kb разделяемой памяти
+ 16 Kb кэш;
или 16 Kb разделяемой +
48 Kb кэш
5
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Архитектура Tesla 10
Архитектура Tesla 20
Вычислительная конфигурация
Каждый поток и блок потоков
имеют идентификаторы.
blockIdx — индекс block’а
внутри grid ’а (1D, 2D).
threadIdx — индекс thread ’а
внутри block’а (1D, 2D, 3D).
6
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Модель программирования CUDA. CPU
Основной процесс приложения CUDA работает на CPU (host):
7
1
инициализирует GPU
2
распределяет память на видеокарте и системе
3
копирует данные в память видеокарты
4
запускает несколько копий процессов kernel на видеокарте
5
копирует полученные результаты из видеопамяти
6
освобождает память
7
завершает работу
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Модель программирования CUDA. GPU
GPU выполняет следующую работу:
8
1
задача разбивается на подзадачи
2
входные данные делятся на блоки, которые вмещаются в
разделяемую память
3
каждый блок обрабатывается блоком потоков
4
над данными в разделяемой памяти проводятся
соответствующие вычисления
5
результаты копируются из разделяемой памяти обратно в
глобальную
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Расширения языка
CUDA С — это расширение языка C/C++
спецификаторы для функций и переменных
новые встроенные типы
встроенные переменные (внутри ядра)
директива для запуска ядра из C кода
9
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Спецификаторы функций
Определяют, где может выполняться функция и откуда она
может быть запущена:
Спецификатор
__host__
__global__
__device__
Выполняется на
host
device
device
Может вызываться из
host
host
device
__host__ опционален;
__host__ и __device__ могут быть использованы
вместе.
Пример:
__global__ v o i d Func ( f l o a t * arg1 , i n t arg2 ,
10
...);
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Ограничения на спецификаторы функций
Ограничения на функции выполняемые на GPU (__device__
и __global__):
не поддерживается рекурсия;
не поддерживается переменное число входных аргументов;
не поддерживаются static-переменные внутри функции;
__device__ функция не поддерживает взятие адреса;
__global__ обозначает kernel и соответствующая
функция должна возвращать значение типа void;
__device__ функция является встроенной.
Можно использовать __noinline__
— тело функции должно быть в том же файле;
— компилятор не среагирует, если функция с
параметрами–указателями, или большое число аргументов.
11
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Директива вызова ядра
Func <<< g r i d , b l o c k [ , b y t e s [ , s t r e a m i d ] ] >>> ( [ arg1 , . . . ] ) ;
grid — переменная/значение типа dim3, задаёт размер grid’a (в
блоках);
block — переменная/значение типа dim3, задаёт размер блока
(в нитях);
bytes — переменная/значение типа size_t, задаёт
дополнительный объём shared-памяти, которая должна быть
динамически выделена; streamid — переменная/значение типа
cudaStream_t, задаёт поток (CUDA stream), в котором должен
произойти вызов, по умолчанию — 0.
12
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Пример
__global__ v o i d k e r n e l ( v o i d )
{
}
i n t main ( v o i d )
{
k e r n e l <<< 1 6 , 3 2 >>> ( ) ;
return 0;
}
13
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Добавлены 1,2,3,4-мерные вектора из базовых типов:
(u)char1, (u)char2, (u)char3, (u)char4,
(u)short1, (u)short2, (u)short3, (u)short4,
(u)int1, (u)int2, (u)int3, (u)int4,
(u)long1, (u)long2, (u)long3, (u)long4,
float1, float2, float3, float4,
longlong1, longlong2,
double1, double2.
Не поддерживаются векторные покомпонентные операции —
это необходимо явно делать для каждой компоненты.
14
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Для создания значений-векторов заданного типа typeName
служит конструкция вида make_<typeName>.
Обращение к компонентам вектора производится по именам —
x, y, z и w.
int2
int2
a = make_int2
b = make_int2
( 1, 7 );
( 2, 0 );
// a = a + b
a . x += b . x ;
a . y += b . y ;
f l o a t 4 c = mak e_float4 ( 1 , 2 , 3 . 4 f , 0 . 1 f ) ;
c.y = a.x + c.x;
a . x = a . y + ( int ) c . z ;
c . x += c . y + c . z + c . w ;
15
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
dim3 — uint3 тип для задания размерности. Обладает
конструктором, инициализирующим все не заданные
компоненты единицами:
dim3 varname ( [ x [ , y [ , z ] ] ] ) ;
Пример:
dim3 b l o c k s ( 1 6 , 16 ) ; // b l o c k s ( 1 6 , 1 6 , 1 )
dim3 g r i d ( 256 ) ; // g r i d ( 2 5 6 , 1 , 1 )
i n t blockDimX = b l o c k s . x ;
16
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Добавлены следующие специальные переменные:
gridDim — размер grid’а (имеет тип dim3)
blockDim — размер блока (имеет тип dim3)
blockIdx — индекс текущего блока в grid’е (имеет тип uint3)
threadIdx — индекс текущей нити в блоке (имеет тип uint3)
warpSize — размер warp’а (имеет тип int)
Ограничения:
нельзя брать адрес встроенных переменных
нельзя присвоить значение встроенной переменной
17
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
CPU C code:
float * a;
...
f o r ( i n t i = 0 ; i < N; i++ ) {
a [ i ] = a [ i ] + 1.5 f ;
}
CUDA C code:
__global__ v o i d k e r n e l ( f l o a t * a , i n t N )
{
// g l o b a l t h r e a d i n d e x
i n t i = b l o c k I d x . x * blockDim . x + t h r e a d I d x . x ;
if ( i < N )
a [ i ] = a [ i ] + 1.5 f ;
}
18
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Спецификаторы переменных
Указывают на область видео–памяти, где они будут храниться.
__device__
__constant__
__shared__
Пример:
__device__ i n t a [ 1 0 0 ] ;
19
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
__device__
Описывает переменную, которая будет находиться на
устройстве.
Может быть уточнен другими спецификаторами.
Переменная:
если не указано особо, то находится в глобальной памяти
имеет время жизни всего приложения
доступна всем потокам и хосту через runtime library
20
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
__constant__
опционально используется с __device__
Переменная:
находится в константной памяти
имеет время жизни всего приложения
доступна всем потокам и хосту через runtime library
21
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
__shared__
опционально используется с __device__
Переменная:
находится в разделяемой памяти блока потоков
имеет время жизни блока
доступна только потокам этого блока
22
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
short array0 [ 1 2 8 ] ;
f l o a t array1 [ 6 4 ] ;
int
array2 [ 2 5 6 ] ;
e x t e r n __shared__ c h a r a r r a y [ ] ;
__device__ v o i d Func ( )
{
sh or t * array0 = ( sh or t *) array ;
f l o a t * array1 = ( f l o a t *) & array0 [ 1 2 8 ] ;
int *
array2 = ( i n t *)
& array1 [ 6 4 ] ;
}
23
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Спецификаторы функций
Директива вызова ядра
Добавленные типы переменных
Добавленные переменные
Спецификаторы переменных
Ограничения на спецификаторы переменных
не могут быть применены к полям структуры (struct или
union)
не могут быть применены к формальным и локальным
переменным функций, исполняемых на хосте
__device__ и __constant__ переменные могут
использоваться только в пределах одного файла, их нельзя
объявлять как extern
запись в переменные типа __constant__ может
осуществляться только CPU при помощи специальных
функций
__shared__ переменные не могут быть
инициализированы при объявлении
24
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
CUDA поддерживает все математические функции из
стандартной библиотеки C. (sin)
Лучше использовать float–аналоги стандартных функций. (sinf)
CUDA предоставляет специальный набор функций пониженной
точности. (__sinf)
Для ряда функций можно задать способ округления при
помощи суффикса:
rn — округление к ближайшему
rz — округление к нулю
ru — округление вверх
rd — округление вниз
f l o a t x = 1 . 7 2 ; __sinf_rz ( x ) ;
Есть ряд оптимизированных функций для работы с целыми
числами.
25
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
#d e f i n e N ( 1 0 2 4 * 1 0 2 4 )
__global__ v o i d k e r n e l ( f l o a t * data ) {
i n t i d x = b l o c k I d x . x * blockDim . x + t h r e a d I d x . x ;
f l o a t x = 2 . 0 f * 3 . 1 4 1 5 9 2 6 f * ( f l o a t ) i d x / ( f l o a t ) N;
data [ i d x ] = s i n f ( __fsqrt_rz ( x ) ) ;
}
i n t main ( i n t argc , c h a r * argv [ ] ) {
f l o a t a [N ] ;
f l o a t * dev = NULL;
dim3 t h r e a d s P e r B l o c k = dim3 ( 1 2 8 , 1 ) ;
dim3 b l o c k s P e r G r i d ( N / t h r e a d s P e r B l o c k . x , 1 ) ;
cudaMalloc ( ( v o i d * * ) & dev , N * s i z e o f ( f l o a t ) ) ;
k e r n e l <<< t h r e a d s P e r B l o c k , b l o c k s P e r G r i d >>> ( dev ) ;
cudaMemcpy ( a , dev , N * s i z e o f ( f l o a t ) ,
cudaMemcpyDeviceToHost ) ;
cudaFree ( dev ) ;
return 0;
}
26
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
f l o a t a [N ] ;
f l o a t * dev = NULL;
// a l l o c a t e memory on t h e GPU by N e l e m e n t s
cudaMalloc ( ( v o i d * * ) & dev , N * s i z e o f ( f l o a t ) ) ;
// run N t h r e a d s i n b l o c k s o f 128 t h r e a d s
// p e r f o r m e d on t h e t h r e a d f u n c t i o n - k e r n e l
// data a r r a y - dev
dim3 t h r e a d s P e r B l o c k = dim3 ( 1 2 8 , 1 ) ;
dim3 b l o c k s P e r G r i d ( N / t h r e a d s P e r B l o c k . x , 1 ) ;
k e r n e l <<< t h r e a d s P e r B l o c k , b l o c k s P e r G r i d >>> ( dev ) ;
// copy data from GPU memory (DRAM) t o CPU memory
cudaMemcpy ( a , dev , N * s i z e o f ( f l o a t ) ,
cudaMemcpyDeviceToHost ) ;
cudaFree ( dev ) ; // r e l e a s e GPU memory
27
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
#d e f i n e N ( 1 0 2 4 * 1 0 2 4 )
__global__ v o i d k e r n e l ( f l o a t * data ) {
// number ( i d ) o f t h e c u r r e n t t h r e a d
i n t i d x = b l o c k I d x . x * blockDim . x + t h r e a d I d x . x ;
f l o a t x = 2 . 0 f * 3 . 1 4 1 5 9 2 6 f * ( f l o a t ) i d x / ( f l o a t ) N;
// f i n d t h e v a l u e and w r i t e i t i n t o a r r a y
data [ i d x ] = s i n f ( __fsqrt_rz ( x ) ) ; //
}
Для каждого элемента массива запускается отдельная
нить, вычисляющая требуемое значение.
Каждая нить обладает уникальным id.
28
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
Асинхронные функции
Асинхронность — управление возвращается до реального
завершения требуемой операции.
запуск ядра
функции копирования памяти, имена которых
оканчиваются на Async
функции копирования памяти device ↔ device
функции инициализации памяти
29
Повторение
Модель программирования CUDA. Расширения языка
Расширения языка. Функции
Добавленные функции
Асинхронные функции
Возвращаемые значения функций
Возвращаемые значения функций
Каждая функция CUDA runtime API (кроме запуска ядра)
возвращает значение типа cudaError_t.
При успешном выполнении возвращается cudaSuccess, иначе —
код ошибки.
Получить описание ошибки в виде строки по ее коду можно с
помощью функции:
char *
30
c u d a G e t E r r o r S t r i n g ( cudaError_t code ) ;
Download