2016-11-25 33 views
3

我试图找到一种更有效的方法来“旋转”或将avx _m256矢量中的32位浮点值向右或向左移动一个地方。Shuffle AVX 256矢量元素左移/右移1位C内部函数

使得:

A7,A6,A5,A4,A3,A2,A1,A0

变得

0,A7,A6,A5,A4,A3,A2,A1

(我不介意,因为我反正更换单元中的数据丢失。)

我已经查看了这个线程:Emulating shifts on 32 bytes with AVX 但我不雷尔y理解正在发生的事情,并且它不会解释_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]); 

我知道一旦一个转变是在地方,我可以用插入来代替剩余的细胞。我觉得这样做会更有效率,然后拆开浮动阵列并重建。

- 我还希望能够左右移动,因为我需要在别处执行类似的操作。

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

+1

我们称之为洗牌,因为你四处移动元素,不移动或旋转的内部元件的钻头。 –

+0

感谢您的术语更正,恰当地更名问题! – MishMash95

+1

什么是紧接在前面的代码,填充什么将会被移动,以及紧接着的将使用移位结果的代码是什么?也许外部部件可以集成到优化工作中。 –

回答

3

对于AVX2

使用VPERMPS做到在一个车道交叉排指令。

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

对于AVX(不包括AVX2)

既然你说的数据从内存中已经到来,这可能是件好事:

  • 使用未对齐的负荷得到将7个元素放在正确的位置,解决所有车道穿越问题。
  • 然后将缠绕的元素混合到另一个元素的向量中。
  • 要获取包含就地混合的元素,可以使用广播负载将其置于高位。 AVX可以在一个VBROADCASTPS指令中广播加载(所以set1()便宜),尽管它确实需要Intel SnB和IvB(唯一两个带有AVX而不是AVX2的Intel微体系结构)上的shuffle端口。 (见标签维基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

+2

再次感谢您的帮助!我尝试了AVX2方法,并且在我自己的机器上本地运行了极其可怕的操作 不幸的是,我意识到我的分发环境只有普通的AVX,另一种方法是使用loadu虽然我已经从你的回复中学到了很多东西,所以谢谢你的时间:)!但是,它比我在实施时已经做的更慢了30%左右 – MishMash95