[英]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.