Модель памяти GPU/CUDA Global memory - Центр микро

advertisement
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Центр микро- и наномасштабной динамики дисперсных систем
Модель памяти GPU/CUDA
Global memory
Марьин Д. Ф.
Уфа, 2011г.
1
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
На GPU/CUDA
выделяют 6 видов
памяти:
2
1
регистровая
2
разделяемая
3
локальная
4
глобальная
5
константная
6
текстурная
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Глобальная, локальная, текстурная и память констант —
локальная видеопамять GPU.
Отличие в различных алгоритмах кэширования и моделях
доступа.
CPU может обновлять и запрашивать только внешнюю
память: глобальную, константную и текстурную.
3
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Registers — СОЗУ в мультипроцессоре (32 -разрядная).
Register file — все регистры мультипроцессора.
Расположение: multiprocessor
Кэшируемость: no
Уровень выделения: on chip
Доступ: GPU — R/W, CPU — no
Скорость работы: «максимальная»
Уровень доступа: per-thread, SP
Время жизни: thread
4
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Распределение регистров
На один мультипроцессор доступно 1024 ÷ 16384 регистра.
Регистры распределяются на этапе компиляции.
Пример:
Регистров на мультипроцессор — 16384
Размер блока (число потоков) — 256
Число регистров на один поток:
16384/256 = 64
Примечание: для большей эффективности надо стараться
занимать меньше 64 или даже 32 регистров, чтобы на одном
мультипроцессоре могло исполняться несколько блоков!
5
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Constant memory — физически не отделена от глобальной
памяти.
Константная память выделяется при помощи спецификатора
__constant__.
Расположение: DRAM
Кэшируемость: yes, 8 KB at MP
Уровень выделения: on chip L1 cache
Доступ: GPU — R/O, CPU — R/W
Скорость работы: высокая (cache) / низкая (400–600
тактов)
Уровень доступа: per-grid, CPU
Время жизни: выделяется CPU
Кэш существует в единственном экземпляре для одного
мультипроцессора, а значит, общий для всех задач внутри
блока.
6
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Функции runtime library работы с памятью
cudaMemcpyToSymbol ( . . . ) ;
cudaMemcpyFromSymbol ( . . . ) ;
cudaMemcpyToSymbolAsync ( . . . ) ;
cudaMemcpyFromSymbolAsync ( . . . ) ;
cudaGetSymbolAddress ( . . . ) ;
cudaGetSy mbolSize ( . . . ) ;
7
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
template <c l a s s T>
cudaError_t cudaMemcpyToSymbol ( c o n s t T& symbol ,
c o n s t v o i d * s r c , s i z e _ t count ,
size_t o f f s e t = 0 ,
enum cudaMemcpyKind k ind = cudaMemcpyHostToDevice ) ;
count — размер в байтах;
offset — сдвиг в байтах от начала symbol;
kind — cudaMemcpyHostToDevice, cudaMemcpyDeviceToDevice.
template <c l a s s T>
cudaError_t cudaMemcpyToSymbolAsync ( . . . ,
cudaStream_t stream ) ;
stream — дескриптор потока, позволяет организовать несколько
потоков команд.
8
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Пример работы с константной памятью
На стороне хоста (в .cu файле):
f l o a t hostData [ 2 5 6 ] ;
// h o s t memory
__constant__ f l o a t constData [ 2 5 6 ] ; // c o n s t a n t memory
// h o s t memory data -> d e v i c e c o n s t a n t memory data
cudaMemcpyToSymbol ( constData , hostData ,
s i z e o f ( hostData ) , 0 ,
cudaMemcpyHostToDevice ) ;
На стороне устройства:
__global__ v o i d k e r n e l ( f l o a t * pos )
{
i n t i n d e x = b l o c k I d x . x * blockDim . x + t h r e a d I d x . x ;
pos [ i n d e x ] = pos [ i n d e x ] * constData [ i n d e x ] ;
}
9
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Локальная память — небольшой объём DRAM, используемый
компилятором в случаях, когда локальные данные процедур
занимают слишком большой размер, или когда компилятор не
может вычислить для них некоторый постоянный шаг при
обращении.
Расположение: DRAM
Кэшируемость: no
Уровень выделения: DRAM
Доступ: GPU — R/W, CPU — no
Скорость работы: низкая (латентность — 400–600 тактов)
Уровень доступа: per-thread, SP
Время жизни: thread
Примечание: нет механизмов, позволяющих явно запретить
компилятору использование локальной памяти для конкретных
переменных.
10
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Global memory — DRAM GPU. Обладает высокой пропускной
способностью (более 100 ГБ/с) и возможностью произвольной
адресации глобальной памяти.
Глобальная память выделяется при помощи спецификатора
__device__ или особым образом.
Расположение: DRAM
Кэшируемость: no
Уровень выделения: DRAM
Доступ: GPU — R/W, CPU — R/W
Скорость работы: низкая (латентность — 400–600 тактов)
Уровень доступа: per-grid, CPU
Время жизни: выделяется CPU
Назначение: передача данных между CPU и GPU.
11
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Функции управления памятью
Выделение памяти на устройстве:
cudaError_t cudaMalloc ( v o i d ** devPtr , s i z e _ t count ) ;
count — размер в байтах.
Освобождение памяти на устройстве:
cudaError_t cudaFree ( v o i d * dev Ptr ) ;
12
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Для эффективного доступа к глобальной памяти важным
требованием является выравнивание данных в памяти.
cudaError_t c u d a M a l l o c P i t c h ( v o i d ** devPtr ,
s i z e _ t * p i t c h , s i z e _ t widthInBy tes , s i z e _ t h e i g h t ) ;
при выделении памяти может увеличить объём памяти под
каждую строку, чтобы гарантировать выравнивание всех строк.
pitch — шаг распределения памяти в байтах.
Если при помощи cudaMallocPitch выделялась память под
матрицу из элементов типа T, то для получения адреса
элемента, расположенного в строке row и столбце col,
используется следующая формула:
T * item = ( T * ) ( ( char * ) baseAddress + row * pitch) + col;
13
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Пример использования cudaMallocPitch для выделения
двухмерного массива размерами width x height
// h o s t s i d e code
f l o a t * dev Ptr ;
size_t pitch ;
int height = 10;
i n t width = 6 3 ;
c u d a M a l l o c P i t c h ( ( v o i d ** ) & devPtr , & p i t c h ,
width * s i z e o f ( f l o a t ) , h e i g h t ) ;
myKernel <<< 1 0 , 64 >>> ( devPtr , p i t c h , width , h e i g h t ) ;
widthInBytes = 252
pitch = 256
14
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
// d e v i c e s i d e code
__global__ v o i d
myKernel ( f l o a t * devPtr , i n t p i t c h ,
i n t width , i n t h e i g h t )
{
f o r ( i n t row = 0 ; row < h e i g h t ; ++row )
{
f l o a t * rowPtr= ( f l o a t * ) ( ( c h a r * ) dev Ptr + row * p i t c h ) ;
f o r ( i n t c o l = 0 ; c o l < width ; ++c o l )
{
f l o a t e l e m e n t = rowPtr [ c o l ] ;
...
rowPtr [ c o l ] = row * width + c o l ;
}
}
}
T * item = ( T * ) ( ( char * ) baseAddress + row * pitch) + col;
15
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
cudaError_t cudaMallocHost ( v o i d ** h o s t P t r , s i z e _ t s i z e ) ;
page–locked (pinned) память со стороны хоста, которая
доступна напрямую устройству.
Повышает скорость передачи данных между CPU и GPU для
функций cudaMemcpy*(). Виртуальная память обладает
большей пропускной способностью, чем страничная память
(malloc()).
Примечание: Является ограниченным ресурсом и чрезмерное
её использование может отрицательно сказаться на
быстродействии всей системы.
Лучше использовать как буффер для обмена данными между
хостом и устройством.
cudaError_t cudaFreeHost ( v o i d * h o s t P t r ) ;
16
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Пересылка данных:
cudaError_t cudaMemset ( v o i d * devPtr , i n t v a l u e ,
s i z e _ t count ) ;
count — размер в байтах;
value — значение.
Копирование данных:
cudaError_t cudaMemcpy( v o i d * dst , c o n s t v o i d * s r c ,
s i z e _ t count , enum cudaMemcpyKind k ind ) ;
cudaError_t cudaMemcpyAsync ( . . .
cudaStream_t stream ) ;
...
17
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Register
Constant memory
Local memory
Global memory
Пример пересылки данных:
int
n = 512;
int
numBytes = n * s i z e o f ( f l o a t ) ;
f l o a t * a = NULL;
f l o a t * aDev = NULL;
a = ( f l o a t * ) m a l l o c ( n* s i z e o f ( f l o a t ) ) ;
cudaError_t e r r o r =
cudaMalloc ( ( v o i d **)&aDev , numBytes ) ;
dim3 t h r e a d s = dim3 ( 1 2 8 ) ;
dim3 b l o c k s = dim3 ( n / t h r e a d s . x ) ;
cudaMemset ( aDev , 0 , n ) ;
v e c t o r s S u m K e rn el <<< b l o c k s , t h r e a d s >>> ( aDev ) ;
cudaMemcpy ( a , aDev , numBytes , cudaMemcpyDeviceToHost ) ;
cudaFree ( aDev ) ;
18
free (a );
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Обращение к глобальной памяти происходит через
чтение/запись 32/64/128-битовых слов. Важно, что адрес, по
которому происходит доступ, должен быть выровнен по
размеру слова (кратен размеру слова в байтах).
Пример выровненного и невыровненного 4-х байтного слова.
19
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Все функции выделяющие глобальную память выделяют её
выровненной по 256 байтам.
Пусть есть массив из следующих структур в глобальной
памяти:
s t r u c t v ec3
{
float a;
float b;
float c ;
}
Каждый элемент массива — 12 байт. Адрес первого элемента
выровнен по 16 байтам, но адрес второго элемента — нет, и его
чтение потребует двух обращений.
20
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Выравнивание:
s t r u c t __align__ ( 1 6 ) v ec3
{
float a;
float b;
float c ;
}
Теперь все элементы массива будут хранится по адресам
кратным 16 байтам.
21
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Объединение запросов в глобальную память (coalescing)
GPU имеет возможность объединять несколько запросов к
глобальной памяти в один (coalescing).
Все обращения MP к памяти происходят независимо для
каждой половины warp’a.
Максимальное объединение — все запросы одного полу-warp’a
удается объединить в один большой запрос на чтение из
глобальной памяти.
22
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Условия возможности объединения
все нити обращаются к 32(CP от 1.2)/32/64-битовым
словам, давая в результате один
32(CP от 1.2)/64/128-байтный блок;
получивщийся блок выровнен по своему размеру (адрес
кратен 32(CP от 1.2)/64/128);
все 16 слов, к которым обращаются нити лежат в пределах
одного блока;
нити обращаются к словам последовательно:
k–ая нить обращается к k–му слову;
допускается, что отдельные нити пропустят обращение к
соответствующим словам.
Если нити полу-warp’a не удовлетворяют любому условию, то
каждое обращение к памяти происходит как отдельная
транзакция!
23
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Гораздо эффективнее, с точки зрения объединения запросов к
памяти, использование не массивов структур, а структуры
массивов.
s t r u c t __align__ ( 1 6 ) A
{
float a;
float b;
int c ;
}
A array [ 2 5 6 ] ;
...
f l o a t ga = a r r a y [ t h r e a d I d x . x ] . a ;
A gs = array [ threadIdx . x ] ;
Не приведет к объединению запросов!
Понадобится 16 транзакций на полу-warp.
24
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
float
float
int c
...
float
float
float
Выравнивание
Coalescing
Структуры массивов
a [256];
b [256];
[256];
ga = a [ t h r e a d I d x . x ] ;
gb = b [ t h r e a d I d x . x ] ;
gc = c [ t h r e a d I d x . x ] ;
Приведет к объединению запросов всех запросов нитей
полу-warp’a!
Понадобится 3 транзакции на полу-warp.
25
Модель памяти GPU/CUDA
Оптимизация работы с глобальной памятью
Выравнивание
Coalescing
Структуры массивов
Основные способы:
выравнивание
объединение запросов в глобальную память (coalescing)
использование не массивов структуры, а структур массивов
26
Download