W SSE3, instrukcja PALIGNR wykonuje następujące czynności:_mm_alignr_epi8 (PALIGNR) równowartość w AVX2
PALIGNR concatenates the destination operand (the first operand) and the source operand (the second operand) into an intermediate composite, shifts the composite at byte granularity to the right by a constant immediate, and extracts the right-aligned result into the destination.
Jestem aktualnie w środku przenoszenie mojego kodu SSE4 użyć instrukcji AVX2 i pracy na 256bit rejestruje zamiast 128-bitowy. Naiwnie wierzyłem, że funkcja wewnętrzna _mm256_alignr_epi8
(VPALIGNR) wykonuje tę samą operację co _mm_alignr_epi8
tylko w rejestrach 256-bitowych. Niestety jednak tak nie jest. W rzeczywistości, _mm256_alignr_epi8
traktuje rejestr 256-bitowy jako 2 128-bitowe rejestry i wykonuje 2 operacje "wyrównania" na dwóch sąsiednich rejestrach 128-bitowych. Skutecznie wykonuje tę samą operację co _mm_alignr_epi8
, ale na 2 rejestrach jednocześnie. To najbardziej wyraźnie przedstawiono tutaj: _mm256_alignr_epi8
Obecnie moje rozwiązanie jest utrzymanie przy użyciu _mm_alignr_epi8
dzieląc ymm (256bit) rejestrach na dwie XMM (128bit) rejestrów (wysokie i niskie), tak jak poniżej:
__m128i xmm_ymm1_hi = _mm256_extractf128_si256(ymm1, 0);
__m128i xmm_ymm1_lo = _mm256_extractf128_si256(ymm1, 1);
__m128i xmm_ymm2_hi = _mm256_extractf128_si256(ymm2, 0);
__m128i xmm_ymm_aligned_lo = _mm_alignr_epi8(xmm_ymm1_lo, xmm_ymm1_hi, 1);
__m128i xmm_ymm_aligned_hi = _mm_alignr_epi8(xmm_ymm2_hi, xmm_ymm1_lo, 1);
__m256i xmm_ymm_aligned = _mm256_set_m128i(xmm_ymm_aligned_lo, xmm_ymm_aligned_hi);
To działa, ale musi być lepszy sposób, prawda? Czy jest być może więcej "ogólnych" instrukcji AVX2, które powinny być używane, aby uzyskać ten sam wynik?
Tak, to to samo rozwiązanie. ale jeśli jest to jedyny sposób, to wygląda na to, że projektanci instrukcji AVX2 mają duże niedopatrzenie. – eladidan
Nie mogłem tego skompilować ... Dostaję błąd kompilacji: "błąd katastroficzny: parametr wewnętrzny musi być wartością natychmiastową" w następującym wierszu: "__m128i vouth = _mm_alignr_epi8 (v0l, v0h, n);". Supposidely, ponieważ n nie jest immidiate. Jak mogłeś to ominąć? Używam kompilatora Intel C++ – eladidan
Działa to dla mnie, o ile n jest stałą czasu kompilacji - używam również kompilatora Intel ICC, ale kompiluję jako C zamiast C++, jeśli to robi jakąkolwiek różnicę, a także działa dla mnie z gcc. –