我正在将使用SSE2内在函数编写的矢量化代码迁移到AVX2内在函数。
令我失望的是,我发现移位指令 _mm256_slli_si256 和 _mm256_srli_si256 仅分别在AVX寄存器的两半上运行,并在它们之间引入零。 (这与处理整个SSE寄存器的 _mm_slli_si128 和 _mm_srli_si128 相反。)
你能推荐我一个简短的替代品吗?
更新:
可以有效地实现 _mm256_slli_si256
_mm256_alignr_epi8(A, _mm256_permute2x128_si256(A, A, _MM_SHUFFLE(0, 0, 3, 0)), N)
或
_mm256_slli_si256(_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(0, 0, 3, 0)), N)
对于大于16字节的移位。
但问题仍然是_mm256_srli_si256
。
答案 0 :(得分:8)
从不同的输入,我收集了这些解决方案。跨越通道间障碍的关键是对齐指令_mm256_alignr_epi8
。
0< N< 16
_mm256_alignr_epi8(A, _mm256_permute2x128_si256(A, A, _MM_SHUFFLE(0, 0, 2, 0)), 16 - N)
N = 16
_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(0, 0, 2, 0))
16< N< 32
_mm256_slli_si256(_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(0, 0, 2, 0)), N - 16)
0< N< 16
_mm256_alignr_epi8(_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(2, 0, 0, 1)), A, N)
N = 16
_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(2, 0, 0, 1))
16< N< 32
_mm256_srli_si256(_mm256_permute2x128_si256(A, A, _MM_SHUFFLE(2, 0, 0, 1)), N - 16)
答案 1 :(得分:5)
这是使用avx2向左移位ymm寄存器的功能。我用它来左移一个,虽然看起来它可以工作多达63位。
//----------------------------------------------------------------------------
// bit shift left a 256-bit value using ymm registers
// __m256i *data - data to shift
// int count - number of bits to shift
// return: __m256i - carry out bit(s)
static __m256i bitShiftLeft256ymm (__m256i *data, int count)
{
__m256i innerCarry, carryOut, rotate;
innerCarry = _mm256_srli_epi64 (*data, 64 - count); // carry outs in bit 0 of each qword
rotate = _mm256_permute4x64_epi64 (innerCarry, 0x93); // rotate ymm left 64 bits
innerCarry = _mm256_blend_epi32 (_mm256_setzero_si256 (), rotate, 0xFC); // clear lower qword
*data = _mm256_slli_epi64 (*data, count); // shift all qwords left
*data = _mm256_or_si256 (*data, innerCarry); // propagate carrys from low qwords
carryOut = _mm256_xor_si256 (innerCarry, rotate); // clear all except lower qword
return carryOut;
}
//----------------------------------------------------------------------------
答案 2 :(得分:1)
如果移位计数是4个字节的倍数,vpermd
(_mm256_permutevar8x32_epi32
)具有正确的随机屏蔽将使用一条指令(或更多,如果您实际需要将移位归零) -in bytes而不是在其上复制不同的元素。)
为了支持变量(4B的倍数)移位计数,您可以将控件掩码从窗口加载到0 0 0 0 0 0 0 1 2 3 4 5 6 7 0 0 0 0 0 0 0
或其他数组中,除了0
只是底部元素,并且不会把事情弄清楚。有关从滑动窗口生成蒙版的更多信息,请参阅my answer on another question。
这个答案很小,因为vpermd
并没有直接解决问题。我指出它可以作为一种替代方案,在某些你正在寻找完整向量移位的情况下可以使用。