Patrício Domingues Dep. Eng. Informática ESTG Instituto Politécnico de Leiria Leiria, Maio 2012 http://bit.ly/patricio Programação Genérica de GPUs 1
CUDA Teaching Center A ESTG/IPLeiria é um CUDA Teaching Center para 2011-12 O único de Portugal http://research.nvidia.com/content/cuda-teaching-centers 2
Agenda Introdução ao GPGPU CPU vs GPU CUDA OpenCL OpenCL vs CUDA Término 3
GPU Graphical Processing Unit GPGPU Vulgo placa gráfica O que é GPGPU? Generic Programming of GPU Programação de placas gráficas para a execução de programas genéricos Programas não necessariamente gráficos 45X 35X 110-240X 4
Porquê GPUs? (1) O poder computacional das GPUs tem crescido muito mais rapidamente que o dos CPUs O mercado (e evolução) das GPUs é sustentado em grande parte pelos...gamers! 5
Obrigado Gamers! 6
Porquê GPUs? (2) A filosofia GPU é explorar paralelismo Aplicar simultaneamente a mesma operação a um conjunto de píxeis Lembrete: GPU servem primariamente para...gráficos! Conceito de manycore GPU têm muitos cores Um CPU tem que procurar ser eficiente num muito maior espetro de aplicações Um core CPU é mais poderoso e versátil do que um core GPU Intel i7 Sandy Bridge-E versus NVIDIA GTX 680 i7: 6 cores (x2 com hyperthreading) GTX 680: 1536 cores (8 x 192) 7
CPU vs GPU (1) CPU Baixa largura de banda CPU-memória Acesso aleatório à memória Nível médio de paralelismo Suporta código para qualquer fim GPU Elevada largura de banda GPU-memória Acesso serializado à memória Elevado nível de paralelismo Orientado para processamento paralelo de dados Fonte: Daniel Moth, C++ AMP, Principle Program Manager 8
CPU vs GPU (2) Core i7 Sandy Bridge NVIDIA Kepler (GTX 680) 9
Programação de GPUs Antigamente... Necessário recorrer às APIs gráficas (e.g., OpenGL) para execução de processamento genérico de dados Difícil de programar, muito pouco produtivo Em 2007, a NVIDIA lançou o CUDA CUDA: Compute Unified Device Architecture Simplifica a programação e execução de código na GPU Acessível como (pequena) extensão à linguagem C Também acessível via outras linguagens (C++,Java, Python, etc.) Presentemente na versão 4.2 (5.0 a caminho) Mas...CUDA apenas corre em hardware NVIDIA 10
Paradigma de programação orientado à thread GPU suporta a existência simultânea de vários milhares de threads Granulosidade diferente das threads num contexto CPU Idealmente, as threads executam as mesmas instruções sobre dados diferentes Exemplo Modelo SIMT Single Instruction Multiple Thread soma de dois vetores com N elementos cada thread soma apenas um elemento CUDA 1 2 3 N t 1 t 2 t 3 t i t n 2 4 6 2N t 1 t 2 t 3 t i t n 3 6 9 3N V_a + V_b = V_c 11
Quero ver código fonte! (1) O CUDA distingue entre código... a ser executado no CPU host a ser executado no GPU device Código executado no GPU Ponto de entrada: kernel global O compilador ( nvcc ) converte código fonte para PTX (instruções do GPU) ID da thread /* N: tamanho dos vetores */ global void addv(int *V_a, int *V_b, int *V_c, int N) { int i = threadidx.x; while( i < N) { V_c[i]=V_a[i]+V_b[i]; // salta p/ próximo i += blockdim.x; } } 12
Quero ver código fonte! (2) Cada thread executa o código do kernel Cada thread tem um threadidx.x diferente Cada thread efetua a soma dos elementos de índice threadidx.x Cada thread executa num core distinto ID da thread /* N: tamanho dos vetores */ global void addv(int *V_a, int *V_b, int *V_c, int N) { int i = threadidx.x; while( i < N) { V_c[i]=V_a[i]+V_b[i]; // salta p/ próximo i += blockdim.x; } } 13
Chamada ao kernel GPU Corresponde à execução do kernel no GPU A chamada é feita a partir do CPU Como é chamado o kernel? (1) addv<<<numblocos,threadsporbloco>>>(va,vb,vc,n); NumBlocos Número de blocos de threads que vão executar o kernel ThreadsPorBloco Número de threads por bloco addv<<<5,6>>>(...) 5 blocos de threads, cada um com 6 threads 14
Como é chamado o kernel? (2) Na realidade, o CUDA disponibiliza uma organização que pode ser tridimensional para a especificação dos blocos de execução Exemplo (duas dimensões) dim3 NumBlocosXY(3,2); dim3 ThreadBlocosXY(4,3); addv<<<numblocos,threadsblocos>>> (va,vb,vc,n); 15
Coordenadas no GPU Coordenadas acessíveis no código da GPU (blockidx.x,blockidx.y) (threadidx.x,threadidx.y) griddim.x griddim.y /* N: tamanho dos vetores */ global void addv(int *V_a, int *V_b, int *V_c, int N) { int i = threadidx.x; while( i < N) { V_c[i]=V_a[i]+V_b[i]; // salta p/ próximo i += blockdim.x; } } blockdim.x 16 blockdim.y
OK, e a memória? A memória do GPU é separada da memória do CPU Exemplos NVIDIA GTX 680 2GB (GPU) Intel i7 Sandy Bridge-E 8 GB (CPU) Espaços de endereçamento diferentes Implicações Cópia explícita de dados entre CPU e GPU via PCI-express CPU GPU PCI-Express Memória CPU Memória GPU 17
Gestão da memória O programador é responsável por... Alocar memória do GPU cudaerror_t cudamalloc(void ** devptr, size_t size); Transferir explicitamente os dados do CPU para o GPU cudaerror_t cudamemcpy(void *dst, const void *src, size_t count, cudamemcpyhosttodevice); Transferir explicitamente os resultados do GPU para o CPU cudaerror_t cudamemcpy(void *dst, const void *src, size_t count, cudamemcpydevicetohost); Libertar memória cudaerror_t cudafree(void *devptr); 18
Ainda sobre memória (1/2) thread Bloco threads Memória local Registos GPU Memória partilhada shared Memória local é privada à thread Implementada na memória global do GPU Registos são a memória mais rápida (on chip) Número limitado Memória partilhada é acessível por bloco de threads Memória rápida (on chip) Requer sincronização entre as threads do bloco 19
Ainda sobre memória (2/2) Kernel 1 Kernel 2 Memória global GPU (peristente entre chamadas a kernels) CPU Memória CPU Memória constantes (leitura) O desempenho de aplicações CUDA está muito dependente da forma como se usa a memória! 20
Estrutura de programa CUDA Estrutura de programa CUDA #1- Alocar memória (cudamalloc(...)) #2 - Copiar conteúdo memória CPU GPU (cudamemcpy(..., cudamemcpyhosttodevice)) #3 Lançar kernel (func<<<blocos,threads>>>(...)) #4 - Execução (assíncrona) do kernel, CPU fica livre (cudadevicesynchronize()) #5 Copiar resultados GPU CPU (cudamemcpy(...,cudamemcpydevicetohost)) #6 Libertar recursos (cudafree(...)) 21
Ainda sobre CUDA Foi apresentado o CUDA runtime API level Interface de alto (!) nível Alternativa CUDA driver API level API de baixo nível O programador deve: Explicitar inicialização do dispositivo Carregamento de módulo Carregmanento de parâmetros Execução de kernel(s)... 22
OpenCL Outros paradigmas/frameworks para GPGPU OpenCL Norma proposta pela Apple e apoiada por muitas empresas Intel, AMD/ATI, IBM, Samsung,..., NVIDIA Presentemente na versão 1.2 (Dez. 2011) Pequena extensão à linguagem C Visa o suporte de vários dispositivos de processamento ( aceleradores ) Norma mais genérica do que o CUDA» Requer mais esforço do programador Exemplos: GPUs, CPUs (Intel, CELL, etc.) 23
Suporte para vários aceleradores Driver OpenCL AMD Código OpenCL Driver OpenCL NVIDIA Driver OpenCL CELL Driver OpenCL Intel 24
OpenCL vs CUDA API requer elevado número de parâmetros Suporte para dispositivos genéricos Exemplo: clenqueuereadbuffer(...) cl_int clenqueuereadbuffer( cl_command_queue command_queue, cl_mem buffer, cl_bool blocking_read, size_t offset, size_t cb, void*ptr, cl_uint num_events_in_wait_list, const cl_event*event_wait_list, cl_event*event) cudaerror_t cudamemcpy(void *dst, const void *src, size_t count, cudamemcpydevicetohost); 25
Estrutura de programa OpenCL Obter informação sobre dispositivos disponíveis Seleção dos dispositivos a serem empregues Criação de uma command queue OpenCL Criação dos buffers no dispositivo Transferência dados do CPU para o dispositivo Criação do objeto kernel program Compilação do kernel Criação do objeto kernel Suporte dispositivos genéricos Requer muitos mais passos... Configuração dos parâmetros do kernel Execução do kernel Cópia dos resultados (dispositivo CPU) Libertar recursos 26
E a Microsoft? C++ AMP (C++ Accelerated Massive Parallelism) Norma aberta da Microsoft baseada no DirectX11 Apenas disponível para sistemas Windows... Aproveitamento de GPU para GPGPU Extensão à linguagem C++ e biblioteca para processamento de dados multidimensionais #include <amp.h> using namespace concurrency; void AddArrays(int n, int * pa, int * pb, int * pc) { array_view<int,1> a(n, pa); array_view<int,1> b(n, pb); array_view<int,1> sum(n, pc); parallel_for_each( sum.grid, [=](index<1> i) restrict(direct3d) { sum[i] = a[i] + b[i]; } ); } 27
Onde posso saber mais? Mestrado em Eng. Informática Computação Móvel UC de Computação de Alto Desempenho NVIDIA CUDA Programming Guide CUDA Zone (documentation) CUDA C BEST PRACTICES GUIDE NVIDIA CUDA C - Programming Guide http://www.nvidia.com/object/cuda_develop.html Programming Massively Parallel Processors: A Hands-on Approach, David B. Kirk, Wen-mei W. Hwu, Morgan Kaufmann, 1st edition (February 2010) 28
Obrigado! Questões? (c) Internet, 2012 (e obrigado OpenClipArt.org) 29