Вы находитесь на странице: 1из 98

NVIDIA CUDA

для параллельных
вычислений на GPU

Александр Харламов
NVIDIA
Вычисления на GPU
Открывают новые возможности
Значительно сокращая время до получения результата
Цикл обработки данных уменьшается от дней до минут, от
недель до дней

Новый взгляд на вычислительные архитектуры


Активизируя исследования в области параллельных
алгоритмов, новых программных моделей и вычислительных
архитектур
Рост производительности GPU
Пиковая производительность

1 TF
900 GPU 10-й
800
серии
700
600
500
400 GPU 8-й
300 серии
200
100
0
2002 2003 2004 2005 2006 2007 2008
Исследователи всего мира строят станции на основе GPU

3 GPUs
3 GPUs
Korea University of
Illinois

2 GPUs
University of
Cambridge, UK

8 GPUs

16 GPUs
University of
Antwerp,
Belgium
Параллельные вычисления на GPU
100+ млн. GPU в мире поддерживают CUDA

GeForce® TeslaTM Quadro®


Развлечения Высокопроизводительные вычисления Дизайн, разработка
Выбор CUDA платформы
Tesla Quadro GeForce

Стресс-тест с проверкой точности вычислений X


Произведено NVIDIA из высококачественных комплектующих X X
3-х летняя гарантия, корпоративная поддержка X X
4 Гб оперативной памяти для работы с большими объемами данных X X
Единое профессиональное решение для вычислений и графики X
Пользовательские приложения: PhysX, Video, Imaging X
Короткий жизненный цикл пользовательского продукта X
Производится и сопровождается партнерами NVIDIA X
Поддержка осуществляется через партнеров NVIDIA X
Более 250 заказчиков / разработчиков ПО
Life Sciences & Productivit Oil and Manufa CAE / Commun
Medical Equipment y / Misc Gas EDA cturing Finance Numerics ication

Max Planck GE Healthcare CEA Hess Synopsys Renault Symcor The Nokia
FDA Siemens WRF Weather TOTAL Nascentric Boeing Level 3 Mathworks RIM
Robarts Techniscan Modeling CGG/Veritas Gauda SciComp Wolfram Philips
Research Boston Scientific OptiTex Chevron CST Hanweck National Samsung
Medtronic Eli Lilly Tech-X Headwave Agilent Quant Instruments LG
AGC Silicon Elemental Acceleware Catalyst Access Sony
Technologies Analytics
Evolved Informatics Seismic City RogueWave Ericsson
Dimensional Tech-x
machines Stockholm Imaging P-Wave BNP Paribas NTT
Smith-Waterman Research Seismic RIKEN DoCoMo
Manifold
DNA sequencing Harvard Imaging SOFA Mitsubishi
Digisens
AutoDock Delaware Mercury Hitachi
General Mills
NAMD/VMD Pittsburg Computer Radio
Rapidmind
Folding@Home ETH Zurich ffA Research
MS Visual
Howard Huges Institute Atomic Laboratory
Studio
Medical Physics US Air Force
Rhythm & Hues
CRIBI Genomics
xNormal
Elcomsoft
LINZIK
Будущие прорывы в индустрии опираются
на компьютерное моделирование

Вычислительная Вычислительное Вычислительная Вычислительная


геология моделирование медицина физика

Вычислительная Вычислительная Вычислительная Обработка


химия биология экономика сигналов
© NVIDIA Corporation 2008
Масштабируемая программно-аппаратная архитектура
для параллельных вычислений
CUDA для параллельных вычислений

Программно-аппаратный стек
для процессоров NVIDIA

Раскрывает потенциал GPU для


вычислений общего назначения

Спроектирован для поддержки


любого вычислительного
интерфейса ATI’s Compute ―Solution‖

OpenCL, C/C++, и т.д.


Программная модель
Программная модель CUDA

Масштабируемость на десятки ядер, сотни параллельных


потоков

Позволяет сфокусироваться на разработке параллельных


алгоритмов
А не внутренней механике языка программирования

Поддерживает гетерогенные вычисления


CPU для последовательного кода, GPU – для параллельного
Ключевые абстракции CUDA

Потоки CUDA выражают мелкозернистый параллелизм данных


Упрощают параллельную декомпозицию задач
Виртуализируют физические процессоры

Блоки потоков CUDA выражают крупнозернистый параллелизм


Простая модель исполнения
Обеспечивают прозрачную масштабируемость

Легковесные примитивы синхронизации


Простая модель синхронизации

Разделяемая память для обмена данными между потоками


Кооперативное исполнение потоков
Потоки CUDA

Ядро CUDA исполняется массивом потоков


Все потоки исполняют одну программу
Каждый поток использует свой индекс для вычислений и
управления исполнением

threadID 0 1 2 3 4 5 6 7


float x = input[threadID];
float y = func(x);
output[threadID] = y;

Взаимодействие потоков

Потоки могут быть не полностью независимы


Обмениваются результатами вычислений
Разделяют доступ к внешней памяти

Возможность взаимодействия потоков – ключевая


особенность программной модели CUDA
Потоки кооперируют, используя разделяемую память и примитивы
синхронизации
Блоки потоков: масштабируемость

Монолитный массив потоков разделяется на блоки


Потоки внутри блока взаимодействуют через разделяемую память
Потоки в разных блоках не могут синхронизироваться
Позволяет программам прозрачно масштабироваться

Блок 0 Блок 1 Блок N-1


threadID 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7

… … …
float x = input[threadID]; float x = input[threadID]; float x = input[threadID];
float y = func(x);
output[threadID] = y;
float y = func(x);
output[threadID] = y; … float y = func(x);
output[threadID] = y;
… … …
Прозрачная масштабируемость

Блоки могут быть распределены на любой процессор


Код на CUDA масштабируется на любое количество ядер

Устройство A Устройство B

SM SM SM SM SM SM
Сетка блоков

Блок 0 Блок 1

Блок 0 Блок 1 Блок 2 Блок 3 Блок 0 Блок 1 Блок 2 Блок 3

Блок 4 Блок 5
Блок 2 Блок 3
Блок 4 Блок 5 Блок 6 Блок 7
Блок 6 Блок 7

Блок 4 Блок 5

Блок 6 Блок 7
Гетерогенная модель вычислений
Последовательная программа, с параллельными секциями
Последовательный код исполняется на CPU
Параллельный код исполняется блоками потоков на множестве вычислительных
модулей GPU
Последовательный код

Параллельное ядро A

KernelA<<< nBlk, nTid >>>(args);

Последовательный код

Параллельное ядро B …
KernelB<<< nBlk, nTid >>>(args);
Расширения C для CUDA

Стандартный C код Код на CUDA C


void saxpy_serial(int i, float a, __global__
float *x, float *y) void saxpy_parallel(int n, float a, float *x, float *y)
{ {
y[i] = a*x[i] + y[i]; int i = blockIdx.x*blockDim.x + threadIdx.x;
} if (i < n) y[i] = a*x[i] + y[i];
}

// Вызов последовательного // Вызов параллельного ядра SAXPY с размером


// блока в 256 потоков
// ядра SAXPY
int nblocks = (n + 255) / 256;
for (int i = 0; i < n; ++i)
saxpy_parallel<<<nblocks, 256>>>(n, 2.0f, x, y);
saxpy_serial(i, 2.0, x, y);

1
Уровни параллелизма в CUDA

Параллелизм на уровне потоков


Каждый поток – независимая нить исполнения

Параллелизм на уровне данных


По потокам внутри блока
По блокам внутри ядра

Параллелизм на уровне задач


Блоки исполняются независимо друг от друга
Пространство памяти CUDA

Block
Thread
Регистры Разделяемая
Локальная память память
Пространство памяти CUDA

KernelA<<< nBlk, nTid >>>(args);


Глобальная
KernelB<<< nBlk, nTid >>>(args); память


Пространство памяти CUDA

Устройство 0

Память CPU cudaMemcpy()


Устройство 1
Архитектура
GPU как параллельный процессор
GPU обладает массивно-параллельной вычислительной
архитектурой
Выступает в роли сопроцессора для CPU
Имеет доступ к выделенной памяти с широкой полосой
пропускания 80+ GB/s
Исполняет множество потоков одновременно

Параллельные секции приложения исполняются как


вычислительные ядра
Каждое ядро исполняет множество потоков

Потоки GPU легковесны


Очень низкие накладные расходны на создание
Мгновенное переключение контекстов
GPU использует тысячи потоков для эффективности

© NVIDIA Corporation 2008


Мультипроцессор NVIDIA Tesla 10
SM
I-Cache
RISC-подобная скалярная система команд MT Issue
Многопоточное исполнение инструкций C-Cache
Поддержка до 1024 потоков
Аппаратный менеджер потоков
TPC SP SP
Geometry Controller
SMC

8 скалярных АЛУ
I-Cache I-Cache I-Cache
MT Issue MT Issue MT Issue
C-Cache
SP SP
C-Cache
SP SP
C-Cache
SP SP
SP SP
Операции с одинарной точностью IEEE-754 SP

SP
SP

SP
SP

SP
SP

SP
SP

SP
SP

SP

Целочисленные операции
SP SP SP SP SP SP

SFU SFU

DP
SFU SFU

DP
SFU SFU

DP
SP SP
16K 32-х битных регистров Shared
Memory
Shared
Memory

Texture Unit
Shared
Memory

2 АЛУ для специальных операций


Tex L1

SP SP
sin/cos/rcp/rsq
SFU SFU
1 АЛУ для операций с двойной точностью
Поддерживает FMA DP
16KB разделяемой памяти
Shared
Memory
Архитектура NVIDIA Tesla 10
240 процессоров работают на частоте 1.5 GHz: 1 TFLOPS в пике
128 потоков на процессор: 30,720 потоков на чипе
SM
I-Cache
MT Issue
C-Cache

SP SP
Host CPU Bridge System Memory

Work Distribution
Tesla T10 SP SP

I-Cache
SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache I-Cache


SMC
``

I-Cache I-Cache
SP SP
MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue MT Issue
C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache C-Cache

SP SP
SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP

SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP

SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP SP SP SP ` SP SP SP

SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP SP

SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU SFU

DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
DP
Shared
SFU SFU
Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory Memory

Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit Texture Unit
Tex L1 Tex L1 Tex L1 Tex L1 Tex L1 Tex L1 Tex L1 Tex L1 Tex L1 Tex L1

Interconnection Network
DP
ROP L2 ROP L2 ROP L2 ROP L2 ROP L2 ROP L2 ROP L2 ROP L2
Shared
DRAM DRAM DRAM DRAM DRAM DRAM DRAM DRAM Memory
Программная модель & архитектура

Block Warp 0 Warp 1


Thread
Программная модель & архитектура

KernelA<<< nBlk, nTid >>>(args);


Программная модель & архитектура

KernelA<<< nBlk, nTid >>>(args);

KernelB<<< nBlk, nTid >>>(args);


Fermi

8x производительность double вычислений


Error Correcting Codes
Однородное адресное пространство
Указатели на функции
Исполнение разных ядер
Иерархия кэшей
Warp-коалесинг
Средства разработки
Средства разработки

CUDA C
Runtime API
Driver API
OpenCL
CUDA C (Runtime API)

Расширение языка C
CUDA API:
Расширения языка C
Затрагивает те части кода, которые исполняются на GPU
Runtime библиотека состоит из:
Общие компоненты (типы и функции)
Управление GPU и взаимодействие с графическими API
Функции доступные на GPU
– __syncthreads
– «быстрые» функции
Расширение языка:
Спецификаторы функций
Исполняется Вызывается
__device__ float DeviceFunc() device device
__global__ void KernelFunc() device host
__host__ float HostFunc() host host

__global__ определяет ядро


Всегда возвращает void
__device__ и __host__ можно использовать вместе
__device__ недоступен указатель на функции
Для __device__ функций
Нет рекурсии
Нет статических переменных
Нет переменного числа аргументов
Расширение языка:
Спецификаторы переменных
Память Видимость Время жизни
__shared__ int SharedVar; shared thread block thread block
__device__ int GlobalVar; global grid Приложение
__constant__ int ConstantVar; constant grid Приложение

Переменные без спецификатора попадают в регистры


Кроме больших структур, которые попадают в локальную память

Указатели могут указывать на память в разделяемой или глобальной памяти


Глобальная память:
Память выделенная на CPU и переданная в ядро
Разделяемая память:
Статически выделенная внутри ядра
Статически выделенная при вызове
CUDA C Runtime
#define N (256*256) // array size
NVCC (cudart.lib) #define PI 3.1415926f

Спецификаторы __global__ void kernel ( float * data )


{
функций int idx = blockIdx.x * blockDim.x + threadIdx.x ;

data [idx] = idx;


Встроенные }

переменные
С / C++ интерфейс
Библиотека функций
__device__
CUDA C Runtime
int main ( int argc, char * argv [] )
NVCC (cudart.lib) {
float * a = new float [N]; // CPU память
Спецификаторы float * dev = NULL; // GPU память

функций // выделение памяти


cudaMalloc ( (void**)&dev, N * sizeof ( float ) );

Встроенные dim3 threads = dim3( 512, 1 );


dim3 blocks = dim3( N / threads.x, 1 );
переменные // запуск ядра
kernel<<<blocks, threads>>> ( dev );
С / C++ интерфейс cudaThreadSynchronize();

cudaMemcpy ( a, dev, N * sizeof ( float ),


Библиотека функций cudaMemcpyDeviceToHost );
cudaFree ( dev );
__host__
delete [] a;

return 0;
}
CUDA C Runtime
#define N (256*256) // array size
#define PI 3.1415926f

__global__ void linear( float * pDst, float * pSrc,


int wDst, int wSrc )
{
int idx = blockIdx.x * blockDim.x + threadIdx.x ;

+ + + + float factor = (float) wDst / (float) wSrc;

float center = idx / factor;


int start = (int) center;
int stop = start + 1;
float t = center - start;

float a = pSrc[start];
float b = pSrc[stop];
float r = a * (1 - t) + b * t;

pDst[idx] = r;
}
CUDA C Runtime
NVCC
-keep
.ptx
.cubin
CUDA C Runtime
__global__ void kernel ( float * data )
NVCC {
int idx = blockIdx.x * blockDim.x + threadIdx.x ;
-keep data [idx] = idx;
}
.ptx
.cubin
CUDA C Runtime
.entry _Z6kernelPf (
NVCC .param .u32 __cudaparm__Z6kernelPf_data)
{
.reg .u16 %rh<4>;
-keep .reg .u32 %r<8>;
.reg .f32 %f<3>;
.ptx .loc 14 6 0
$LBB1__Z6kernelPf:
.cubin .loc 14 10 0
mov.u16 %rh1, %ctaid.x; //
mov.u16 %rh2, %ntid.x; //
mul.wide.u16 %r1, %rh1, %rh2; //
cvt.u32.u16 %r2, %tid.x; //
add.u32 %r3, %r2, %r1; //
cvt.rn.f32.s32 %f1, %r3; //
ld.param.u32 %r4, [__cudaparm__Z6kernelPf_data]; // i
mul.lo.u32 %r5, %r3, 4; //
add.u32 %r6, %r4, %r5; //
st.global.f32 [%r6+0], %f1; // id:15
.loc 14 11 0
exit;
$LDWend__Z6kernelPf:
} // _Z6kernelPf
CUDA C Driver
Низкоуровневый API CUdevice device;
CUcontext context;
Инициализация cuInit() CUmodule module;
CUfunction function;
Поиск устройства CUdeviceptr pData;
CUdevice float * pHostData = new float[N];
Создание контекста
cuInit(0);
CUcontext
Загрузка модуля cuDeviceGetCount(&device_count);
cuDeviceGet( &device, 0 );
CUmodule
cuCtxCreate( &context, 0, device );
Загрузка функции
CUfunction cuModuleLoad( &module, "hello.cuda_runtime.ptx" );
Выделение памяти cuModuleGetFunction( &function, module, "_Z6kernelPf" );
CUdeviceptr
cuMemAlloc( &pData, N * sizeof(float) );
// …
// ...
CUDA C Driver
Низкоуровневый API // ...
// …
cuFuncSetBlockShape( function, N, 1, 1 );
Установка размеров
cuParamSeti( function, 0, pData );
блока
Установка аргументов cuParamSetSize( function, sizeof(void *) );
функции ядра cuLaunchGrid( function, 1, 1 );
Установка параметров
cuMemcpyDtoH( pHostData, pData, N * sizeof( float) );
ядра
cuMemFree( pData );
Запуск ядра cuLaunch()
Копирование памяти
Освобождение ресурсов
OpenCL

Кроссплатформенный стандарт
GPU, CPU, Cell, …
Проблема: функциональность, но не производительность
Разный код для разных платформ
Разные расширения openGL-style
CUDA vs OpenCL
Терминология
CUDA C OpenCL
Поток (thread) Элемент работы (work-item)
Блок потоков Группа работы (work-group)
(thread block) N-мерное пространство индексов (ND-
Сеть (grid) Range index space)
Ядро Ядро
CUDA vs OpenCL
Спецификаторы функций
CUDA C OpenCL
__global__ __kernel
__host__ n/a
__device__ n/a
CUDA vs OpenCL
Пространство памяти
CUDA C OpenCL
__device__ __global
__shared__ __local
__constant__ __constant
local __private
OpenCL
Низкоуровневый API cl_context ctx;
cl_command_queue cmd_q;
Создание контекста cl_program program;
cl_kernel kernel;
cl_context cl_mem mem;
cl_device_id * pDevId = NULL;
Поиск устройства
cl_device_id
ctx = clCreateContextFromType(0,CL_DEVICE_TYPE_GPU,0,0,0)
Создание очереди
комманд clGetContextInfo(ctx,CL_CONTEXT_DEVICES,0,0,&dev_cnt);

Создание ид. clGetContextInfo(ctx,CL_CONTEXT_DEVICES,dev_cnt,pDevId,0)


программы и
cmd_q= clCreateCommandQueue(ctx,pDevId[0],0,0);
компиляция
Создание ид. ядра program = clCreateProgramWithSource(ctx,1,pText,0,0);

// ... clBuildProgram(program, 0,0,0,0,0);

kernel = clCreateKernel(program, "simple", 0);

// ...
OpenCL
Низкоуровневый API // ...

// ... mem = clCreateBuffer(ctx,CL_MEM_WRITE_ONLY,


N*sizeof(float),0,0);
Выделение памяти
clSetKernelArg(kernel, 0, sizeof(cl_mem),(void*) &mem);
Установка аргументов clSetKernelArg(kernel, 1, sizeof(int), (void*) &N);
функции ядра
clEnqueueNDRangeKernel(cmd_q,kernel,1,0,&N,&N,0,0,0);
Добавление в очередь
ядра с заданным clEnqueueReadBuffer(cmd_q, mem, CL_TRUE, 0,
N*sizeof(float), pData,0,0,0);
рамером рабочей
группы и NDRange clReleaseMemObject(mem);
clReleaseKernel(kernel);
Добавление в очередь clReleaseProgram(program);
копирование памяти clReleaseCommandQueue(cmd_q);
clReleaseContext(ctx);
Освобождение ресурсов
Оптимизации
Ресурсы для разработчиков
Инструментарий разработчика CUDA
(CUDA toolkit)
Компилятор и библиотеки
Версии для Win32/64, MacOS, Linux
доступны для загрузки
Набор примеров и средств разработки
(CUDA SDK)
Готовые решения на CUDA
Примеры использования
Библиотеки
CUFFT, CUBLAS, CUDPP
Инструменты для отладки и
оптимизации
Nexus
Оптимизация

PTX
PTX

Промежуточный ассемблер может показать много


интересного
--ptxas-options=-v

__global__ void kernel(float *pData) __global__ void kernel(float *pData)


{ {
float id = (float) threadIdx.x; float id = (float) threadIdx.x;
pData[threadIdx.x] = _sinf( id ); pData[threadIdx.x] = sinf( id );
} }
PTX

Промежуточный ассемблер может показать много


интересного
--ptxas-options=-v

__global__ void kernel(float *pData) __global__ void kernel(float *pData)


{ {
float id = (float) threadIdx.x; float id = (float) threadIdx.x;
pData[threadIdx.x] = _sinf( id ); pData[threadIdx.x] = sinf( id );
} }

2 .reg 10 .reg !
28 bytes lmem !
PTX

Промежуточный ассемблер может показать много


интересного
--keep

__global__ void kernel(float3 *pData) __global__ void kernel(float4 *pData)


{ {
pData[threadIdx.x] = f3(); pData[threadIdx.x] = f4();
} }
PTX

Промежуточный ассемблер может показать много


интересного
--keep
{ // ... { // ...
mov.u16 %rh1, %tid.x; // mov.u16 %rh1, %tid.x;
mul.wide.u16 %r1, %rh1, 12; // mul.wide.u16 %r1, %rh1, 16;
ld.param.u32 %r2, [__cudaparm__kernel_f3_pD] ld.param.u32 %r2,[__cudaparm__kernel_f4_pD
add.u32 %r3, %r2, %r1; // add.u32 %r3, %r2, %r1; //
mov.f32 %f1, 0f00000000; // 0 mov.f32 %f1, 0f00000000; // 0
st.global.f32 [%r3+0], %f1; // id:14 mov.f32 %f2, 0f00000000; // 0
mov.f32 %f2, 0f00000000; // 0 mov.f32 %f3, 0f00000000; // 0
st.global.f32 [%r3+4], %f2; // id:15 mov.f32 %f4, 0f00000000; // 0
mov.f32 %f3, 0f00000000; // 0 st.global.v4.f32 [%r3+0], {%f1,%f2,%f3,%f4};
st.global.f32 [%r3+8], %f3; // id:16 .loc 14 23 0
.loc 14 18 0 exit; //
exit; // $LDWend__Z9kernel_P6float4:
$LDWend__Z9kernel_P6float3: } // _Z9kernel_P6float4
} // _Z9kernel_P6float3
Occupancy

Покрытие латентностей: инструкции потока


выполняются последовательно

Исполнение других потоков необходимо для


покрытия латентностей

Занятость: отношение активных варпов к


максимально возможному
В архитектуре Tesla 32 варпа на SM
Occupancy

Увеличение занятости приводит к лучшему


покрытию латентностей

После определенной точки (~50%), происходит


насыщение

Занятость ограничена достыпными ресурсами:


Регистры
Разделяемая память
Оптимизация

Occupancy
Calculator
Spreadsheet
Оптимизация

Visual
Profiler
Оптимизация

Profiler
Counter
Plot
Особенности памяти

Константная: обращение в один адрес всем варпом


Разделяемая: обращение в
Разные банки
В один адрес (broadcast)
Текстурная: обращение локализованно
Глобальная: обращения объеденены в одну транзакцию
Host: минимизировать трансферы
Coalescing GMEM
Наиболее важная оптимизация
Координированное чтение / запись (16 потоков)
Непрерывный участок памяти:
64 bytes─каждый поток читает 32-битное слово: int, float, …
128 bytes─ каждый поток читает 64-битное слово: int2, float2, double…
256 bytes─ каждый поток читает 128-битное слово: int4, float4, …
Ограничения:
Начальный адрес должен быть выровнен по размеру
kый поток полу-варпа должен обращаться к kому элемету
Исключение: Потоки могут быть неактивными
Например если выбрана другая ветка исполнения
Coalesced Доступ:
Чтение float (32-bit)
t0 t1 t2 t3 t14 t15

… …
128 132 136 140 144 184 188 192

Все потоки активны

t0 t1 t2 t3 t14 t15

… …
128 132 136 140 144 184 188 192

Потоки могут не учавствовать


Uncoalesced Доступ:
Чтение float (32-bit)
t0 t1 t2 t3 t14 t15

… …
128 132 136 140 144 184 188 192

Произвольный доступ

t0 t1 t2 t3 t13 t14 t15

… …
128 132 136 140 144 184 188 192

Не выровненный адрес (не кратный 64b)


1 транзакция — 64B сегмент
Coalescing SM 1.2
Объединение транзакций
происходит при любом
шаблоне доступа
2 транзакции — 64B и 32B сегменты
который ложится в
сегмент размера: 32B для
8-bit слов, 64B для 16-bit
слов, 128B для 32- и 64-
bit слов 1 транзакция —128B сегмент
Выравниевание более не
играет такой роли но
сильно хаотичные чтение
/ запись все еще
медленные
Коалесинг
Банки разделяемой памяти

Одновременное обращение потоков к


разделяемой памяти Bank 0
Память разбивается на банки Bank 1

Необходимо для обеспечения высокой Bank 2


пропускной способности Bank 3
Bank 4
Каждый банк работает с одним адресом
Bank 5
одновременно
Bank 6
Одновременное обращение в один банк Bank 7
приводит к конфликтам
Доступ сериализуется
Bank 15
Конфликты банков

Нет конфликтов Нет конфликтов


– Прямая адресация, с шагом == 1 – Хаотичная адресация
Thread 0 Bank 0 Thread 0 Bank 0
Thread 1 Bank 1 Thread 1 Bank 1
Thread 2 Bank 2 Thread 2 Bank 2
Thread 3 Bank 3 Thread 3 Bank 3
Thread 4 Bank 4 Thread 4 Bank 4
Thread 5 Bank 5 Thread 5 Bank 5
Thread 6 Bank 6 Thread 6 Bank 6
Thread 7 Bank 7 Thread 7 Bank 7

Thread 15 Bank 15 Thread 15 Bank 15


Конфликты банков

2х Конфликты 8х Конфликты

Thread 0 Bank 0 Thread 0 Bank 0


Thread 1 Bank 1 Thread 1 Bank 1
x8
Thread 2 Bank 2 Thread 2 Bank 2
Thread 3 Bank 3 Thread 3 Bank 3
Thread 4 Bank 4 Thread 4 Bank 4
Bank 5 Thread 5 Bank 5
Bank 6 Thread 6 Bank 6
Thread 12
Bank 7 Thread 7 x8
Bank 7
Thread 13
Thread 14
Thread 15 Bank 15 Thread 15 Bank 15
Конфликты банков
Ветвление

Если происходит ветвление внутри варпа, то разные ветви


исполнения сериализуются

Увеличивается общее количество инструкций

Если ветвление происходит между варпами, то штраф


минимальный
Ветвление
Инструкции
Инструкции

Следить за ветвлением

Заменить часть вычислений на look-up таблицу

Интринсики
__sinf(); __cosf(); expf()
__[u]mul24()
__fdividef()
__[u]sad()
Мифы о вычислениях на GPU
Мифы о вычислениях на GPU

Миф 1: GPU исполняет программы как графические


шейдеры
Мифы о вычислениях на GPU

Миф 1: GPU исполняет программы как графические


шейдеры

Это не так – CUDA использует вычислительные ресурсы GPU


напрямую
Мифы о вычислениях на GPU

Миф 2: Архитектурно, GPU представляют из себя


Очень широкие SIMD-машины (1000) ...
… с крайне неэффективной поддержкой ветвления ...
… которые ориентированые на обработку 4-х мерных векторов
Мифы о вычислениях на GPU

Миф 2: Архитектурно, GPU представляют из себя


Очень широкие SIMD-машины (1000) ...
… с крайне неэффективной поддержкой ветвления ...
… которые ориентированые на обработку 4-х мерных векторов

Современные GPU используют SIMT исполнение, с размером


блока (warp) в 32 элемента и скалярными потоками
Мифы о вычислениях на GPU

Миф 3: GPU неэффективны с точки зрения


энергопотребления
Мифы о вычислениях на GPU

Миф 3: GPU неэффективны с точки зрения


энергопотребления

Показатель производительность/ватт для GPU от 4 до 20 раз


выше чем у CPU
до 89 раз для некоторых применений
Мифы о вычислениях на GPU

Миф 4: GPU не используют “настоящую” арифметику с


плавающей точкой
Мифы о вычислениях на GPU

Миф 4: GPU не используют “настоящую” арифметику с


плавающей точкой

GPU поддерживают стандарт IEEE-754


Сравнимы с другими вычислительными устройствами
Поддерживаются вычисления с двойной точностью
Поддержка операций с двойной точностью
NVIDIA GPU SSE2 Cell SPE
Поддержка стандарта IEEE 754 IEEE 754 IEEE 754

Режимы округления для FADD и FMUL Все 4 режима IEEE: rtne, zero, inf, -inf Все 4 режима IEEE: rtne, zero, inf, -inf Только zero/truncate

Обработка денормализованных чисел С полной скоростью Поддерживается, 1000+ циклов Не поддерживается


Поддержка NaN Да Да Нет
Поддержка переполнений и
Да Да Бесконечности отсутствуют
бесконечностей
Флаги Нет Да Некоторые
FMA Да Нет Да

Извлечение квадратного корня Эмуляция на основе FMA Аппаратная поддержка Программная эмуляция

Деление Эмуляция на основе FMA Аппаратная поддержка Программная эмуляция

Точность операции 1/x 24 bit 12 бит 12 бит

Точность операции 1/sqrt(x) 23 bit 12 бит 12 бит

Точность операций log2(x) и 2^x 23 bit Нет Нет

8
Вопросы ?

GPU
CPU

Oil & Gas Finance Medical Biophysics Numerics Audio Video Imaging

© NVIDIA Corporation 2008


Backup slides
Производительность DGEMM
FFT Performance: CPU vs GPU (8-Series)
1D Fast Fourier Transform NVIDIA Tesla C870 GPU (8-series GPU)
Quad-Core Intel Xeon CPU 5400 Series 3.0GHz,
On CUDA In-place, complex, single precision
90

80

70
GFLOPS

60
CUFFT
50
2.x
40 CUFFT
1.1
30 • Intel FFT numbers
calculated by repeating
20
same FFT plan
10 • Real FFT performance is
~10 GFlops
0

Transform Size (Power of 2)


Source for Intel data : http://www.intel.com/cd/software/products/asmo-na/eng/266852.htm
Single Precision BLAS: CPU vs GPU (10-series)
CUBLAS: CUDA 2.0b2, Tesla C1060 (10-series GPU)
BLAS (SGEMM) on CUDA ATLAS 3.81 on Dual 2.8GHz Opteron Dual-Core
350

CUDA
300

ATLAS 1
250
Thread
GFLOPS

200

150

100

50

Matrix Size
Double Precision BLAS: CPU vs GPU (10-series)
CUBLAS CUDA 2.0b2 on Tesla C1060 (10-series)
BLAS (DGEMM) on CUDA ATLAS 3.81 on Intel Xeon E5440 Quad-core, 2.83 GHz
70

CUBLAS
60

50
GFLOPS

40

30

20

10

Matrix Size
Folding@Home

Distributed computing to study protein folding


Alzheimer’s Disease
Huntington’s Disease
Cancer
Osteogenesis imperfecta
Parkinson’s Disease
Antibiotics

CUDA client available now!

© NVIDIA Corporation 2008 93


Molecular Dynamics : GROMACS

Folding@Home

600

450 511
ns/day

300 369

4 150
170
4 100
CPU 0 PS3 ATI GPU Tesla 8 Tesla 10

NVIDIA GPUS
© NVIDIA Corporation 2008
National Center for Atmospheric Research
Weather Research and Forecast (WRF) model
4000+ registered users worldwide
First-ever release with GPU acceleration
12km CONUS WRF benchmark
Running on NCSA CUDA cluster

Adapted 1% of WRF code to CUDA

Resulted in 20% overall speedup

Ongoing work to adapt more


of WRF to CUDA

© NVIDIA Corporation 2008


Astrophysics N-Body Simulation

12+ billion body-body interactions per second


300 GFLOP/s+ on GeForce 8800 Ultra http://progrape.jp/cs/
1-5 GFLOP/s on single-core CPU
Faster than custom GRAPE-6Af n-body computer
http://www.astrogpu.org/
© NVIDIA Corporation 2008
Linear Scaling with Multiple GPUs
Oil and Gas Computing: Reverse Time Migration
Hand Optimized SSE Versus CUDA C
200

160
GFLOPS

120

80

40

0
1 4 8 128 256 384

X86 CPU Number of Cores


NVIDIA GPU
Cambridge University Turbomachinery CFD
Partial differential equations on structured grids

NVIDIA GPUs enable faster design cycles


and new science

Up to 10 million points on a single GPU

Scales to many GPUs using MPI

10x – 20x speedup Intel Core2 Quad 2.33 GHz


CFD analysis of a jet engine fan, courtesy of Vicente Jerez Fidalgo, Whittle Lab
Slide courtesy of Tobias Brandvik and Graham Pullan, Whittle Lab
© NVIDIA Corporation 2008

Вам также может понравиться