首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SIMD变量旋转

SIMD变量旋转
EN

Stack Overflow用户
提问于 2013-10-06 03:11:45
回答 4查看 1.9K关注 0票数 2

在整个YMM寄存器上执行旋转操作的最快方法是什么,只有在运行时才知道?

所述旋转已知为64位的倍数。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-10-06 03:46:01

使用AVX2,您可以使用_mm256_permutevar8x32_epi32。伪代码(未经测试,常量可能出错):

代码语言:javascript
复制
static inline __m256i rotate(__m256i x, unsigned n) {
    static const __m256i rotspec[4] = {
        _mm256_set_epi32(0, 1, 2, 3, 4, 5, 6, 7),
        _mm256_set_epi32(6, 7, 0, 1, 2, 3, 4, 5),
        _mm256_set_epi32(4, 5, 6, 7, 0, 1, 2, 3),
        _mm256_set_epi32(2, 3, 4, 5, 6, 7, 0, 1)
    };
    return _mm256_permutevar8x32_epi32(x, rotspec[n]);
}
票数 3
EN

Stack Overflow用户

发布于 2013-10-23 04:40:07

您可以使用AVX旋转,如下所示。假设您的输入是x

代码语言:javascript
复制
__m256d t0 = _mm256_permute_pd(x, 0x05);            // [x2  x3  x0  x1]
__m256d t1 = _mm256_permute2f128_pd(t0, t0, 0x01);  // [x0  x1  x2  x3]
__m256d y  = _mm256_blend_pd(t0, t1, 0x0a);         // [x0  x3  x2  x1]

结果在y中。通过倒置混合面罩,您可以向左旋转:

代码语言:javascript
复制
__m256d t0 = _mm256_permute_pd(x, 0x05);            // [x2  x3  x0  x1]
__m256d t1 = _mm256_permute2f128_pd(t0, t0, 0x01);  // [x0  x1  x2  x3]
__m256d y  = _mm256_blend_pd(t0, t1, 0x05);         // [x2  x1  x0  x3]
票数 1
EN

Stack Overflow用户

发布于 2013-10-28 01:20:47

如果您仅限于AVX指令,您仍然可以使用条件混合指令(VBLENDVPD)来选择正确的旋转而不使用开关。这可能会更快,特别是当情况难以预测的时候。

充分执行正确的轮调(经测试):

代码语言:javascript
复制
// rotate packed double vector right by n
__m256d rotate_pd_right(__m256d x, int n) {
    __m128i c = _mm_cvtsi32_si128(n);
    __m128i cc = _mm_unpacklo_epi64(c,c);

    // create blend masks (highest bit)
    __m128d half_low = _mm_castsi128_pd(_mm_slli_epi64(cc, 63));
    __m128d swap_low = _mm_castsi128_pd(_mm_slli_epi64(cc, 62));
    __m256d half = _mm256_insertf128_pd(_mm256_castpd128_pd256(half_low), half_low, 1);
    __m256d swap = _mm256_insertf128_pd(_mm256_castpd128_pd256(swap_low), swap_low, 1);

    // compute rotations
    __m256d t0 = _mm256_permute_pd(x, 0x05);            // [2 3 0 1]
    __m256d t1 = _mm256_permute2f128_pd(t0, t0, 0x01);  // [1 0 2 3]

    __m256d y0 = x;                                     // [3 2 1 0]
    __m256d y1 = _mm256_blend_pd(t0, t1, 0x0a);         // [0 3 2 1]
    __m256d y2 = _mm256_permute2f128_pd(x, x, 0x01);    // [1 0 3 2]
    __m256d y3 = _mm256_blend_pd(t0, t1, 0x05);         // [2 1 0 3]

    // select correct rotation
    __m256d y01 = _mm256_blendv_pd(y0, y1, half);
    __m256d y23 = _mm256_blendv_pd(y2, y3, half);
    __m256d yn  = _mm256_blendv_pd(y01, y23, swap);

    return yn;
}

左旋可以简单地作为

代码语言:javascript
复制
__m256d rotate_pd_left(__m256d x, int n) {
    return rotate_pd_right(x, -n);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19205026

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档