Loop de versionamento com GCC
-
19-09-2019 - |
Pergunta
Eu estou trabalhando em auto vetorização com GCC. Não estou em posição de intrínsecos uso ou atributos devido à exigência do cliente. (Eu não posso começar a entrada do usuário para vetorização de suporte)
Se a informação de alinhamento da matriz que pode ser vetorizado é desconhecida, GCC invoca um passe para 'loop de controle de versão'. Loop de controle de versão será executada quando vetorização loop é feito em árvores. Quando um circuito é identificado como sendo vectorizable, e a restrição no alinhamento de dados ou dependência de dados é impedi-la, (porque não pode ser determinado em tempo de compilação), em seguida, duas versões do ciclo irá ser gerado. Estas são as versões vectorizada e não-Vectorized do loop juntamente com controlos de tempo de execução para o alinhamento ou dependência a versão de controlo que é executado.
A minha pergunta é como temos que fazer valer o alinhamento? Se eu ter encontrado um loop que é vectorizable, não deve gerar duas versões do circuito por causa da falta de informação sobre o alinhamento.
Por exemplo. Considere o código abaixo
short a[15]; short b[15]; short c[15];
int i;
void foo()
{
for (i=0; i<15; i++)
{
a[i] = b[i] ;
}
}
despejo Tree (opções:--fdump-árvore otimizado -ftree-vectorize)
<SNIP>
vector short int * vect_pa.49;
vector short int * vect_pb.42;
vector short int * vect_pa.35;
vector short int * vect_pb.30;
bb 2>:
vect_pb.30 = (vector short int *) &b;
vect_pa.35 = (vector short int *) &a;
if (((signed char) vect_pa.35 | (signed char) vect_pb.30) & 3 == 0) ;; <== (A)
goto <bb 3>;
else
goto <bb 4>;
bb 3>:
</SNIP>
No 'bb 3' versão do código vetorizado é gerado. No 'bb 4' código sem vetorização é gerado. Estas são feitas por verificar o alinhamento (declaração 'A'). Agora sem usar intrínsecos e outros atributos, como devo começar apenas o código vectorized (sem esta verificação de alinhamento de tempo de execução.)
Solução
Se os dados em questão está sendo alocado estaticamente, então você pode usar o atributo __align__
que os apoios do CCG para especificar que ele deve ser alinhado com o limite necessário. Se você está alocando dinamicamente essas matrizes, você pode over-alocar pelo valor de alinhamento, e depois bater o ponteiro retornado até o alinhamento que você precisa.
Você também pode usar a função posix_memalign()
se você estiver em um sistema que o suporta. Finalmente, nota de memória que malloc()
sempre alocar alinhado com o tamanho do maior tipo built-in, geralmente 8 bytes para um duplo. Se você não precisa de mais do que isso, então malloc
deve bastar.
Editar : Se você modificar o código de alocação para forçar que o check para ser verdade (ou seja overallocate, como sugerido acima), o compilador deve obrigar por não conditionalizing o código de loop. Se você precisava de alinhamento a um limite de 8 bytes, como parece, que seria algo como a = (a + 7) & ~3;
.
Outras dicas
eu recebo apenas uma versão do loop, utilizando o seu código exato com estas opções: gcc -march=core2 -c -O2 -fdump-tree-optimized -ftree-vectorize vec.c
A minha versão do GCC é gcc version 4.4.1 (Ubuntu 4.4.1-4ubuntu8)
.
GCC está fazendo algo inteligente aqui. Isso força o a
matrizes e b
para ser de 16 bytes alinhados. Ele não faz isso para c
, presumivelmente porque c
nunca é usado em um loop vectorizable.