SSE内在函数包含_mm_shuffle_ps xmm1 xmm2 immx
,允许从xmm1
中选择2个来自xmm2
的2个元素的元素。然而,这适用于花车,(由 _ps 隐含,单打包装)。但是,如果你强制打包整数 __ m128i ,那么你也可以使用 _mm_shuffle_ps :
#include <iostream>
#include <immintrin.h>
#include <sstream>
using namespace std;
template <typename T>
std::string __m128i_toString(const __m128i var) {
std::stringstream sstr;
const T* values = (const T*) &var;
if (sizeof(T) == 1) {
for (unsigned int i = 0; i < sizeof(__m128i); i++) {
sstr << (int) values[i] << " ";
}
} else {
for (unsigned int i = 0; i < sizeof(__m128i) / sizeof(T); i++) {
sstr << values[i] << " ";
}
}
return sstr.str();
}
int main(){
cout << "Starting SSE test" << endl;
cout << "integer shuffle" << endl;
int A[] = {1, -2147483648, 3, 5};
int B[] = {4, 6, 7, 8};
__m128i pC;
__m128i* pA = (__m128i*) A;
__m128i* pB = (__m128i*) B;
*pA = (__m128i)_mm_shuffle_ps((__m128)*pA, (__m128)*pB, _MM_SHUFFLE(3, 2, 1 ,0));
pC = _mm_add_epi32(*pA,*pB);
cout << "A[0] = " << A[0] << endl;
cout << "A[1] = " << A[1] << endl;
cout << "A[2] = " << A[2] << endl;
cout << "A[3] = " << A[3] << endl;
cout << "B[0] = " << B[0] << endl;
cout << "B[1] = " << B[1] << endl;
cout << "B[2] = " << B[2] << endl;
cout << "B[3] = " << B[3] << endl;
cout << "pA = " << __m128i_toString<int>(*pA) << endl;
cout << "pC = " << __m128i_toString<int>(pC) << endl;
}
相关相应程序集的片段(mac osx,macports gcc 4.8,-march = native在ivybridge CPU上):
vshufps $228, 16(%rsp), %xmm1, %xmm0
vpaddd 16(%rsp), %xmm0, %xmm2
vmovdqa %xmm0, 32(%rsp)
vmovaps %xmm0, (%rsp)
vmovdqa %xmm2, 16(%rsp)
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
....
因此它似乎在整数上工作正常,我预期因为寄存器对类型不可知,但是必须有一个理由说明文档说这个指令仅用于浮点数。有人知道任何缺点,或者我错过的影响吗?
答案 0 :(得分:5)
整数没有等效于_mm_shuffle_ps
。要在这种情况下达到相同的效果,你可以做到
SSE2
*pA = _mm_shuffle_epi32(_mm_unpacklo_epi32(*pA, _mm_shuffle_epi32(*pB, 0xe)),0xd8);
SSE4.1
*pA = _mm_blend_epi16(*pA, *pB, 0xf0);
或change to the floating point domain喜欢这个
*pA = _mm_castps_si128(
_mm_shuffle_ps(_mm_castsi128_ps(*pA),
_mm_castsi128_ps(*pB), _MM_SHUFFLE(3, 2, 1 ,0)));
But changing domains may incur bypass latency delays。请记住,根据Agner
旁路延迟在延迟是瓶颈的长依赖链中很重要,但是 而不是吞吐量而不是重要的延迟。
您必须测试代码并查看上述哪种方法更有效。
幸运的是,在大多数Intel / AMD CPU上,在大多数整数向量指令之间使用shufps
通常没有任何代价。阿格纳说:
例如,我在混合
PADDD
和SHUFPS
[在Sandybridge]时发现没有延迟。
Nehalem确实有{2}的旁路延迟延迟,但即便如此,单个SHUFPS
通常仍然比其他多个指令更快。额外的指令也有延迟,以及成本计算。
反向(FP数学指令之间的整数混洗)不安全:
在示例8.3a中的第112页的Agner Fog's microarchitecture 中,他显示使用SHUFPS
(PSHUFD
)代替_mm_shuffle_epi32
(SHUFPS
)时浮点域导致四个时钟周期的旁路延迟。在例8.3b中,他使用SHUFPS来消除延迟(在他的例子中有效)。
在Nehalem上实际上有五个域名。 Nahalem似乎受影响最大(在Nahalem之前不存在旁路延迟)。在Sandy Bridge,延误不太重要。哈斯韦尔更是如此。事实上,Haswell Agner说他发现_mm_shuffle_ps
或SHUFPS
之间没有延迟(参见第140页)。