Pregunta sobre sse, avx, c – ¿Cómo realizar el desplazamiento a la izquierda del elemento con __m128i?

4

Las instrucciones de cambio de SSE que he encontrado solo pueden cambiar en la misma cantidad en todos los elementos:

_mm_sll_epi32()_mm_slli_epi32()

Estos desplazan todos los elementos, pero por la misma cantidad de desplazamiento.

¿Hay alguna manera de aplicar diferentes turnos a los diferentes elementos? Algo como esto:

__m128i a,  __m128i b;  

r0:=    a0  <<  b0;
r1:=    a1  <<  b1;
r2:=    a2  <<  b2;
r3:=    a3  <<  b3;

Tu respuesta

3   la respuesta
0

En algunas circunstancias, esto puede sustituir a_mm_shl_epi32(a, b):

_mm_mullo_ps(a, 1 << b);

en general, esto requiereb Tener un valor constante. No conozco una forma eficiente de calcular.(1 << b) utilizando instrucciones SSE anteriores.

2

Sin XOP, sus opciones son limitadas. Si puede controlar el formato del argumento de conteo de turnos, entonces puede usar_mm_mullo_pi16 ya que multiplicar por una potencia de dos es lo mismo que desplazarse por esa potencia.

Por ejemplo, si desea cambiar sus 8 elementos de 16 bits en un registro SSE<0, 1, 2, 3, 4, 5, 6, 7> puede multiplicar por 2 elevadas a los poderes de conteo de turnos, es decir, por<0, 2, 4, 8, 16, 32, 64, 128>.

Gracias, lo he conseguido con _mm_mullo_epi32 (SSE4.1). Hmm ..., ¿Puede haber una mejor manera para la CPU de Intel? user1468756
7

Existe el_mm_shl_epi32() intrínseco que hace exactamente eso.

http://msdn.microsoft.com/en-us/library/gg445138.aspx

Sin embargo, requiere laConjunto de instrucciones XOP. Solo los procesadores AMD Bulldozer e Interlagos o posteriores tienen esta instrucción. No está disponible en ningún procesador Intel.

Si quieres hacerlo sin las instrucciones de XOP, tendrás que hacerlo de la manera más difícil: sácalos y hazlos uno por uno.

Sin las instrucciones de XOP, puede hacer esto con SSE4.1 usando los siguientes intrínsecos:

_mm_insert_epi32()_mm_extract_epi32()

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse41_reg_ins_ext.htm

Esos le permitirán extraer partes de un registro de 128 bits en registros regulares para hacer el cambio y volver a colocarlos.

Si vas con el último método, será horriblemente ineficiente. Es por eso_mm_shl_epi32() Existe en primer lugar.

Preguntas relacionadas