Shuffle AVX 256向量元素由左/右1位置 - C内在函数

时间:2016-11-25 12:28:15

标签: c sse hpc intrinsics avx

我试图找到一种更有效的方式来旋转"或者将avx _m256向量中的32位浮点值向右或向左移动一个位置。

这样:

a7,a6,a5,a4,a3,a2,a1,a0

变为

0,a7,a6,a5,a4,a3,a2,a1

(我不介意,无论如何,当我更换电池时数据会丢失。)

我已经看过这个帖子:Emulating shifts on 32 bytes with AVX 但我真的不明白发生了什么,也没有解释_MM_SHUFFLE(0,0,3,0)作为输入参数的作用。

我正在尝试优化此代码:

_mm256_store_ps(temp, array[POS(ii, jj)]);
_mm256_store_ps(left, array[POS(ii, jj-1)]);

tmp_array[POS(ii, jj)] = _mm256_set_ps(left[0], temp[7], temp[6], temp[5], temp[4], temp[3], temp[2], temp[1]);

我知道一旦轮班到位,我可以使用插入来替换剩余的单元格。我觉得这将更有效,然后解压缩到float [8]数组并重构。

- 我也希望能够左右移动,因为我需要在其他地方执行类似的操作。

非常感谢任何帮助!谢谢!

1 个答案:

答案 0 :(得分:4)

对于AVX2

使用VPERMPS在一个交叉的随机播放指令中执行此操作。

rotated_right = _mm256_permutevar8x32_ps(src, _mm256_set_epi32(0,7,6,5,4,3,2,1));

对于AVX(不含AVX2)

由于你说数据来自内存,这可能是好的:

  • 使用未对齐的载荷将7个元素放到正确的位置,解决所有的交叉问题。
  • 然后将缠绕的元素混合到另一个7的矢量中。
  • 要获取用于混合的原位元素,可以使用广播加载将其置于高位。 AVX可以在一条VBROADCASTPS指令中进行广播加载(所以set1()便宜),虽然它确实需要Intel SnB和IvB上的shuffle端口(只有两个Intel微架构与AVX但不是AVX2)。 (请参阅标记wiki中的perf链接。

INSERTPS仅适用于XMM目的地,无法到达上层车道。

您可以使用VINSERTF128进行另一个未对齐的加载,最终将您想要的元素作为高级元素放在上部通道中(在低通道中有一些“不关心”矢量)。

这是编译,但未经过测试。

__m256 load_rotr(float *src)
{
#ifdef __AVX2__
    __m256 orig = _mm256_loadu_ps(src);
    __m256 rotated_right = _mm256_permutevar8x32_ps(orig, _mm256_set_epi32(0,7,6,5,4,3,2,1));
    return rotated_right;
#else
    __m256 shifted = _mm256_loadu_ps(src + 1);
    __m256 bcast = _mm256_set1_ps(*src);
    return _mm256_blend_ps(shifted, bcast, 0b10000000);
#endif
}

请参阅the code + asm on Godbolt