我希望在移位为零的同时向左或向右移动SSE / AVX寄存器的32位数。
让我对我感兴趣的转变更加准确。对于SSE,我想做四个32位浮点数的以下转换:
shift1_SSE: [1, 2, 3, 4] -> [0, 1, 2, 3]
shift2_SSE: [1, 2, 3, 4] -> [0, 0, 1, 2]
对于AVX,我想转移做以下转变:
shift1_AVX: [1, 2, 3, 4, 5, 6, 7, 8] -> [0, 1, 2, 3, 4, 5, 6, 7]
shift2_AVX: [1, 2, 3, 4, 5, 6, 7, 8] -> [0, 0, 1, 2, 3, 4, 5, 6]
shift3_AVX: [1, 2, 3, 4 ,5 ,6, 7, 8] -> [0, 0, 0, 0, 1, 2, 3, 4]
对于SSE,我提出了以下代码
shift1_SSE = _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 4));
shift2_SSE = _mm_shuffle_ps(_mm_setzero_ps(), x, 0x40);
//shift2_SSE = _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 8));
使用SSE 有更好的方法吗?
对于AVX,我提出了以下需要AVX2的代码(并且未经测试)。编辑(由Paul R解释,此代码不起作用)。
shift1_AVX2 =_mm256_castsi256_ps(_mm256_slli_si256(_mm256_castps_si256(x), 4)));
shift2_AVX2 =_mm256_castsi256_ps(_mm256_slli_si256(_mm256_castps_si256(x), 8)));
shift3_AVX2 =_mm256_castsi256_ps(_mm256_slli_si256(_mm256_castps_si256(x), 12)));
如何使用AVX而不是AVX2(例如使用_mm256_permute
或_mm256_shuffle`)做到最好?使用AVX2有更好的方法吗?
编辑:
Paul R告诉我,我的AVX2代码不起作用,AVX代码可能不值得。相反,对于AVX2,我应该使用_mm256_permutevar8x32_ps
和_mm256_and_ps
。我没有AVX2(Haswell)系统,因此很难测试。
编辑:
根据Felix Wyss的回答,我提出了一些AVX的解决方案,它只需要3个用于shift1_AVX和shift2_AVX的内在函数,而只需要一个用于shift3_AVX的内在函数。这是因为_mm256_permutef128Ps
有一个zeroing feature。
shift1_AVX
__m256 t0 = _mm256_permute_ps(x, _MM_SHUFFLE(2, 1, 0, 3));
__m256 t1 = _mm256_permute2f128_ps(t0, t0, 41);
__m256 y = _mm256_blend_ps(t0, t1, 0x11);
shift2_AVX
__m256 t0 = _mm256_permute_ps(x, _MM_SHUFFLE(1, 0, 3, 2));
__m256 t1 = _mm256_permute2f128_ps(t0, t0, 41);
__m256 y = _mm256_blend_ps(t0, t1, 0x33);
shift3_AVX
x = _mm256_permute2f128_ps(x, x, 41);
答案 0 :(得分:6)
您可以使用_mm256_permute_ps
,_mm256_permute2f128_ps
和_mm256_blend_ps
进行右移,如下所示:
__m256 t0 = _mm256_permute_ps(x, 0x39); // [x4 x7 x6 x5 x0 x3 x2 x1]
__m256 t1 = _mm256_permute2f128_ps(t0, t0, 0x81); // [ 0 0 0 0 x4 x7 x6 x5]
__m256 y = _mm256_blend_ps(t0, t1, 0x88); // [ 0 x7 x6 x5 x4 x3 x2 x1]
结果在y
。要向右旋转,请将置换遮罩设置为0x01
而不是0x81
。通过更改置换和混合控制字节,可以类似地完成左移和左移和更大的移位/旋转。
答案 1 :(得分:5)
你的SSE实现没问题,但我建议你使用_mm_slli_si128
实现两个转换 - 转换使它看起来很复杂,但实际上归结为每个班次只有一条指令。
不幸的是,您的AVX2实施赢了。几乎所有AVX指令实际上只是在两个相邻的128位通道上并行运行的两条SSE指令。因此,对于您的第一个shift_AVX2示例,您将获得:
0, 0, 1, 2, 0, 4, 5, 6
----------- ----------
LS lane MS lane
然而,一切都没有丢失:在AVX上的 工作的少数指令之一是_mm256_permutevar8x32_ps。请注意,您需要结合使用_mm256_and_ps
来将元素中的移位归零。另请注意,这是一个AVX2解决方案 - 除了基本的算术/逻辑运算之外,AVX本身非常有限,因此我认为如果没有AVX2,您将很难有效地完成此任务。