2014-11-11 29 views
7

Próbuję użyć wektoryzacji w moim kompilatorze (Microsoft Visual Studio 2013). Jednym z problemów, przed którymi stoję, jest to, że nie chce używać AVX2. Podczas badania tego problemu skonstruowałem następujący przykład, który oblicza sumę 16 liczb, z których każda jest 16-bitowa.Dlaczego funkcja automatycznego wektoryzacji MSVC nie korzysta z AVX2?

int16_t input1[16] = {0}; 
int16_t input2[16] = {0}; 
... // fill the arrays with some data 

// Calculate the sum using a loop 
int16_t output1[16] = {0}; 
for (int x = 0; x < 16; x++){ 
    output1[x] = input1[x] + input2[x]; 
} 

Kompilator vectorizes tego kodu, ale tylko do instrukcji SSE:

vmovdqu xmm1, xmmword ptr [rbp+rax] 
lea  rax, [rax+10h] 
vpaddw xmm1, xmm1, xmmword ptr [rbp+rax+10h] 
vmovdqu xmmword ptr [rbp+rax+30h], xmm1 
dec  rcx 
jne  main+0b0h 

upewnić się, że kompilator ma możliwość wygenerowania kodu AVX2 pisałem te same obliczenia, co następuje:

// Calculate the sum using one AVX2 instruction 
int16_t output2[16] = {0}; 
__m256i in1 = _mm256_loadu_si256((__m256i*)input1); 
__m256i in2 = _mm256_loadu_si256((__m256i*)input2); 
__m256i out2 = _mm256_add_epi16(in1, in2); 
_mm256_storeu_si256((__m256i*)output2, out2); 

Widzę, że dwie części kodu są równoważne (tj. output11 jest równa output2 po ich wykonaniu).

I wyprowadza instrukcji AVX2 do drugiej części kodu:

vmovdqu ymm1, ymmword ptr [input2] 
vpaddw ymm1, ymm1, ymmword ptr [rbp] 
vmovdqu ymmword ptr [output2], ymm1 

nie chcę przepisać mój kod do korzystania intrinsics jednak: po to napisany jako pętla jest znacznie bardziej naturalne, jest kompatybilny ze starymi procesorami (SSE) i ma inne zalety.

Jak mogę poprawić mój przykład, aby kompilator mógł wektoryzować w sposób AVX2?

+2

Zgaduję tylko tutaj, ale z tego, co widziałem o rozmowach na AVX w Visual Studio, implementacja wciąż wydaje się niedojrzała i wiadomo, że nie wykorzystuje wszystkich możliwych optymalizacji. Inną możliwością jest to, że optymalizator zdecydował, że najlepszą wydajnością jest niestosowanie instrukcji AVX2 we wszystkich okolicznościach, w których byłoby to możliwe. Na przykład zdarzają się sytuacje, w których instrukcja AVX może powodować brak pamięci podręcznej, co oznacza, że ​​faktycznie kończy się wolniej niż bardziej naiwne podejście. – sjdowling

+0

Pobierz CPU-z na przykład i sprawdź, czy twój procesor obsługuje AVX lub AVX2. Jeśli nie, zakładam, że właśnie dlatego Visual Studio blokuje konfigurację – NirMH

+0

@NirMH Myślę, że powinno być jasne z mojego kodu, że obsługuje AVX2. Mam na myśli, że druga część mojego kodu obejmuje jedną taką instrukcję. I wspomniałem, że daje on poprawny wynik (czek nie jest w kodzie, ale naprawdę sprawdziłem). – anatolyg

Odpowiedz

0

Program Visual Studio z łatwością tworzy kod AVX2 podczas arytmetyki zmiennoprzecinkowej. Myślę, że to wystarczy, aby zadeklarować, że "VS2013 obsługuje AVX2".

Jednak bez względu na to, co zrobiłem, VS2013 nie produkują kod AVX2 do obliczeń Integer (ani int16_t ani int32_t pracował), więc myślę, że to nie jest obsługiwany w ogóle (gcc produkuje AVX2 do mojego kodu w wersji 4.8. 2; nie wiem o wcześniejszych wersjach).

Gdybym musiał wykonać obliczenia na int32_t, mógłbym rozważyć zamianę ich na float iz powrotem. Jednak ponieważ używam int16_t, to nie pomaga.