pcsx2 - procesador con soporte avx2
Cómo rotar un vector SSE/AVX (2)
Necesito realizar una operación de rotación con la menor cantidad de ciclos de reloj posible. En el primer caso, asumamos __m128i
como fuente y tipo de __m128i
:
source: || A0 || A1 || A2 || A3 ||
dest: || A1 || A2 || A3 || A0 ||
dest = (__m128i)_mm_shuffle_epi32((__m128i)source, _MM_SHUFFLE(0,3,2,1));
Ahora quiero hacer lo mismo con los intrínsecos AVX. Asumamos esta vez __m256i
como fuente y tipo de __m256i
:
source: || A0 || A1 || A2 || A3 || A4 || A5 || A6 || A7 ||
dest: || A1 || A2 || A3 || A4 || A5 || A6 || A7 || A0 ||
A los intrínsecos de AVX les faltan la mayoría de las operaciones de enteros SSE correspondientes. Tal vez haya alguna manera de obtener la salida deseada trabajando con la versión de punto flotante.
Lo he intentado con:
dest = (__m256i)_mm256_shuffle_ps((__m256)source, (__m256)source, _MM_SHUFFLE(0,3,2,1));
pero lo que obtengo es:
|| A0 || A2 || A3 || A4 || A5 || A6 || A7 || A1 ||
¿Alguna idea sobre cómo resolver esto de una manera eficiente? (sin mezclar el funcionamiento de SSE y AVX y sin invertir "manualmente" A0
y A1
¡Gracias por adelantado!
Mi solución:
__m256 tmp = ( __m256 ) _mm256_permute_ps((__m256)_source, _MM_SHUFFLE ( 0,3,2,1 ));
* ( _dest ) = ( __m256i) _mm256_blend_ps(tmp, _mm256_permute2f128_ps ( tmp,tmp,1 ), 136);
Todavía no he comprobado cómo están las cosas con AVX, pero al menos para SSE, ¿consideraste _mm_align*
?
Por ejemplo, esto rota un vector de bytes por 2 bytes:
__m128i v;
v = _mm_alignr_epi8 (v, v, 2) // v = v[2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,1]
Esto puede ser una sola instrucción. También tales operaciones son lat 1 / tp 1, es decir, rápidas.
Es probable que AVX sea un poco complicado con este enfoque, por lo que una adaptación puede no ser útil.