O documento apresenta uma visão geral sobre paralelização automática de código, conceitos sobre o modelo polyhedral e ferramentas que utilizam essa abordagem. É discutido o processo de detecção de regiões paralelizáveis em código, transformações de laços e representação no modelo polyhedral. Exemplos demonstram a tradução de código C para LLVM IR e CUDA para execução em GPUs.
Delphi is an integrated development environment (IDE) for console, desktop graphical, web, and mobile applications. Delphi's compilers use their own Object Pascal dialect of Pascal and generate native code for 32- and 64-bit Windows operating systems, as well as 32-bit Mac OS X and iOS. (iOS code generation is done with the Free Pascal compiler). As of late 2011 support for the Linux and Android operating system was planned by Embarcadero. To create applications for managed code platforms, a similar (but not mutually compatible) alternative is Delphi Prism. Delphi was originally developed by Borland as a rapid application development tool for Windows, and as the successor of Borland Pascal. Delphi and its C++ counterpart, C++Builder, shared many core components, notably the IDE and VCL, but remained separate until the release of RAD Studio 2007. RAD Studio is a shared host for Delphi, C++Builder, and others. In 2006, Borland’s developer tools section were transferred to a wholly owned subsidiary known as CodeGear, which was sold to Embarcadero Technologies in 2008.
"The topological instability model for metallic glass formation: MD assessmen...lccausp
"The topological instability model for metallic glass formation: MD assessment", presented at http://3whpc.lcca.usp.br
Cited video available at http://youtu.be/x3XbeN7uJ84
Delphi is an integrated development environment (IDE) for console, desktop graphical, web, and mobile applications. Delphi's compilers use their own Object Pascal dialect of Pascal and generate native code for 32- and 64-bit Windows operating systems, as well as 32-bit Mac OS X and iOS. (iOS code generation is done with the Free Pascal compiler). As of late 2011 support for the Linux and Android operating system was planned by Embarcadero. To create applications for managed code platforms, a similar (but not mutually compatible) alternative is Delphi Prism. Delphi was originally developed by Borland as a rapid application development tool for Windows, and as the successor of Borland Pascal. Delphi and its C++ counterpart, C++Builder, shared many core components, notably the IDE and VCL, but remained separate until the release of RAD Studio 2007. RAD Studio is a shared host for Delphi, C++Builder, and others. In 2006, Borland’s developer tools section were transferred to a wholly owned subsidiary known as CodeGear, which was sold to Embarcadero Technologies in 2008.
"The topological instability model for metallic glass formation: MD assessmen...lccausp
"The topological instability model for metallic glass formation: MD assessment", presented at http://3whpc.lcca.usp.br
Cited video available at http://youtu.be/x3XbeN7uJ84
Extração de Features Usando Compilação CondicionalCamilo Ribeiro
Monografia apresentada por Camilo Ribeiro como requisito parcial para a obtenção do título de Especialista em Engenharia de Software pela Universidade Federal de Minas Gerais
"Aula sobre Paralelização Automática". Rogério A. Gonçalves e Prof. Dr. Alfredo Goldman IME/USP.
1. Paralelização Automática de Código em Plataformas
Heterogêneas Modernas
Rogério A. Gonçalves1,2 Alfredo Goldman1
1Laboratório de Sistemas de Software (LSS)
Centro de Competência de Software Livre (CCSL)
Instituto de Matemática e Estatística (IME)
Universidade de São Paulo (USP)
2Departamento de Computação (DACOM)
Universidade Tecnológica Federal do Paraná (UTFPR)
Grupo de Computação de Alto Desempenho e Sistemas Distribuídos
rogerioag@utfpr.edu.br, {rag,gold}@ime.usp.br
3o Workshop de High Performance Computing
Convênio: USP – Rice University
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 1 / 55
2. Roteiro
1 Introdução
2 Conceitos
3 Abordagens sobre Paralelização
4 Transformações de Laços
5 Modelo Polyhedral
6 Ferramentas e Exemplos
7 LLVM e Ferramentas
8 Dúvidas
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 2 / 55
3. Objetivos
Uma visão geral sobre a abordagem de paralelização
automática.
Alguns conceitos sobre o Modelo Polyhedral.
Apresentar algumas ferramentas que utilizam esse
modelo.
Apresentar as ferramentas e projetos LLVM.
Exemplos práticos indo do fonte original ao código para
GPU.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 3 / 55
4. Introdução I
Evolução e heterogeneidade das plataformas de
hardware.
Dispositivos aceleradores tem sido utilizados na
composição de supercomputadores.
Não há suporte direto à reescrita de aplicações
existentes.
Os kits de desenvolvimento ainda não estão maduros o
suficiente.
Programar novas aplicações ou traduzir aplicações de
código legado não é uma tarefa trivial.
Ponto de vista do software.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 4 / 55
5. Introdução II
Plataformas vs. Aplicações
No cenário atual é evidente a grande distância entre o
potencial de desempenho disponibilizado pelas plataformas
modernas e as aplicações que precisam fazer uso desse
potencial.
Soluções
O ideal é que a ligação entre esses contextos seja feita por
ferramentas de compilação e ambientes de execução.
Fornecendo suporte à execução de aplicações novas e de
código legado.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 5 / 55
6. Paralelização de Aplicações I
Existem pelo menos duas formas de se obter aplicações
paralelas:
Concepção de aplicações paralelas
Adaptar aplicações existentes
Nas duas formas, existe um modelo de programação
que fornece suporte à escrita ou adaptação do código, e
um modelo de execução que irá executar a versão
paralela do código.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 6 / 55
7. Paralelização de Aplicações II
No contexto de tradução de código, tem-se pelo menos
duas abordagens conhecidas de paralelização que se
distinguem na forma e no momento da intervenção para
paralelização:
Via código fonte: depende da existência do código
fonte (source-to-source).
Via código binário: aplica transformações sobre o
binário gerado para a execução da aplicação.
(Tradução Dinâmica - DBT).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 7 / 55
8. Aceleração de Aplicações I
A aceleração de aplicações está relacionada com as
plataformas modernas.
São plataformas heterogêneas, que congregam diversas
tecnologias e seus elementos de processamento que
trabalham como aceleradores na execução de
aplicações.
Como exemplos dos dispositivos que atualmente
compõem essas plataformas temos os arranjos de
coprocessadores Xeon Phi (Intel), as GPUs (NVidia,
AMD) e FPGAS (Xilinx, Altera).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 8 / 55
9. Aceleração de Aplicações II
O uso de dispositivos aceleradores torna possível a
divisão da carga de execução entre um elemento de
processamento principal e elementos que irão trabalhar
como coprocessadores.
Regiões de código paralelizáveis podem ser
transformadas em kernels e terem sua execução
acelerada em uma GPU. Ex.: Laços.
Trabalhos tem proposto modelos para a execução de
aplicações combinando dispositivos multicore e
multiGPU.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 9 / 55
10. Abordagens que se destacam
Diretivas de Compilação
Diretivas de compilação são usadas para guiar o compilador no processo de
tradução e paralelização de código.
Paralelização Automática
São usadas técnicas e modelos para detectar automaticamente quais
regiões do código são paralelizáveis.
Nas duas abordagens uma versão paralela do código é gerada para a
plataforma alvo.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 10 / 55
11. Diretivas de Compilação
O código é anotado com diretivas de preprocessamento
(#pragma).
Ferramentas que utilizam diretivas
O OpenMP (multicore).
O hiCUDA (transformar e gerar código para CUDA).
O CGCM (otimiza a comunicação e transferências de dados).
Os compiladores PGI e o OpenHMPP que implementam o padrão
OpenACC.
O accULL é uma implementação do padrão OpenACC com suporte a
CUDA e a OpenCL.
O OpenMC é uma extensão do OpenMP para suporte a GPU.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 11 / 55
12. Diretivas de Compilação
Exemplo da diretiva #pragma acc kernels que define uma região de
código que será transformada em kernels.
1 #pragma acc data copy ( b [ 0 : n∗m] ) c r e a t e ( a [ 0 : n∗m] )
2 {
3 f o r ( i t e r = 1; i t e r <= p ; ++i t e r ) {
4 #pragma acc k e r n e l s
5 {
6 f o r ( i = 1; i < n−1; ++i )
7 f o r ( j = 1; j < m−1; ++j ) {
8 /∗ Suprimido . ∗/
9 }
10 f o r ( i = 1; i < n−1; ++i )
11 f o r ( j = 1; j < m−1; ++j )
12 /∗ Suprimido . ∗/
13 }
14 }
15 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 12 / 55
13. Paralelização Automática
A ideia é que o código não seja modificado, nem
anotado.
Regiões paralelizáveis detectadas automaticamente.
Ferramentas da abordagem automática
Par4All (análise interprocedural)
C-to-CUDA
PPCG
KernelGen
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 13 / 55
14. Transformações de Laços I
Técnicas de otimização de laços são utilizadas por
compiladores há muito tempo.
Possibilitam a exploração de processamento paralelo e
reduzem o tempo de execução associado aos laços.
A análise de dependência deve ser feita sobre todas as
iterações do laço.
Uma transformação aplicada deve preservar a semântica
do código original e a sequência temporal de todas as
dependências.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 14 / 55
15. Transformações de Laços II
Transformações podem ser aplicadas para: analisar,
preparar e expor algum paralelismo latente.
Exemplos
loop unrolling, loop interchange, loop skewing, loop
reversal, loop blocking e cycle shrinking, loop fusion,
peeling e distribuição, entre outras.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 15 / 55
16. Detecção de Regiões Paralelizáveis I
No processo de paralelização de código é necessário
detectar as regiões paralelizáveis.
Essas regiões são chamadas de Static Control Parts
(SCoPs).
São partes do código de uma função que podem ser
vistas como uma estrutura de fluxo de controle que
contem apenas laços FOR e IFs.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 16 / 55
17. Transformações de Laços e Modelo Polyhedral I
O Modelo Polyhedral possui um suporte melhor para a
representação e análise de código de laços do que a
AST.
A representação de SCoPs no modelo baseia-se nos
conceitos: domínio de iteração, função de scattering e
função de acesso.
Encontrando-se um SCoP, a região de código pode ser
representada no modelo e transformações e otimizações
podem ser aplicadas à representação gerada.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 17 / 55
18. Transformações de Laços e Modelo Polyhedral II
1 f o r ( i =1; i<=n−1; i ++) {
2 f o r ( j =1; j<=m−1; j++) {
3 A[ i ] [ j ] = (A[ i −1][ j ] + A[ i ] [ j −1] + A[ i +1][ j ] + A[ i ] [ j +1]) /4;
4 }
5 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 18 / 55
19. Transformações de Laços e Modelo Polyhedral III
Função de Scattering: c1 = i + j e c2 = i (novo domínio
de iterações).
Figura 3: Domínio de Iteração
DS1 = {(i, j) ∈ Z2|1 ≤ i ≤ n−1∧1 ≤ j ≤ m−1}
Figura 4: Função de Scattering
θS1(i, j) = (i + j, i)
θS1(i, j) = (c1, c2)
c1 = i + j
c2 = i
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 19 / 55
20. Transformações de Laços e Modelo Polyhedral IV
Código original e modificado com o CLooG (Skewing):
1 f o r ( i =1; i<=n−1; i ++) {
2 f o r ( j =1; j<=m−1; j ++) {
3 A[ i ] [ j ] = (A[ i −1][ j ] + A[ i ] [ j −1] + A[ i +1][ j ] + A[ i ] [ j +1]) / 4 ; // S1
4 }
5 }
Substituindo as variáveis: i = c2 e j = c1 − i = c1 − c2,
tem-se o código final:
1 i f ((m >= 2) && ( n >= 2) ) {
2 f o r ( c1=2;c1<=n+m−2;c1++) {
3 f o r ( c2=max(1 , c1−m+1) ; c2<=min ( c1 −1,n−1) ; c2++) {
4 A[ c2 ] [ c1−c2 ] = (A[ c2 −1][ c1−c2 ] + A[ c2 ] [ c1−c2 −1] + A[
c2 +1][ c1−c2 ] + A[ c2 ] [ c1−c2 +1]) /4; //S1 ’
5 }
6 }
7 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 20 / 55
21. Ferramentas que utilizam o Modelo Polyhedral I
São ferramentas que cobrem desde a extração de
regiões candidatas à paralelização, passando por
bibliotecas que permitem o uso como subprojetos até
geradores de código com base em informações do
Modelo Polyhedral.
Ferramentas que extraem SCoPs: clan e pet.
Gerador de Código para C: CLooG.
Compiladores como PLuTo e PoCC fazem tradução
source-to-source de código C e Fortran.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 21 / 55
22. Ferramentas que utilizam o Modelo Polyhedral II
O C-to-CUDA faz a tradução source-to-source de
código C para CUDA.
PPCG usa as bibliotecas pet e isl para gerar código
OpenMP e CUDA.
O PoLLy é um projeto LLVM que implementa o modelo
polyhedral para código intermediário (LLVM-IR).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 22 / 55
23. Por que usar LLVM? I
LLVM (llvm.org) é um projeto que fornece uma infraestrutura para a
construção de compiladores.
Desenvolvimento: LLVM Team - University of Illinois at
Urbana-Champaign.
Licença: University of Illinois/NCSA Open Source License, certificada
pela OSI.
Sua organização modular facilita o reuso no desenvolvimento de
ferramentas de compilação.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 23 / 55
24. Por que usar LLVM? II
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 24 / 55
25. Exemplo: LLVM IR I
Código em C.
1 i n t main ( ) {
2 i n t a , b , c ;
3 a = 5 ;
4 b = 2 ;
5 c = a + b ;
6
7 i f ( c > 5) {
8 c = 2 ∗ c ;
9 }
10 e l s e {
11 c = 3 ∗ c ;
12 }
13
14 r e t u r n 0 ;
15 }
Código em LLVM-IR.
1 d e f i n e i32 @main ( ) #0 {
2 %1 = a l l o c a i32 , a l i g n 4
3 %a = a l l o c a i32 , a l i g n 4
4 %b = a l l o c a i32 , a l i g n 4
5 %c = a l l o c a i32 , a l i g n 4
6 s t o r e i32 0 , i32 ∗ %1
7 s t o r e i32 5 , i32 ∗ %a, a l i g n 4
8 s t o r e i32 2 , i32 ∗ %b, a l i g n 4
9 %2 = l o a d i32 ∗ %a, a l i g n 4
10 %3 = l o a d i32 ∗ %b, a l i g n 4
11 %4 = add nsw i32 %2, %3
12 s t o r e i32 %4, i32 ∗ %c, a l i g n 4
13 %5 = l o a d i32 ∗ %c, a l i g n 4
14 %6 = icmp s g t i32 %5, 5
15 br i1 %6, l a b e l %vv , l a b e l %ff
16
17 vv : ; preds = %0
18 %7 = l o a d i32 ∗ %c, a l i g n 4
19 %8 = mul nsw i32 2 , %7
20 s t o r e i32 %8, i32 ∗ %c, a l i g n 4
21 br l a b e l %fim
22
23 ff : ; preds = %0
24 %9 = l o a d i32 ∗ %c, a l i g n 4
25 %10 = mul nsw i32 3 , %9
26 s t o r e i32 %10 , i32 ∗ %c, a l i g n 4
27 br l a b e l %fim
28
29 fim : ; preds = %vv, %ff
30 r e t i32 0
31 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 25 / 55
26. Exemplo: LLVM IR I
1 d e f i n e i32 @main ( ) #0 {
2 %1 = a l l o c a i32 , a l i g n 4
3 %a = a l l o c a i32 , a l i g n 4
4 %b = a l l o c a i32 , a l i g n 4
5 %c = a l l o c a i32 , a l i g n 4
6 s t o r e i32 0 , i32 ∗ %1
7 s t o r e i32 5 , i32 ∗ %a, a l i g n 4
8 s t o r e i32 2 , i32 ∗ %b, a l i g n 4
9 %2 = l o a d i32 ∗ %a, a l i g n 4
10 %3 = l o a d i32 ∗ %b, a l i g n 4
11 %4 = add nsw i32 %2, %3
12 s t o r e i32 %4, i32 ∗ %c, a l i g n 4
13 %5 = l o a d i32 ∗ %c, a l i g n 4
14 %6 = icmp s g t i32 %5, 5
15 br i1 %6, l a b e l %vv , l a b e l %ff
16
17 vv : ; preds = %0
18 %7 = l o a d i32 ∗ %c, a l i g n 4
19 %8 = mul nsw i32 2 , %7
20 s t o r e i32 %8, i32 ∗ %c, a l i g n 4
21 br l a b e l %fim
22
23 ff : ; preds = %0
24 %9 = l o a d i32 ∗ %c, a l i g n 4
25 %10 = mul nsw i32 3 , %9
26 s t o r e i32 %10 , i32 ∗ %c, a l i g n 4
27 br l a b e l %fim
28
29 fim : ; preds = %vv, %ff
30 r e t i32 0
31 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 26 / 55
27. Exemplo: LLVM IR I
Código em C.
1 i n t funcA ( i n t x , i n t y ) {
2 i n t r e s u l t = x ∗ y ;
3 r e t u r n r e s u l t ;
4 }
5
6 i n t main ( ) {
7 i n t a , b , c ;
8 a = 5 ;
9 c = funcA ( a , 2) ;
10
11 r e t u r n 0 ;
12 }
Código em LLVM-IR.
1 d e f i n e i32 @funcA ( i32 %x, i32 %y) #0 {
2 %1 = a l l o c a i32 , a l i g n 4
3 %2 = a l l o c a i32 , a l i g n 4
4 % r e s u l t = a l l o c a i32 , a l i g n 4
5 s t o r e i32 %x, i32 ∗ %1, a l i g n 4
6 s t o r e i32 %y, i32 ∗ %2, a l i g n 4
7 %3 = l o a d i32 ∗ %1, a l i g n 4
8 %4 = l o a d i32 ∗ %2, a l i g n 4
9 %5 = mul nsw i32 %3, %4
10 s t o r e i32 %5, i32 ∗ %result , a l i g n 4
11 %6 = l o a d i32 ∗ %result , a l i g n 4
12 r e t i32 %6
13 }
14 d e f i n e i32 @main ( ) #0 {
15 %1 = a l l o c a i32 , a l i g n 4
16 %a = a l l o c a i32 , a l i g n 4
17 %b = a l l o c a i32 , a l i g n 4
18 %c = a l l o c a i32 , a l i g n 4
19 s t o r e i32 0 , i32 ∗ %1
20 s t o r e i32 5 , i32 ∗ %a, a l i g n 4
21 %2 = l o a d i32 ∗ %a, a l i g n 4
22 %3 = c a l l i32 @funcA ( i32 %2, i32 2)
23 s t o r e i32 %3, i32 ∗ %c, a l i g n 4
24 r e t i32 0
25 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 27 / 55
28. Exemplo: LLVM IR I
Código em C.
1 i n t main ( ) {
2 i n t i ;
3 i n t r e s = 0 ;
4 f o r ( i =0; i < 100; i ++){
5 r e s = r e s + i ;
6 }
7
8 r e t u r n 0 ;
9 }
Código em LLVM-IR.
1 d e f i n e i32 @main ( ) #0 {
2 %1 = a l l o c a i32 , a l i g n 4
3 %i = a l l o c a i32 , a l i g n 4
4 %res = a l l o c a i32 , a l i g n 4
5 s t o r e i32 0 , i32 ∗ %1
6 s t o r e i32 0 , i32 ∗ %res , a l i g n 4
7 s t o r e i32 0 , i32 ∗ %i , a l i g n 4
8 br l a b e l %2
9
10 ; < label >:2 ; preds = %9, %0
11 %3 = l o a d i32 ∗ %i , a l i g n 4
12 %4 = icmp s l t i32 %3, 100
13 br i1 %4, l a b e l %5, l a b e l %12
14
15 ; < label >:5 ; preds = %2
16 %6 = l o a d i32 ∗ %res , a l i g n 4
17 %7 = l o a d i32 ∗ %i , a l i g n 4
18 %8 = add nsw i32 %6, %7
19 s t o r e i32 %8, i32 ∗ %res , a l i g n 4
20 br l a b e l %9
21
22 ; < label >:9 ; preds = %5
23 %10 = l o a d i32 ∗ %i , a l i g n 4
24 %11 = add nsw i32 %10 , 1
25 s t o r e i32 %11 , i32 ∗ %i , a l i g n 4
26 br l a b e l %2
27
28 ; < label >:12 ; preds = %2
29 r e t i32 0
30 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 28 / 55
29. Exemplo: LLVM IR I
1 d e f i n e i32 @main ( ) #0 {
2 %1 = a l l o c a i32 , a l i g n 4
3 %i = a l l o c a i32 , a l i g n 4
4 %res = a l l o c a i32 , a l i g n 4
5 s t o r e i32 0 , i32 ∗ %1
6 s t o r e i32 0 , i32 ∗ %res , a l i g n 4
7 s t o r e i32 0 , i32 ∗ %i , a l i g n 4
8 br l a b e l %2
9
10 ; < label >:2 ; preds = %9, %0
11 %3 = l o a d i32 ∗ %i , a l i g n 4
12 %4 = icmp s l t i32 %3, 100
13 br i1 %4, l a b e l %5, l a b e l %12
14
15 ; < label >:5 ; preds = %2
16 %6 = l o a d i32 ∗ %res , a l i g n 4
17 %7 = l o a d i32 ∗ %i , a l i g n 4
18 %8 = add nsw i32 %6, %7
19 s t o r e i32 %8, i32 ∗ %res , a l i g n 4
20 br l a b e l %9
21
22 ; < label >:9 ; preds = %5
23 %10 = l o a d i32 ∗ %i , a l i g n 4
24 %11 = add nsw i32 %10 , 1
25 s t o r e i32 %11 , i32 ∗ %i , a l i g n 4
26 br l a b e l %2
27
28 ; < label >:12 ; preds = %2
29 r e t i32 0
30 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 29 / 55
30. Ferramentas LLVM
Projetos como o DragonEgg, PoLLy e NVPTX
possibilitam que regiões paralelizáveis sejam traduzidas
para kernels que possam ter sua execução lançada em
GPUs.
DragonEgg: Plugin para GCC que traduz código
intermediário (GIMPLE) para a representação
intermediária do LLVM (LLVM-IR).
PoLLy: Implementação do Modelo Polyhedral para
LLVM.
NVPTX: Backend do LLVM para gerar código PTX
(intermediário das GPUs da NVIDIA).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 30 / 55
31. PoLLy I
Aplica otimizações e transformações sobre o código
intermediário LLVM-IR.
Da mesma forma que outras ferramentas, o PoLLy
trabalha com (SCoPs).
O PoLLy implementa um conjunto de passos que
detectam e traduzem essas partes do código para a
representação do modelo polyhedral para que possam
ser aplicadas análises e transformações, e o código
LLVM-IR otimizado gerado.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 31 / 55
32. Gerando Código para GPU
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 32 / 55
33. Exemplo Soma de Vetores I
Código do exemplo soma de vetores:
1 i n t main () {
2 i n t i ;
3 /∗ I n i c i a l i z a c a o dos v e t o r e s . ∗/
4 i n i t _ a r r a y () ;
5
6 /∗ Calculo . ∗/
7 f o r ( i = 0; i < N; i++) {
8 h_c [ i ] = h_a [ i ] + h_b [ i ] ;
9 }
10
11 /∗ Resultados . ∗/
12 print_array () ;
13 check_result () ;
14
15 r e t u r n 0;
16 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 33 / 55
34. Exemplo Soma de Vetores II
Código LLVM-IR equivalente gerado:
1 @h_a = common g l o b a l [1024 x float ] zeroinitializer , a l i g n 16
2 @h_b = common g l o b a l [1024 x float ] zeroinitializer , a l i g n 16
3 @h_c = common g l o b a l [1024 x float ] zeroinitializer , a l i g n 16
4 d e f i n e void @init_array () #0 {
5 }
6 d e f i n e void @print_array () #0 {
7 }
8 d e f i n e void @check_result () #0 {
9 }
10 d e f i n e i32 @main () #0 {
11 %1 = a l l o c a i32 , a l i g n 4
12 %i = a l l o c a i32 , a l i g n 4
13 s t o r e i32 0 , i32∗ %1
14 c a l l void @init_array ()
15 s t o r e i32 0 , i32∗ %i , a l i g n 4
16 br l a b e l %2
17
18 ; <label >:2 ; preds = %18, %0
19 %3 = load i32∗ %i , a l i g n 4
20 %4 = icmp s l t i32 %3, 1024
21 br i1 %4, l a b e l %5, l a b e l %21
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 34 / 55
35. Exemplo Soma de Vetores III
22
23 ; < l a b e l >:5 ; preds = %2
24 %6 = load i32∗ %i , a l i g n 4
25 %7 = s e x t i32 %6 to i64
26 %8 = g e t e l e m e n t p t r inbounds [1024 x float ]∗ @h_a , i32 0 , ←
i64 %7
27 %9 = load float∗ %8, a l i g n 4
28 %10 = load i32∗ %i , a l i g n 4
29 %11 = s e x t i32 %10 to i64
30 %12 = g e t e l e m e n t p t r inbounds [1024 x float ]∗ @h_b , i32 0 , ←
i64 %11
31 %13 = load float∗ %12 , a l i g n 4
32 %14 = fadd float %9, %13
33 %15 = load i32∗ %i , a l i g n 4
34 %16 = s e x t i32 %15 to i64
35 %17 = g e t e l e m e n t p t r inbounds [1024 x float ]∗ @h_c , i32 0 , ←
i64 %16
36 s t o r e float %14 , float∗ %17 , a l i g n 4
37 br l a b e l %18
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 35 / 55
36. Exemplo Soma de Vetores IV
38 ; < l a b e l >:18 ; preds = %5
39 %19 = load i32∗ %i , a l i g n 4
40 %20 = add nsw i32 %19 , 1
41 s t o r e i32 %20 , i32∗ %i , a l i g n 4
42 br l a b e l %2
43
44 ; <label >:21 ; preds = %2
45 c a l l void @print_array ()
46 c a l l void @check_result ()
47 r e t i32 0
48 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 36 / 55
37. Exemplo Soma de Vetores V
O CFG do laço de repetição contido na função main:
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 37 / 55
38. Exemplo Soma de Vetores VI
Laço em destaque como SCoP detectado pelo PoLLy:
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 38 / 55
39. Exemplo Soma de Vetores VII
O PoLLy detecta as SCoPs do código que serão
traduzidas para a representação polyhedral.
O PoLLy pode ser usado para separar o código em
blocos independentes.
Visualização do código com blocos independentes que
foram separados pelo PoLLy.
O SCoP continua sendo o mesmo, porém foi alterado
internamente, com a recuperação dos ponteiros para
elementos dos arranjos sendo feita no início do corpo
do laço.
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 39 / 55
40. Exemplo Soma de Vetores VIII
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 40 / 55
41. Exemplo da Estrutura de um kernel para GPU
Kernel para a soma de vetores:
1 __global__ void vecAdd ( f l o a t ∗ A, f l o a t ∗ B, f l o a t ∗ C, i n t n ) {
2 i n t i d = blockDim . x ∗ b l o c k I d x . x + t h r e a d I d x . x ;
3 i f ( i d < n ) {
4 C[ i d ] = A[ i d ] + B[ i d ] ;
5 }
6 }
7
8 i n t main () {
9 /∗ . . . ∗/
10 i n t threadsPerBlock = 256;
11 i n t b l o c k s P e r G r i d =(N + threadsPerBlock − 1) /
threadsPerBlock ;
12 vecAdd<<<blocksPerGrid , threadsPerBlock >>>(d_A, d_B, d_C, N) ;
13 /∗ . . . ∗/
14 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 41 / 55
42. Mapeamento de identificadores no LLVM-IR
O NVPTX fornece declarações de funções que recuperam os identificadores:
CUDA Significado LLVM-IR para o NVPTX
threadIdx.x Id da Thread na dim. x declare i32 @llvm.nvvm.read.ptx.sreg.tid.x()
threadIdx.y Id da Thread na dim. y declare i32 @llvm.nvvm.read.ptx.sreg.tid.y()
threadIdx.z Id da Thread na dim. z declare i32 @llvm.nvvm.read.ptx.sreg.tid.z()
blockIdx.x Id do Bloco na dim. x declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.x()
blockIdx.y Id do Bloco na dim. y declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.y()
blockIdx.z Id do Bloco na dim. z declare i32 @llvm.nvvm.read.ptx.sreg.ctaid.z()
blockDim.x Dimensão x do Bloco declare i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
blockDim.y Dimensão y do Bloco declare i32 @llvm.nvvm.read.ptx.sreg.ntid.y()
blockDim.z Dimensão z do Bloco declare i32 @llvm.nvvm.read.ptx.sreg.ntid.z()
gridDim.x Dimensão x do Grid declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.x()
gridDim.y Dimensão y do Grid declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.y()
gridDim.z Dimensão z do Grid declare i32 @llvm.nvvm.read.ptx.sreg.nctaid.z()
warp size Tamanho do warp declare i32 @llvm.nvvm.read.ptx.sreg.warpsize()
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 42 / 55
43. Transformação para Kernels I
Funções de módulos LLVM-IR podem ser transformados em kernels.
Para exemplificar a transformação de funções para a estrutura de
kernels, consideremos o exemplo soma de vetores. Tanto o CFG da
função principal (main), quanto a função sum_vectors().
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 43 / 55
44. Transformação para Kernels II
A correspondência entre os trechos de código LLVM-IR original e o
formato para o NVPTX. Transformação da função sum_vectors para
kernel:
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 44 / 55
45. Transformação para Kernels III
Sequência de passos necessários para gerar, carregar o código do
kernel e efetuar transferências:
1 v o i d sum_vectors ( ) {
2 /∗ Gerando o PTX. ∗/
3 char ∗ ptx = generatePTX ( l l , s i z e ) ;
4 /∗ Criando um c o n t e x t o . ∗/
5 cuCtxCreate (&cudaContext , 0 , cudaDevice ) ;
6 /∗ Carregando o modulo . ∗/
7 cuModuleLoadDataEx(&cudaModule , ptx , 0 , 0 , 0) ;
8 /∗ Recuperando a funcao k e r n e l . ∗/
9 cuModuleGetFunction (& k e r n e l F u n c t i o n , cudaModule , " sum_kernel " ) ;
10 /∗ T r a n s f e r i n d o os dados para a memoria do d i s p o s i t i v o . ∗/
11 cuMemcpyHtoD ( devBufferA , &hostA [ 0 ] , s i z e o f ( f l o a t ) ∗N) ;
12 cuMemcpyHtoD ( devBufferB , &hostB [ 0 ] , s i z e o f ( f l o a t ) ∗N) ;
13 /∗ D e f i n i c a o das dimensoes do a r r a n j o de t h r e a d s . ∗/
14 c a l c u l a t e D i m e n s i o n s (& blockSizeX , &blockSizeY , &blockSizeZ , &g r i d S i z e X , &
g r i d S i z e Y , &g r i d S i z e Z ) ;
15 /∗ Parametros da funcao k e r n e l . ∗/
16 v o i d ∗ kernelParams [ ] = { &devBufferA , &devBufferB , &devBufferC } ;
17 /∗ Lancando a execucao do k e r n e l . ∗/
18 cuLaunchKernel ( k e r n e l F u n c t i o n , g r i d S i z e X , g r i d S i z e Y , g r i d S i z e Z , blockSizeX
, blockSizeY , blockSizeZ , 0 , NULL , kernelParams , NULL) ;
19 /∗ Recuperando o r e s u l t a d o . ∗/
20 cuMemcpyDtoH(&hostC [ 0 ] , devBufferC , s i z e o f ( f l o a t ) ∗N) ;
21 r e t u r n 0 ;
22 }
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 45 / 55
46. Sequência de Passos para os Próximos Exemplos I
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 46 / 55
47. Exemplo: vectorAdd (Soma de Vetores)
1 f l o a t h_a [N ] ;
2 f l o a t h_b [N ] ;
3 f l o a t h_c [N ] ;
4
5 i n t main ( ) {
6 i n t i ;
7 /∗ I n i c i a l i z a c a o dos v e t o r e s . ∗/
8 i n i t _ a r r a y ( ) ;
9
10 /∗ C a l c u l o . ∗/
11 f o r ( i = 0 ; i < N; i ++) {
12 h_c [ i ] = h_a [ i ] + h_b [ i ] ;
13 }
14
15 /∗ R e s u l t a d o s . ∗/
16 p r i n t _ a r r a y ( ) ;
17 c h e c k _ r e s u l t ( ) ;
18
19 r e t u r n 0 ;
20 }
Código em C.
Transformada em LLVM-IR. (Fase 1)
SCoP detectado pelo PoLLy (Fases 2, 3 e 4).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 47 / 55
48. Exemplo: vectorAdd (Soma de Vetores)
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 47 / 55
50. Código para o vectoradd-kernel
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 49 / 55
51. Código PTX para o vectoradd-kernel
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 50 / 55
52. Exemplo: sincos (Cálculo de Seno e Cosseno)
1 s u b r o u t i n e s i n c o s _ f u n c t i o n ( nx , ny ,
nz , x , y , xy )
2
3 i m p l i c i t none
4
5 i n t e g e r , i n t e n t ( i n o u t ) : : nx , ny ,
nz
6 r e a l , i n t e n t ( i n ) : : x ( nx , ny , nz ) ,
y ( nx , ny , nz )
7 r e a l , i n t e n t ( i n o u t ) : : xy ( nx , ny ,
nz )
8
9 i n t e g e r : : i , j , k
10
11 do k = 1 , nz
12 do j = 1 , ny
13 do i = 1 , nx
14 xy ( i , j , k ) = s i n ( x ( i , j , k ) )
+ cos ( y ( i , j , k ) )
15 enddo
16 enddo
17 enddo
18
19 end s u b r o u t i n e s i n c o s _ f u n c t i o n
Rotina em Fortran + Código Principal em C.
Transformada em LLVM-IR. (Fase 1)
SCoP detectado pelo PoLLy (Fases 2, 3 e 4).
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 51 / 55
53. Exemplo: sincos (Cálculo de Seno e Cosseno)
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 51 / 55
55. Código para o sincos-kernel
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 53 / 55
56. Referências e Links
D. F. Bacon, S. L. Graham, O. J. Sharp, Oliver, and J. Sharp,
“Compiler Transformations for High-Performance Computing,” ACM
Comput. Surv., vol. 26, no. 4, pp. 345–420, Nov. 1994.
M. Benabderrahmane, L.-N. Pouchet, A. Cohen, and C. Bastoul, “The
Polyhedral Model is More Widely Applicable Than You Think,” in
Proceedings of the 19th Joint European Conference on Theory and
Practice of Software, International Conference on Compiler
Construction, 2010, pp. 283–303.
LLVM: http://llvm.org
PoLLy: htpp://polly.llvm.org
NVPTX: http://llvm.org/docs/NVPTXUsage.html
Gonçalves, Goldman Paralelização Automática 17 de abril de 2015 54 / 55