【发布时间】:2014-11-17 22:59:03
【问题描述】:
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 on an 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
....
因此,它似乎在整数上运行良好,这是我所期望的,因为寄存器与类型无关,但是文档说该指令仅适用于浮点数肯定是有原因的。有人知道我遗漏的任何缺点或影响吗?
【问题讨论】:
-
访问具有不兼容类型的 SSE/AVX 寄存器可能会损害性能。 (仅在最新的英特尔处理器 AFAIK 上)
-
查看这个问题difference-between-the-avx-instructions-vxorpd-and-vpxor中的cmets。尤其是 Mysticial 的第一个
-
我知道类似的问题,虽然问题是有一个等效的功能,但我的问题以 shuffle 指令为例。