Upload
intel-software-brasil
View
264
Download
1
Embed Size (px)
DESCRIPTION
Intel Software Conference – Maio, 2014 Igor Freitas [email protected]
Citation preview
Principais conceitos e técnicas em vetorização Intel Software Conference – Maio, 2014 Igor Freitas [email protected]
Agenda
2
Introdução
Auto-vetorização
Diretivas - #pragma
Vetorização com Intel® Cilk™ Plus
Intrinsics
Conclusões
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
0 64
X4
Y4
X4opY4
X3
Y3
X3opY3
X2
Y2
X2opY2
X1
Y1
X1opY1
0 128
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
0 127
X8
Y8
X8opY8
X7
Y7
X7opY7
X6
Y6
X6opY6
X5
Y5
X5opY5
128 255
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
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
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”
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
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
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