繁体   English   中英

将复数的实部和虚部解压缩到单独的 ymm 寄存器中

[英]Unpacking real and imaginary parts of complex numbers into separate ymm registers

我需要读取一系列复杂的单精度数字,像 [real1, imag1, real2, imag2, ...] 一样存储到 ymm 寄存器中并将它们解压缩,例如 ymm0 包含 [real1, real2, real3, ... ] 和 ymm1 包含 [imag1, imag2, imag3, ...]。 以下代码有效,但使用了四次交叉洗牌。 有没有比我在这里做的更有效的方法来完成这个?

    // the negatives here stand in for imaginary parts
    float _f[] = {1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8};

    int i[] = {0, 2, 4, 6, 1, 3, 5, 7};

    __m256 a = _mm256_loadu_ps(_f);
    __m256 b = _mm256_loadu_ps(_f+8);

    __m256i x = _mm256_loadu_si256((void*)i);

    __m256 c = _mm256_permutevar8x32_ps(a, x);
    __m256 d = _mm256_permutevar8x32_ps(b, x);

    __m256 e = _mm256_permute2f128_ps(c, d, 0x20);
    __m256 f = _mm256_permute2f128_ps(c, d, 0x31);

在此序列的末尾,e 包含实部,f 包含虚部。 我唯一担心的是,在某些机器上,交叉车道洗牌可能很昂贵。

正如哈罗德在评论中所建议的那样,这将完成将实部和虚部分离为单独的向量的工作,但顺序不会完全正确。 相反, e将具有 [real1, real5, real2, real6, ...] 而f将具有相应的虚部。 这对于某些应用程序来说可能已经足够好了,所以我认为值得发布以防其他人发现它有用

    float _f[] = {1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8};

    __m256 a = _mm256_loadu_ps(_f);
    __m256 b = _mm256_loadu_ps(_f+8);

    __m256 c = _mm256_permute_ps(a, 0xd8);
    __m256 d = _mm256_permute_ps(b, 0xd8);

    __m256 e = _mm256_unpacklo_ps(c,d);
    __m256 f = _mm256_unpackhi_ps(c,d);

编辑:而且,正如 Peter Cordes 所指出的,以下更短的解决方案会产生 [real1, real2, real5, real6, real3, real4, real7, real8] 和相应的虚数。

    float _f[] = {1, -1, 2, -2, 3, -3, 4, -4, 5, -5, 6, -6, 7, -7, 8, -8};

    __m256 a = _mm256_loadu_ps(_f);
    __m256 b = _mm256_loadu_ps(_f+8);

    __m256 c = _mm256_shuffle_ps(a, b, 0x88);
    __m256 d = _mm256_shuffle_ps(a, b, 0xdd);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM