Próximo post

Material de Otimização CUDA, do Prof. PhD Fernando Magno Quintão Pereira
http://homepages.dcc.ufmg.br/~fernando/classes/gpuOpt
http://homepages.dcc.ufmg.br/~fernando/classes/gpuOpt/jai.pdf

Dissertação de Mestrado: Um estudo do uso eficiente de programas em placas gráficas

Título:

Um estudo do uso eficiente de programas em placas gráficas

Autora:

Patricia Akemi Ikeda
Mestrado em Ciência da Computação
Instituto de Matemática e Estatística
Universidade de São Paulo

Resumo:

Inicialmente projetadas para processamento de gráficos, as placas gráficas
(GPUs) evoluíram para um coprocessador paralelo de propósito geral de alto
desempenho. Devido ao enorme potencial que oferecem para as diversas áreas
de pesquisa e comerciais, a fabricante NVIDIA destaca-se pelo pioneirismo
ao lançar a arquitetura CUDA (compatível com várias de suas placas), um
ambiente capaz de tirar proveito do poder computacional aliado à maior facilidade
de programação.
Na tentativa de aproveitar toda a capacidade da GPU, algumas práticas
devem ser seguidas. Uma delas consiste em manter o hardware o mais ocupado
possível. Este trabalho propõe uma ferramenta prática e extensível que
auxilie o programador a escolher a melhor configuração para que este objetivo
seja alcançado.

Material:

Slides apresentação
Dissertação

An Analytical Model for a GPU Architecture with Memory-level and Thread-level Parallelism Awareness

Artigo: An analytical model for a GPU architecture with memory-level and thread-level parallelism awareness

Para poder entender os gargalos das aplicações para GPGPU foi criado este modelo analítico simplificado que estima o tempo de execução de kernels massivamente paralelos.

O modelo se baseia no número de requisições de memória concomitantes e introduz duas novas métricas, o paralelismo de memória do sistema (MWP) e o paralelismo de execução de código (CWP). Todas as aplicações do modelo são escritas em CUDA C.

Nosso colega Paulo Carlos da USP fez um excelente resumo do artigo em um seminário apresentado.

Confira nossa série completa de Seminários.

Programming Massively Parallel Processors: A Hands-on Approach

programming_massively_parallel_processors

Programming massively parallel processors

Primeiro textbook em GPGPU, Programming Massively Parallel Processors: A Hands-on Approach é um excelente livro para iniciantes em algoritmos paralelos em GPUs. Partindo de aplicações simples e chegando a casos de estudo reais, os autores abordam técnicas de otimização e aspectos relativos à arquitetura de GPU. O livro baseia-se na linguagem CUDA C e em Saiba mais

CUDA para CPU – MCUDA

Vejam que idéia interessante:

.

CUDA é um modelo de programação de paralelismo de dados que oferece várias abstrações-chave como thread blocks, hierarquia de memória e barreira de sincronização para escrever aplicações. Esse modelo tem sido provado eficiente para a programação de GPUs.

Esse paper de Stratton, Stone & Hwu (2008) descreve um framework chamado MCUDA, que permite que programas CUDA sejam executados eficientemente em multi-core CPUs de memória compartilhada.

Com esses resultados, eles mostram que CUDA pode ser um model de programação paralela eficiente não só para arquiteturas de GPUs.

.

Clique aqui para ver o artigo.

Clique aqui para ver a página de download do MCUDA.

The OpenCL Programming Book

The book starts with the basics of parallelization, covers the main concepts, grammar, and setting up a development environment for OpenCL, concluding with source-code walkthroughs of the FFT and Mersenne Twister algorithms written in OpenCL.
It is highly recommended for those wishing to get started on programming in OpenCL.

Format: Adobe Reader (PDF)
File Size: 3.49MB
Digital: 246 pages
Price: USD 19.50
Publisher: Fixstars Corporation
Author: Fixstars Corporation (Ryoji Tsuchiyama, Takashi Nakamura, Takuro Iizuka, Akihiro Asahara, Satoshi Miki)

Published Date: 3/31/2010

.
OpenCL Programming Contents

Introduction to Parallelization
Why Parallell
Parallel Computing (Hardware)
Parallel Computing (Software)
Conclusion
OpenCL
What is OpenCL?
Historical Background
An Overview of OpenCL
Why OpenCL?
Applicable Platforms
OpenCL Setup
Available OpenCL Environments
Developing Environment Setup
First OpenCL Program
Basic OpenCL
Basic Program Flow
Online/Offline Compilation
Calling the Kernel
Advanced OpenCL
OpenCL C
OpenCL Programming Practice
Case Study
FFT (Fast Fourier Transform)
Mersenne Twister
Notes
.
Ver detalhes e comprar.

Comparação GPU x sistemas paralelos

Monografia de conclusão de curso de A. V. Grammelsbacher e J. C. C. Medrado.

O trabalho visa fornecer um estudo comparando a execução de algoritmos paralelos na CPU e na GPU, elucidando se é mais vantajoso executar determinados algoritmos na CPU ou na GPU. Para realizar as comparações são feitos benchmarks da execução de algoritmos com a finalidade de medir a capacidade de processamento em FLOPS , a cópia de dados na memória entre outras características do sistema.

Comparacao de desempenho entre GPGPU e Sistemas Paralelos

Livro: “Numerical Recipes in C”

O livro “Numerical Recipes in C” é um bom ponto de partida para se aprender sobre vários métodos numéricos, como resolução de sistemas lineares, maximização e minimização de funçoes, FFT e outros métodos. Cada capítulo do livro possui uma rápida explicação do método, seguido do seu respectivo código-fonte. Além disso, caso o leitor deseje se aprofundar mais em um determinado método, existem algumas referências bibliográficas no final de cada capítulo.

Neste link, encontra-se o índice do livro, onde é possível consultar os contéudos que o livro aborda.

Sinopse do artigo: BEMxGPU

Achei um artigo muito interessante,

Takahashi, T.; Hamada, T. (2009): “GPU-accelerated boundary element method for Helmhotz’ equation in three dimensions“.

Mesmo para quem conhece Elementos de Contorno, vale a pena ler o artigo. Aprendi várias coisas sobre GPU com ele, mesmo sem ter entendido muito a parte de Elementos de Contorno (apesar de ser minha área de pesquisa):

Peak performance

O artigo fala que “um processador escalar é capaz de executar 2 operações aritméticas por ciclo de clock. Nossa GPU tem 1.17 GHz e 12 multiprocessadores, num total de 96 processadores escalares. Portanto, a peak performance é de 228.1 Gflop/s”.

O “portanto é novo pra mim. Eu não sabia que era possível calcular a peak performance da máquina a partir desses dados… Como dá pra ver o clock da minha GPU no manual (1,296 GHz), e eu sei que ela tem 30 multiprocessadores, agora sei que a peak performance dela é 622.1 Gflop/s.

Fonte de citação

O artigo revê vários conceitos da programação CUDA e da tecnologia GPGPU. Isso é bom não só pra reforçar nosso know-how, mas também é sempre bom ter fontes adicionais pra citar nos nossos artigos. Frases de efeito que o artigo usa que talvez você queira citar:

  • Um warp tem mesmo 32, e não 16 threads;
  • O manual CUDA recomenda blocos com múltiplos de 64 threads para máxima performance;
  • A velocidade de floating-point operations throughput atual das GPUs é até 20 vezes maior que da CPU;
  • Programas de engenharia têm sido experimentados na GPU antes de CUDA, com OpenGL, DirectX, Cg e dispositivos dedicados.

Custo computacional

O artigo revisa o custo computacional de importantes métodos matemáticos. Por exemplo, ele fala que o custo computacional da solução direta de sistemas lineares (como escalonamentos, pivoteamentos, eliminação de Gauss) é da ordem de O(N3), e o consumo de memória é O(N2). Ele diz isso pra justificar a escolha de métodos iterativos no trabalho, como o gradiente conjugado, cujo custo computacional cai pra O(N2) e o consumo de memória cai pra O(N). Boa justificativa pro pessoal que mexe com gradiente conjugado & cia! O artigo ressalva, contudo, que o custo nesses métodos iterativos é proporcional ao número de iterações necessários para o método convergir, e que portanto um pré-condicionamento da matriz é sempre necessário para minimizar esse custo.

Em outro ponto no final do artigo, eles confirmam essa afirmação comparando um pré-condicionador (point-Jacobi), que permitiu convergência em 543 passos e 7498 s, com outro (block-diagonal) que convergiu em 446 passos em 9095 s (não, o resultado não está invertido). Essa diferença de 21% na eficiência justifica investir no estudo de pré-condicionadores.

E já que estamos falando de sistemas lineares: o artigo também alerta que sistemas lineares podem apresentar autovalores fictícios, que podem não só desacelerar a convergência do solver como degenerar os resultados. Há métodos para remover esses autovalores, como o de Burton-Miller, citado no trabalho.

Benchmark justo

Quando comparamos um código em GPU com CPU, os códigos têm que ser o mais parecidos possível para que a comparação seja justa. Para garantir que a comparação seja justa, o artigo faz uma coisa que eu nunca tinha visto: ele conta o número de operações que o algoritmo executa: quantas adições/subtrações, multiplicações, e uso de funções transcendentais. Aí é só garantir que CPU e GPU executem o mesmo número de operações, e a comparação terá sido justa. De quebra, aprendi que há uma forma de executar divisões implementada em hardware! É a função __fdividef(alfa,beta), que equivale a alfa/beta (eu só conhecia __sinf e __cosf).

Precisão mista

O artigo traz uma explicação bem detalhada sobre como fazer precisão mista, que serve para usar precisão dupla só quando for necessário ou para emular precisão dupla em GPUs que não têm esse recurso. Tem até um trecho de código explicando como fazer isso:

static __device__ __inline__ void dsacc0(float *ah, float *al, float b)

{

float t1 = *ah + b;

float e = t1 – *ah;

float t2 = ((b-e) + (*ah – (t1 – e))) + *al;

*ah = t1 + t2;

*al = t2 – (*ah – t1);

}

Todos sabemos que precisão dupla ainda é um ponto fraco das GPGPUs. A maioria só tem precisão simples, e nas que têm precisão dupla, o desempenho é dezenas de vezes inferior do que o da precisão simples. No entanto, precisão dupla, que é inútil em cálculos gráficos, é essencial em problemas de engenharia como o método dos elementos de contorno (assunto do artigo).

Threads por bloco

Na página 18, os autores contam em detalhes como fizeram para otimizar o número de threads por bloco.

  • Nthreads deve ser múltiplo de 64, de acordo com o manual do CUDA;
  • Cada bloco tem somente 16kb de memória compartilhada;
  • Os múltiplos de 64 que não excedem 16kb (neste problema) são: 64, 128, 192, 256 e 320;
  • Blocos com esses números de threads usariam respectivamente 1408, 2816, 4416, 5632 e 7360 registradores (neste problema). Como o número máximo de registradores é 8192, esse não é um parâmetro a se preocupar (neste problema);
  • Dois ou mais blocos são recomendados por multiprocessador, para compensar a carga de latência;
  • Como os blocos de 192, 256 e 320 threads resultariam em menos que isso, essas opções são descartadas;
  • 64 threads resultaria em 5 blocos por multiprocessador, mas o artigo afirma que a eficiência de caching de dados diminui com o tamanho do bloco;
  • Conclusão: o tamanho ótimo do bloco é 128 threads (de largura).

É interessante ler a discussão inteira. Dá várias idéias sobre como escolher o tamanho de bloco nos nossos próprios problemas.

Padrões de floats

Devido à imprecisão dos resultados da GPU, não é uma boa idéia usá-la na integração numérica de singularidades. Como essa integração é necessária no método dos elementos de contorno, os autores fizeram com que a parte singular das integrais fosse calculada pela CPU e a parte não-singular pela GPU. O resultado da integral era a soma dos resultados dos dois dispositivos. Aí a surpresa: GPUs não seguem a mesma especificação IEEE-754 sobre aritmética de ponto flutuante que as CPUs seguem! Assim, a partir de um dado número de elementos, a precisão do resultado da integral “quebrava”, isto é, a integral não melhorava se o integrador fosse refinado.

Observe como a GPU em precisão simples perde precisão mesmo com o aumento do refinamento.

Observe como a GPU em precisão simples perde precisão mesmo com o aumento do refinamento.

Isso parece ter sido tão frustrante que os autores desistiram de usar precisão simples a partir daí (apesar dela ser incrivelmente mais rápida na GPU).

Limite da GPU

Meus programas sempre têm um limite de tamanho de dados que eu posso usar, mas nunca investiguei isso a fundo. No fim, não sei a razão desse limite. Nesse artigo, um gráfico pouco usual é plotado. No eixo y, em vez de milissegundos, são mostrados Gflop/s.

Figura 5: Performance da GPU em tempo total versus tempo de kernel.

Figura 5: Performance da GPU em tempo total versus tempo de kernel.

Como a porcentagem de capacidade de computação do kernel vai sempre se aproximando da do programa completo e o total tende a uma assíntota (claro, a GPU tem uma peak performance), os autores concluíram que o programa deles era limitado pela aritmética, e não pela largura de banda de memória.

Boa leitura!

Abrindo a caixa-preta das GPUs NVIDIA

Vasily Volkov e James W. Demmel deram uma importante contribuição às técnicas de programação de GPUs NVIDIA das séries 8, 9 e 200, no artigo intitulado “Benchmarking GPUs to Tune Dense Linear Algebra”. Usaram as ferramentas de software concebidas por Wladimir J. van der Laan (um Assembler e um Desassembler) para ter acesso ao código em linguagem Assembly das GPUs, que não é informado pela NVIDIA, e assim entender melhor a arquitetura do hardware para obter o máximo desempenho. É leitura indispensável para quem quer extrair até o último FLOPS da sua GPU.

Seguir

Obtenha todo post novo entregue na sua caixa de entrada.