Principais conceitos e técnicas
em vetorização
Intel Software Conference – Maio, 2014
Igor Freitas
igor.freitas@intel.com
Agenda
2
 Introdução
 Auto-vetorização
 Diretivas - #pragma
 Vetorização com Intel® Cilk™ Plus
 Intrinsics
 Conclusões
3
Introdução
4
for (i=0;i<=MAX;i++)
c[i]=a[i]+b[i];
+
c[i+7] c[i+6] c[i+5] c[i+4] c[i+3] c[i+2] c[i+1] c[i]
b[i+7] b[i+6] b[i+5] b[i+4] b[i+3] b[i+2] b[i+1] b[i]
a[i+7] a[i+6] a[i+5] a[i+4] a[i+3] a[i+2] a[i+1] a[i]
Vector
- Uma instrução
- Oito operações
+
C
B
A
Scalar
- Uma instrução
- Uma operação
• O que é e ?
• Capacidade de realizar uma operação
matemática em dois ou mais elementos
ao mesmo tempo.
• Por que Vetorizar ?
• Ganho substancial em performance !
Introdução
5
Introdução
Código C/C++
ou Fortran
Thread 0 /
Core 0
Thread 1/
Core1
Thread 2
/ Core 2
Thread 12
/ Core12
...
Thread
0/Core0
Thread
1/Core1
Thread
2/Core2
Thread 244
/Core61
.
.
.
128 Bits 256 Bits
Vector Processor Unit por Core Vector Processor Unit por Core
Paralelismo (Multithreading)
Vetorização
512 Bits
Introdução
6
MMX™ instructions
(1997)
Intel® Streaming SIMD Extensions (Intel® SSE in 1999 to Intel® SSE4.2 in 2008)
Intel® Advanced Vector Extensions (Intel® AVX in 2011 and Intel® AVX2 in 2013)
Intel® Many Integrated Core Architecture (Intel® MIC Architecture in 2012)
Intel® Pentium® processor (1993)
7
X4
Y4
X4opY4
X3
Y3
X3opY3
X2
Y2
X2opY2
X1
Y1
X1opY1
064
X4
Y4
X4opY4
X3
Y3
X3opY3
X2
Y2
X2opY2
X1
Y1
X1opY1
0128
MMX™
Vector size: 64bit
Data types: 8, 16 and 32 bit integers
VL: 2,4,8
For sample on the left: Xi, Yi 16 bit
integers
Intel® SSE
Vector size: 128bit
Data types:
8,16,32,64 bit integers
32 and 64bit floats
VL: 2,4,8,16
Sample: Xi, Yi bit 32 int / float
Introdução
8
Intel® AVX
Vector size: 256bit
Data types: 32 and 64 bit floats
VL: 4, 8, 16
Sample: Xi, Yi 32 bit int or float
Intel® MIC
Vector size: 512bit
Data types:
32 and 64 bit integers
32 and 64bit floats
(some support for
16 bits floats)
VL: 8,16
Sample: 32 bit float
X4
Y4
X4opY4
X3
Y3
X3opY3
X2
Y2
X2opY2
X1
Y1
X1opY1
0127
X8
Y8
X8opY8
X7
Y7
X7opY7
X6
Y6
X6opY6
X5
Y5
X5opY5
128255
X4
Y4
…
X3
Y3
…
X2
Y2
…
X1
Y1
X1opY1
0
X8
Y8
X7
Y7
X6
Y6
...
X5
Y5
…
255
…
…
…
…
…
…
…
…
…
X9
Y9
X16
Y16
X16opY16
…
…
…
...
…
…
…
…
…
511
X9opY9 X8opY8 …
Introdução
Cinco possíveis abordagens:
 Bibliotecas matemáticas
– Ex.: Intel® Math Kernel Library (MKL)
 Auto-vetorização
– Trabalho a cargo do Compilador
 Array Notation – Cilk Plus
– Notação vetorial na linguagem de programação explicitando a vetorização
 Semi auto-vetorização
– SIMD
– IVDEP
– VECTOR E NOVECTOR
 C/C++ Vector classes
– Intrinsics
9
Introdução
10
Facilidade de Uso
Ajuste Fino
Vectors
Intel® Math Kernel Library
Array Notation: Intel® Cilk™ Plus
Auto vectorization
Semi-auto vectorization:
#pragma (vector, ivdep, simd)
C/C++ Vector Classes
(F32vec16, F64vec8)
Introdução
Devemos avaliar três fatores:
 Necessidade de performance
 Disponibilidade de recursos para
otimizar o código
 Portabilidade do código
11
Auto-vetorização
1º Passo: Parâmetros para o Compilador
 vec-report[n] : relatório do que foi e do que pode ser vetorizado . “n”
determina o nível de detalhes
 guide : GAP – Guided Auto-parallelization . Sugestões de como vetorizar
 O[n] : Nível de otimização O2 (default) já inclui auto-vetorização
 x[code] : Otimiza as instruções de acordo com a arquitetura do processador.
 -xAVX , -xCORE-AVX2, -xSSE4.2, -xSSE4.1, -xSSSE3, -xSSE3
 xHost: Compilador checa o processador e aplica a melhor instrução suportada
 msse2 (default): (Windows: /arch:SSE2)
12
Auto-vetorização
 m<extension>: checagem para processadores “não Intel®”
 Não aplica otimizações específicas para processadores Intel®
 Compatibilidade para processadores Intel® e “não Intel®”
 Instruções AVX suportadas em processadores “não Intel®”
 ax<extension>
 Compilador gera dois caminhos: “genérico” e “otimizado”
 Ex: “icc -axCORE-AVX2 –axSSE4.2 codigo.c “ em um processador que suporta somente SSE
4.2, o compilador ignora a instrução CORE-AVX2
13
Auto-vetorização
Ajudando o compilador a vetorizar
 Evitar “loop unrolling” manual pois:
 Atrela otimização a arquitetura de hardware (Vector Processor Unit)
 Prejudica a leitura do código
 Parâmetro ao compilador: -unroll[=n]
14
Auto-vetorização
Unrolling Loop
1. double acc1 = 0, accu2 = 0, acc3 = 0, acc4 =0;
2. for (i=0; i<NUM; i+=4) {
3. acc1 = src1[i+0] * src2 + acc1;
4. acc2 = src1[i+1] * src2 + acc1;
5. acc3 = src1[i+2] * src2 + acc1;
6. acc4 = src1[i+3] * src2 + acc1;
7. }
8. accu = acc1 + acc2 + acc3 + acc4;
Forma simplificada
double acc = 0;
#pragma unroll(4) // #pragma nounroll
for (i=0; i<NUM; i++) {
accu = src1[i]*src2 + accu;
}
Requisitos para um loop ser vetorizado
 Em loops encadeados, o loop mais interno será vetorizado
 Deve conter apenas blocos básicos, ex.: uma única linha de código sem condições (if
statements) ou saltos (go to)
 Quantidade de iterações do loop deve ser conhecida antes de sua execução, mesmo que
em tempo de execução
 Sem dependências entre os elementos a serem calculados
 Memória não alinhada (contígua)
 GAP – Guided Autoparallelization (Intel® Compiler “-guide” ) pode ajudar
15
Loop Não Vetorizável – Dependência sobre a[i-1]
for (i=1; i<MAX; i++) {
d[i] = e[i] – a[i-1];
a[i] = b[i] + c[i];
}
Auto-vetorização
16
Diretivas - #pragma
Tipos de diretivas:
 SIMD
 Permissão total ao compilador vetorizar
 Responsabilidade da vetorização é do programador
 Mais agressivo que IVDEP ou VECTOR ALWAYS
 IVDEP
 Remove dependências entre ponteiros nos vetores
 VECTOR e NOVECTOR
 “Dicas” que mudam a heurística default do compilador
 Habilita/desabilita vetorização
 Alinhamento de dados, vetorização de loops sobressalentes
17
Diretivas - #pragma
Diretivas SIMD: forçando a vetorização
#pragma simd [clause[ [,] clause] ... ]
Guia o compilador para casos onde a auto-vetorização não é possível
Atributos padrão:
VECTORLENGTH N : tamanho do vetor (2, 4, 8 ou 16)
VECTORLENGTHFOR (data-type) : tamanho_vetor/sizeof(type)
PRIVATE (VAR1[, VAR2]...) : variável privada para cada iteração do loop
FIRSTPRIVATE (VAR1[, VAR2]...) : broadcast do valor inicial a todas as outras instâncias para cada iteração
LASTPRIVATE (VAR1[, VAR2]...) : broadcast do valor original as outras instâncias no final do loop
LINEAR (var1:step [, var2:step2]...) : incrementa número de steps para cada variável em um loop, unit-stride vector
REDUCTION (oper:var1[, var2]...) : Aplica operação de redução (+, *, -, AND, OR, EQV, NEQV) nas variáveis indicadas
ASSERT : Direciona o compilador a produzir um erro ou um warning quando a vetorização falha
18
Diretivas - #pragma
Diretivas SIMD: forçando a vetorização
19
Diretivas - #pragma
Diretivas SIMD
Adição de vetores – C/C++
1.__declspec(align(16)) float a[MAX], b[MAX], c[MAX];
2.#pragma simd
3.for (i=0; i<MAX; i++)
4. c[i] = a[i]+b[i];
Diretivas VECTOR
#pragma vector aligned | unaligned : comunica ao compilador que os dados estão
alinhados
#pragma vector nontemporal | temporal ou “-opt-streaming-store always” : uso
ótimo do cache em casos de write-only; os dados não precisam ser armazenados na
cache, e sim diretamente na memória. Usar “#pragma vector aligned” antes.
#pragma novector : Instrui o compilador a não vetorizar. Útil em loops com muitas
condições (ifs)
#pragma vector always : força vetorização automática independente da heurística do
compilador
20
Diretivas - #pragma
Diretivas VECTOR
Streaming stores (Xeon and Xeon Phi)
 Escritas na memória que não necessitam de prévias operações de
leitura.
 Evita prefetch da memória para a cache
 Nontemporal buffer
 Otimiza bandwith
 -opt-streaming-stores [always | never | auto ]
 #pragma vector nontemporal[(var1[, var2, ...])]
21
Diretivas - #pragma
22
Diretivas IVDEP
#pragma ivdep: Ignora dependências de variáveis
“-restrict” (necessário parâmetro ao compilador “-restrict”) : similar a
“ivdep” , informa que determinada variável não possui
restrições/dependências
Diretivas - #pragma
//-restrict necessario ao compilador neste caso
void vectorize (float* restrict a, float* restrict b, float* c, float* d, int n)
{
int i;
for (i =0; i<n; i++) {
a[i] = c[i] * d[i];
b[i] = a[i] + c[i] - d[i];
}
ou
#pragma ivdep
void vectorize(float* a, float* b, float* c, float* d, int n) { … }
#pragma loop count : Informa ao compilador o número
de loops . Útil para melhores predições de vetorização
__assume_aligned : elimita checagem se os dados estão
alinhados, porém e´specífico para cada vetor
23
Diretivas - #pragma
void myfunc( double p[] ) {
__assume_aligned(p, 64);
for (int i=0; i<n; i++){
p[i]++;
}
int i;
int mysum(int start, int end, int a)
{
int iret=0;
#pragma loop_count min(3), max(10), avg(5)
for (i=start;i<=end;i++)
iret += a;
return iret;
}
__attribute__((aligned(64)) ou __mm_malloc() / __mm__free() :
alocação estática e dinâmica de dados alinhados
-opt-assume-safe-padding : quando este parâmetro é especificado,
o compilador assume que as váriaveis (estáticas ou dinâmicas) foram
preenchidas com elementos adicionais para ficarem alinhadas de
acordo com o tamanho do registrador vetorial. Ex:
24
Diretivas - #pragma
float data[n] __attribute__((aligned(64))); (Linux)
__declspec(align(64)) float A[n]; (Windows)
float *A = (float*)_mm_malloc(n*sizeof(float), 16);
// ...
_mm_free(A);
ptr = (float *)malloc(sizeof(float) * n); //sem “padding”
ptr = (float *)malloc(sizeof(float) * n + 64); //espaço adicional para
“padding”
25
Vetorização com
Intel® Cilk™ Plus
 Array notation
 Elemental functions
26
Vetorização com Intel® Cilk™ Plus
Vetorização com Intel® Cilk™ Plus
Array notations
 Extensões C++ Intel® Cilk Plus™ para operações com vetores
 Notação vetorial em C/C++
27
28
A[:] += B[:]; // todo o vetor é computado
A[0:16] += B[32:16]; // A(0 até 15) + B(32 até 47)
A[0:16:2] += B[32:16:4] // A(0, 2, 4, ...30) + B(32, 36, 38, ... 92)
Compatibilidade com compiladores não-Intel
#ifdef __INTEL_COMPILER
A[:] += B[:];
#else
for (int i=0; i<16; i++)
A[i] += B[i];
#endif
Vetorização com Intel® Cilk™ Plus
Array notations
29
Adição de vetores – C/C++ - Dados alinhados
1.__declspec(align(16)) float a[MAX], b[MAX], c[MAX];
2.c[i:MAX] = a[i:MAX]+b[i:MAX];
Vetorização com Intel® Cilk Plus
Array notations
30
 Possibilita chamar versão vetorizada da função escalar
 Excelente em casos onde as funções estão implementadas
em biblioteca de terceiros
Vetorização com Intel® Cilk Plus
Elemental functions
31
Lib X
float my_simple_add(float x1, float x2){
return x1 + x2;
}
Elemental Function
__attribute__(vector) float my_simple_add(float x1, float x2);
// ...em outro arquivo de código
#pragma simd
for (int i=0; i < N, ++i) {
output[i] = my_simple_add(inputa[i], inputb[i]);
}
Ou
my_simple_add(inputA[:], inputB[:]);
Vetorização com Intel® Cilk Plus
Elemental functions
32
Intrinsics
O que é Intel® C++ Intrinsic ?
 Provê acesso a ISA (Instruction Set Architecture) através de código C/C++ ao invés de
código Assembly
 Ganho de performance próximo a códigos Assembly com a facilidade de C/C++
 Vetorização – Extensões SIMD (Simple Instructions Multiple Data)
33
Intrinsics
34
MIC Intrinsics
SSE Intrinsics
Intrinsics SSE
for (int i=0; i<n; i+4)
{
__m128 vecA = _mm_load_ps(A+i);
__m128 vecB = _mm_load_ps(B+i);
vecA = _mm_add_ps(vecA, vecB);
_mm_store_ps(A+i, vecA);
}
vecA[0] vecA[1] vecA[2] vecA[3]
SSE Register – 128 bits
4 packed single precision
vecB[0] vecB[1] vecB[2] vecB[3]
DRAM
A* | B* | ...
add
vecA[0] vecA[1] vecA[2] vecA[3]
Intrinsics AVX-512
for (int i=0; i<n; i+4)
{
__m512 vecA = _mm_load_ps(A+i);
__m512 vecB = _mm_load_ps(B+i);
vecA = _mm512_add_ps(vecA, vecB);
_mm512_store_ps(A+i, vecA);
}
Intrinsics
35
Conclusões
Conclusões
36
Vetorização
Permite obter mais performance
Uso de padrões abertos
Mesma técnica de programação para
CPUs e Co-processadores
Vários maneiras de vetorizar:
Facilidade ou “Ajuste fino”
©2014, Intel Corporation. All rights reserved. Intel, the Intel logo, Intel Inside, Intel Xeon, and Intel Xeon Phi are trademarks of Intel Corporation in the U.S. and/or other countries. *Other names and brands may be claimed as the property of others.
37

Principais conceitos e técnicas em vetorização

  • 1.
    Principais conceitos etécnicas em vetorização Intel Software Conference – Maio, 2014 Igor Freitas igor.freitas@intel.com
  • 2.
    Agenda 2  Introdução  Auto-vetorização Diretivas - #pragma  Vetorização com Intel® Cilk™ Plus  Intrinsics  Conclusões
  • 3.
  • 4.
    4 for (i=0;i<=MAX;i++) c[i]=a[i]+b[i]; + c[i+7] c[i+6]c[i+5] c[i+4] c[i+3] c[i+2] c[i+1] c[i] b[i+7] b[i+6] b[i+5] b[i+4] b[i+3] b[i+2] b[i+1] b[i] a[i+7] a[i+6] a[i+5] a[i+4] a[i+3] a[i+2] a[i+1] a[i] Vector - Uma instrução - Oito operações + C B A Scalar - Uma instrução - Uma operação • O que é e ? • Capacidade de realizar uma operação matemática em dois ou mais elementos ao mesmo tempo. • Por que Vetorizar ? • Ganho substancial em performance ! Introdução
  • 5.
    5 Introdução Código C/C++ ou Fortran Thread0 / Core 0 Thread 1/ Core1 Thread 2 / Core 2 Thread 12 / Core12 ... Thread 0/Core0 Thread 1/Core1 Thread 2/Core2 Thread 244 /Core61 . . . 128 Bits 256 Bits Vector Processor Unit por Core Vector Processor Unit por Core Paralelismo (Multithreading) Vetorização 512 Bits
  • 6.
    Introdução 6 MMX™ instructions (1997) Intel® StreamingSIMD Extensions (Intel® SSE in 1999 to Intel® SSE4.2 in 2008) Intel® Advanced Vector Extensions (Intel® AVX in 2011 and Intel® AVX2 in 2013) Intel® Many Integrated Core Architecture (Intel® MIC Architecture in 2012) Intel® Pentium® processor (1993)
  • 7.
    7 X4 Y4 X4opY4 X3 Y3 X3opY3 X2 Y2 X2opY2 X1 Y1 X1opY1 064 X4 Y4 X4opY4 X3 Y3 X3opY3 X2 Y2 X2opY2 X1 Y1 X1opY1 0128 MMX™ Vector size: 64bit Datatypes: 8, 16 and 32 bit integers VL: 2,4,8 For sample on the left: Xi, Yi 16 bit integers Intel® SSE Vector size: 128bit Data types: 8,16,32,64 bit integers 32 and 64bit floats VL: 2,4,8,16 Sample: Xi, Yi bit 32 int / float Introdução
  • 8.
    8 Intel® AVX Vector size:256bit Data types: 32 and 64 bit floats VL: 4, 8, 16 Sample: Xi, Yi 32 bit int or float Intel® MIC Vector size: 512bit Data types: 32 and 64 bit integers 32 and 64bit floats (some support for 16 bits floats) VL: 8,16 Sample: 32 bit float X4 Y4 X4opY4 X3 Y3 X3opY3 X2 Y2 X2opY2 X1 Y1 X1opY1 0127 X8 Y8 X8opY8 X7 Y7 X7opY7 X6 Y6 X6opY6 X5 Y5 X5opY5 128255 X4 Y4 … X3 Y3 … X2 Y2 … X1 Y1 X1opY1 0 X8 Y8 X7 Y7 X6 Y6 ... X5 Y5 … 255 … … … … … … … … … X9 Y9 X16 Y16 X16opY16 … … … ... … … … … … 511 X9opY9 X8opY8 … Introdução
  • 9.
    Cinco possíveis abordagens: Bibliotecas matemáticas – Ex.: Intel® Math Kernel Library (MKL)  Auto-vetorização – Trabalho a cargo do Compilador  Array Notation – Cilk Plus – Notação vetorial na linguagem de programação explicitando a vetorização  Semi auto-vetorização – SIMD – IVDEP – VECTOR E NOVECTOR  C/C++ Vector classes – Intrinsics 9 Introdução
  • 10.
    10 Facilidade de Uso AjusteFino Vectors Intel® Math Kernel Library Array Notation: Intel® Cilk™ Plus Auto vectorization Semi-auto vectorization: #pragma (vector, ivdep, simd) C/C++ Vector Classes (F32vec16, F64vec8) Introdução Devemos avaliar três fatores:  Necessidade de performance  Disponibilidade de recursos para otimizar o código  Portabilidade do código
  • 11.
  • 12.
    1º Passo: Parâmetrospara o Compilador  vec-report[n] : relatório do que foi e do que pode ser vetorizado . “n” determina o nível de detalhes  guide : GAP – Guided Auto-parallelization . Sugestões de como vetorizar  O[n] : Nível de otimização O2 (default) já inclui auto-vetorização  x[code] : Otimiza as instruções de acordo com a arquitetura do processador.  -xAVX , -xCORE-AVX2, -xSSE4.2, -xSSE4.1, -xSSSE3, -xSSE3  xHost: Compilador checa o processador e aplica a melhor instrução suportada  msse2 (default): (Windows: /arch:SSE2) 12 Auto-vetorização
  • 13.
     m<extension>: checagempara processadores “não Intel®”  Não aplica otimizações específicas para processadores Intel®  Compatibilidade para processadores Intel® e “não Intel®”  Instruções AVX suportadas em processadores “não Intel®”  ax<extension>  Compilador gera dois caminhos: “genérico” e “otimizado”  Ex: “icc -axCORE-AVX2 –axSSE4.2 codigo.c “ em um processador que suporta somente SSE 4.2, o compilador ignora a instrução CORE-AVX2 13 Auto-vetorização
  • 14.
    Ajudando o compiladora vetorizar  Evitar “loop unrolling” manual pois:  Atrela otimização a arquitetura de hardware (Vector Processor Unit)  Prejudica a leitura do código  Parâmetro ao compilador: -unroll[=n] 14 Auto-vetorização Unrolling Loop 1. double acc1 = 0, accu2 = 0, acc3 = 0, acc4 =0; 2. for (i=0; i<NUM; i+=4) { 3. acc1 = src1[i+0] * src2 + acc1; 4. acc2 = src1[i+1] * src2 + acc1; 5. acc3 = src1[i+2] * src2 + acc1; 6. acc4 = src1[i+3] * src2 + acc1; 7. } 8. accu = acc1 + acc2 + acc3 + acc4; Forma simplificada double acc = 0; #pragma unroll(4) // #pragma nounroll for (i=0; i<NUM; i++) { accu = src1[i]*src2 + accu; }
  • 15.
    Requisitos para umloop ser vetorizado  Em loops encadeados, o loop mais interno será vetorizado  Deve conter apenas blocos básicos, ex.: uma única linha de código sem condições (if statements) ou saltos (go to)  Quantidade de iterações do loop deve ser conhecida antes de sua execução, mesmo que em tempo de execução  Sem dependências entre os elementos a serem calculados  Memória não alinhada (contígua)  GAP – Guided Autoparallelization (Intel® Compiler “-guide” ) pode ajudar 15 Loop Não Vetorizável – Dependência sobre a[i-1] for (i=1; i<MAX; i++) { d[i] = e[i] – a[i-1]; a[i] = b[i] + c[i]; } Auto-vetorização
  • 16.
  • 17.
    Tipos de diretivas: SIMD  Permissão total ao compilador vetorizar  Responsabilidade da vetorização é do programador  Mais agressivo que IVDEP ou VECTOR ALWAYS  IVDEP  Remove dependências entre ponteiros nos vetores  VECTOR e NOVECTOR  “Dicas” que mudam a heurística default do compilador  Habilita/desabilita vetorização  Alinhamento de dados, vetorização de loops sobressalentes 17 Diretivas - #pragma
  • 18.
    Diretivas SIMD: forçandoa vetorização #pragma simd [clause[ [,] clause] ... ] Guia o compilador para casos onde a auto-vetorização não é possível Atributos padrão: VECTORLENGTH N : tamanho do vetor (2, 4, 8 ou 16) VECTORLENGTHFOR (data-type) : tamanho_vetor/sizeof(type) PRIVATE (VAR1[, VAR2]...) : variável privada para cada iteração do loop FIRSTPRIVATE (VAR1[, VAR2]...) : broadcast do valor inicial a todas as outras instâncias para cada iteração LASTPRIVATE (VAR1[, VAR2]...) : broadcast do valor original as outras instâncias no final do loop LINEAR (var1:step [, var2:step2]...) : incrementa número de steps para cada variável em um loop, unit-stride vector REDUCTION (oper:var1[, var2]...) : Aplica operação de redução (+, *, -, AND, OR, EQV, NEQV) nas variáveis indicadas ASSERT : Direciona o compilador a produzir um erro ou um warning quando a vetorização falha 18 Diretivas - #pragma
  • 19.
    Diretivas SIMD: forçandoa vetorização 19 Diretivas - #pragma Diretivas SIMD Adição de vetores – C/C++ 1.__declspec(align(16)) float a[MAX], b[MAX], c[MAX]; 2.#pragma simd 3.for (i=0; i<MAX; i++) 4. c[i] = a[i]+b[i];
  • 20.
    Diretivas VECTOR #pragma vectoraligned | unaligned : comunica ao compilador que os dados estão alinhados #pragma vector nontemporal | temporal ou “-opt-streaming-store always” : uso ótimo do cache em casos de write-only; os dados não precisam ser armazenados na cache, e sim diretamente na memória. Usar “#pragma vector aligned” antes. #pragma novector : Instrui o compilador a não vetorizar. Útil em loops com muitas condições (ifs) #pragma vector always : força vetorização automática independente da heurística do compilador 20 Diretivas - #pragma
  • 21.
    Diretivas VECTOR Streaming stores(Xeon and Xeon Phi)  Escritas na memória que não necessitam de prévias operações de leitura.  Evita prefetch da memória para a cache  Nontemporal buffer  Otimiza bandwith  -opt-streaming-stores [always | never | auto ]  #pragma vector nontemporal[(var1[, var2, ...])] 21 Diretivas - #pragma
  • 22.
    22 Diretivas IVDEP #pragma ivdep:Ignora dependências de variáveis “-restrict” (necessário parâmetro ao compilador “-restrict”) : similar a “ivdep” , informa que determinada variável não possui restrições/dependências Diretivas - #pragma //-restrict necessario ao compilador neste caso void vectorize (float* restrict a, float* restrict b, float* c, float* d, int n) { int i; for (i =0; i<n; i++) { a[i] = c[i] * d[i]; b[i] = a[i] + c[i] - d[i]; } ou #pragma ivdep void vectorize(float* a, float* b, float* c, float* d, int n) { … }
  • 23.
    #pragma loop count: Informa ao compilador o número de loops . Útil para melhores predições de vetorização __assume_aligned : elimita checagem se os dados estão alinhados, porém e´specífico para cada vetor 23 Diretivas - #pragma void myfunc( double p[] ) { __assume_aligned(p, 64); for (int i=0; i<n; i++){ p[i]++; } int i; int mysum(int start, int end, int a) { int iret=0; #pragma loop_count min(3), max(10), avg(5) for (i=start;i<=end;i++) iret += a; return iret; }
  • 24.
    __attribute__((aligned(64)) ou __mm_malloc()/ __mm__free() : alocação estática e dinâmica de dados alinhados -opt-assume-safe-padding : quando este parâmetro é especificado, o compilador assume que as váriaveis (estáticas ou dinâmicas) foram preenchidas com elementos adicionais para ficarem alinhadas de acordo com o tamanho do registrador vetorial. Ex: 24 Diretivas - #pragma float data[n] __attribute__((aligned(64))); (Linux) __declspec(align(64)) float A[n]; (Windows) float *A = (float*)_mm_malloc(n*sizeof(float), 16); // ... _mm_free(A); ptr = (float *)malloc(sizeof(float) * n); //sem “padding” ptr = (float *)malloc(sizeof(float) * n + 64); //espaço adicional para “padding”
  • 25.
  • 26.
     Array notation Elemental functions 26 Vetorização com Intel® Cilk™ Plus
  • 27.
    Vetorização com Intel®Cilk™ Plus Array notations  Extensões C++ Intel® Cilk Plus™ para operações com vetores  Notação vetorial em C/C++ 27
  • 28.
    28 A[:] += B[:];// todo o vetor é computado A[0:16] += B[32:16]; // A(0 até 15) + B(32 até 47) A[0:16:2] += B[32:16:4] // A(0, 2, 4, ...30) + B(32, 36, 38, ... 92) Compatibilidade com compiladores não-Intel #ifdef __INTEL_COMPILER A[:] += B[:]; #else for (int i=0; i<16; i++) A[i] += B[i]; #endif Vetorização com Intel® Cilk™ Plus Array notations
  • 29.
    29 Adição de vetores– C/C++ - Dados alinhados 1.__declspec(align(16)) float a[MAX], b[MAX], c[MAX]; 2.c[i:MAX] = a[i:MAX]+b[i:MAX]; Vetorização com Intel® Cilk Plus Array notations
  • 30.
    30  Possibilita chamarversão vetorizada da função escalar  Excelente em casos onde as funções estão implementadas em biblioteca de terceiros Vetorização com Intel® Cilk Plus Elemental functions
  • 31.
    31 Lib X float my_simple_add(floatx1, float x2){ return x1 + x2; } Elemental Function __attribute__(vector) float my_simple_add(float x1, float x2); // ...em outro arquivo de código #pragma simd for (int i=0; i < N, ++i) { output[i] = my_simple_add(inputa[i], inputb[i]); } Ou my_simple_add(inputA[:], inputB[:]); Vetorização com Intel® Cilk Plus Elemental functions
  • 32.
  • 33.
    O que éIntel® C++ Intrinsic ?  Provê acesso a ISA (Instruction Set Architecture) através de código C/C++ ao invés de código Assembly  Ganho de performance próximo a códigos Assembly com a facilidade de C/C++  Vetorização – Extensões SIMD (Simple Instructions Multiple Data) 33 Intrinsics
  • 34.
    34 MIC Intrinsics SSE Intrinsics IntrinsicsSSE for (int i=0; i<n; i+4) { __m128 vecA = _mm_load_ps(A+i); __m128 vecB = _mm_load_ps(B+i); vecA = _mm_add_ps(vecA, vecB); _mm_store_ps(A+i, vecA); } vecA[0] vecA[1] vecA[2] vecA[3] SSE Register – 128 bits 4 packed single precision vecB[0] vecB[1] vecB[2] vecB[3] DRAM A* | B* | ... add vecA[0] vecA[1] vecA[2] vecA[3] Intrinsics AVX-512 for (int i=0; i<n; i+4) { __m512 vecA = _mm_load_ps(A+i); __m512 vecB = _mm_load_ps(B+i); vecA = _mm512_add_ps(vecA, vecB); _mm512_store_ps(A+i, vecA); } Intrinsics
  • 35.
  • 36.
    Conclusões 36 Vetorização Permite obter maisperformance Uso de padrões abertos Mesma técnica de programação para CPUs e Co-processadores Vários maneiras de vetorizar: Facilidade ou “Ajuste fino”
  • 37.
    ©2014, Intel Corporation.All rights reserved. Intel, the Intel logo, Intel Inside, Intel Xeon, and Intel Xeon Phi are trademarks of Intel Corporation in the U.S. and/or other countries. *Other names and brands may be claimed as the property of others. 37