【发布时间】:2016-07-27 06:38:22
【问题描述】:
我一直在尝试在 SSE2 内在函数中实现按向量移位,但从实验和the intel intrinsic guide 来看,它似乎只使用了向量中最不重要的部分。
为了改写我的问题,给定一个向量 {v1, v2, ..., vn} 和一组移位 {s1, s2, ..., sn},我如何计算结果 {r1, r2, ..., rn} 这样:
r1 = v1 << s1
r2 = v2 << s2
...
rn = vn << sn
因为似乎 _mm_sll_epi* 执行此操作:
r1 = v1 << s1
r2 = v2 << s1
...
rn = vn << s1
提前致谢。
编辑:
这是我的代码:
#include <iostream>
#include <cstdint>
#include <mmintrin.h>
#include <emmintrin.h>
namespace SIMD {
using namespace std;
class SSE2 {
public:
// flipped operands due to function arguments
SSE2(uint64_t a, uint64_t b, uint64_t c, uint64_t d) { low = _mm_set_epi64x(b, a); high = _mm_set_epi64x(d, c); }
uint64_t& operator[](int idx)
{
switch (idx) {
case 0:
_mm_storel_epi64((__m128i*)result, low);
return result[0];
case 1:
_mm_store_si128((__m128i*)result, low);
return result[1];
case 2:
_mm_storel_epi64((__m128i*)result, high);
return result[0];
case 3:
_mm_store_si128((__m128i*)result, high);
return result[1];
}
/* Undefined behaviour */
return 0;
}
SSE2& operator<<=(const SSE2& rhs)
{
low = _mm_sll_epi64(low, rhs.getlow());
high = _mm_sll_epi64(high, rhs.gethigh());
return *this;
}
void print()
{
uint64_t a[2];
_mm_store_si128((__m128i*)a, low);
cout << hex;
cout << a[0] << ' ' << a[1] << ' ';
_mm_store_si128((__m128i*)a, high);
cout << a[0] << ' ' << a[1] << ' ';
cout << dec;
}
__m128i getlow() const
{
return low;
}
__m128i gethigh() const
{
return high;
}
private:
__m128i low, high;
uint64_t result[2];
};
}
int main()
{
cout << "operator<<= test: vector << vector: ";
{
auto x = SIMD::SSE2(7, 8, 15, 10);
auto y = SIMD::SSE2(4, 5, 6, 7);
x.print();
y.print();
x <<= y;
if (x[0] != 112 || x[1] != 256 || x[2] != 960 || x[3] != 1280) {
cout << "FAILED: ";
x.print();
cout << endl;
} else {
cout << "PASSED" << endl;
}
}
return 0;
}
应该发生的结果是 {7
希望这会有所帮助,詹斯。
【问题讨论】:
-
拜托,拜托,如果你不给我们你的变量声明,别人怎么知道你在做什么?请先阅读顶部菜单中的帮助文本以了解如何提问,然后阅读“c”标签的信息文本(只需单击它)。那就看stackoverflow.com/help/mcve。
-
@JensGustedt 我在标记它时打错了,它应该是 c++。但不管怎样,你去吧。
-
可变的元素粒度移位是 AVX2 的一部分,而不是 SSE2。此外,它们仅存在于 32/64 位元素大小。您可以改为通过乘法实现元素粒度左移。
-
@EOF 不过,我的元素是 64 位的。并且元素粒度的左移对右移没有帮助,我也需要。
-
看来你运气不好。您可能必须将向量元素移动到整数寄存器,将它们移位并将它们移回,或者将它们拆分为单独的向量寄存器并在移位后将它们合并回来。