我发现的SSE转换指令只能在所有元素上移动相同的数量:
_mm_sll_epi32()
_mm_slli_epi32()
These shift all elements, but by the same shift amount.
有没有办法对不同的元素应用不同的转换?像这样:
__m128i a, __m128i b;
r0:= a0 << b0;
r1:= a1 << b1;
r2:= a2 << b2;
r3:= a3 << b3;
答案 0 :(得分:7)
存在_mm_shl_epi32()
内在函数。
http://msdn.microsoft.com/en-us/library/gg445138.aspx
但是,它需要XOP instruction set 。只有AMD Bulldozer和Interlagos处理器或更高版本才有此指令。它不适用于任何英特尔处理器。
如果你想在没有XOP指令的情况下做到这一点,你将需要以艰难的方式去做:将它们拉出并逐一进行。
如果没有XOP指令,您可以使用以下内在函数对SSE4.1执行此操作:
_mm_insert_epi32()
_mm_extract_epi32()
这些将允许您将128位寄存器的部分提取到常规寄存器中以进行移位并将其放回。
如果你采用后一种方法,那将是非常低效的。这就是为什么_mm_shl_epi32()
首先存在的原因。
答案 1 :(得分:2)
如果没有XOP,您的选择是有限的。如果你可以控制移位计数参数的格式,那么你可以使用_mm_mullo_pi16
,因为乘以2的幂与移动该幂相同。
例如,如果要将SSE寄存器中的8个16位元素移位<0, 1, 2, 3, 4, 5, 6, 7>
,则可以将2乘以上升到移位计数幂,即<0, 2, 4, 8, 16, 32, 64, 128>
。
答案 2 :(得分:0)
在某些情况下,这可以替代_mm_shl_epi32(a, b)
:
_mm_mullo_ps(a, 1 << b);
一般来说,这需要b
具有常数值 - 我不知道使用较旧的SSE指令计算(1 << b)
的有效方法。