C++ AVX,单精度复数的水平和?

C++ AVX,单精度复数的水平和?,c++,avx,avx2,C++,Avx,Avx2,我有一个256位AVX寄存器,包含4个单精度复数,存储为实、虚、实、虚等。我目前正在将整个256位寄存器写回内存并在内存中求和,但这似乎效率低下 如何使用AVX(或AVX2)内部函数执行复数水平和?我会接受使用汇编的答案,如果没有一个使用intrinsic的效率相当的答案 编辑:为了澄清,如果寄存器包含AR、AI、BR、BI、CR、CI、DR、DI,我想计算复数(AR+BR+CR+DR、AI+BI+CI+DI)。如果结果在256位寄存器中,我可以提取2个单精度浮点数 编辑2:潜在的解决方案,但不

我有一个256位AVX寄存器,包含4个单精度复数,存储为实、虚、实、虚等。我目前正在将整个256位寄存器写回内存并在内存中求和,但这似乎效率低下

如何使用AVX(或AVX2)内部函数执行复数水平和?我会接受使用汇编的答案,如果没有一个使用intrinsic的效率相当的答案

编辑:为了澄清,如果寄存器包含AR、AI、BR、BI、CR、CI、DR、DI,我想计算复数(AR+BR+CR+DR、AI+BI+CI+DI)。如果结果在256位寄存器中,我可以提取2个单精度浮点数

编辑2:潜在的解决方案,但不一定是最优的

float hsum_ps_sse3(__m128 v) {
    __m128 shuf = _mm_movehdup_ps(v);        // broadcast elements 3,1 to 2,0
    __m128 sums = _mm_add_ps(v, shuf);
    shuf        = _mm_movehl_ps(shuf, sums); // high half -> low half
    sums        = _mm_add_ss(sums, shuf);
    return        _mm_cvtss_f32(sums);
}

float sumReal = 0.0;
float sumImaginary = 0.0;

 __m256i mask = _mm256_set_epi32 (7, 5, 3, 1, 6, 4, 2, 0);

 // Separate real and imaginary.
__m256 permutedSum = _mm256_permutevar8x32_ps(sseSum0, mask);
__m128 realSum = _mm256_extractf128_ps(permutedSum , 0);
__m128 imaginarySum = _mm256_extractf128_ps(permutedSum , 1);

// Horizontally sum real and imaginary.
sumReal = hsum_ps_sse3(realSum);
sumImaginary = hsum_ps_sse3(imaginarySum);

一个相当简单的解决方案,只需要AVX(而不是AVX2):


结果将是
v0
作为
{sum.re,sum.im,sum.re,sum.im}

一个相当简单的解决方案,只需要AVX(而不是AVX2):


结果将在
v0
中显示为
{sum.re,sum.im,sum.re,sum.im}

我们是一个代码站点;你可以用一个简单的例子更容易地解释你想要什么。也就是说,我忽略了这个问题。是的,AVX是一个疯狂的设计,它有两条车道,但在这种情况下,这并不有害。将实部移动到一个通道,将虚部移动到另一个通道(位0:127和128:255),在通道内进行水平相加。结果以0:31和128:159结束。你的目标是什么?也许你想考虑在两个AVX寄存器中存储八个复数:一个实部和另一个虚部。这真的取决于你的目标是什么。@Zboson我的目标和问题中所说的完全一样。存储数据时,实值和虚值是交替的,这是无法更改的。我在编辑中提出的解决方案将实部和虚部分开以求和,但输入数据将是实部和虚部交替的;你可以用一个简单的例子更容易地解释你想要什么。也就是说,我忽略了这个问题。是的,AVX是一个疯狂的设计,它有两条车道,但在这种情况下,这并不有害。将实部移动到一个通道,将虚部移动到另一个通道(位0:127和128:255),在通道内进行水平相加。结果以0:31和128:159结束。你的目标是什么?也许你想考虑在两个AVX寄存器中存储八个复数:一个实部和另一个虚部。这真的取决于你的目标是什么。@Zboson我的目标和问题中所说的完全一样。存储数据时,实值和虚值是交替的,这是无法更改的。我在编辑中提出的解决方案将实部和虚部分开以求和,但输入数据将是实部和虚部交替的。奇怪-可能与CR/LF行结尾有关?哈哈哈…我在Firefox中使用了一个随机代理欺骗程序,我最近安装了它来试用。显然,它随机选择的个人资料就是这样做的(我认为是IE10)。当我选择一个新的随机配置文件时,它会正确显示。啊哈-那真是一种解脱-我之前点击过,看不出帖子有任何错误。奇怪-可能与CR/LF行结尾有关?哈哈哈…我在Firefox中使用了一个随机代理欺骗程序,我最近安装了它来试用。显然,它随机选择的个人资料就是这样做的(我认为是IE10)。当我选择一个新的随机配置文件时,它会正确地显示出来。啊哈-那真是松了一口气-我之前点击过,看不出这篇文章有什么问题。
__m128i v0 = _mm256_castps256_ps128(v);      // get low 2 complex values
__m128i v1 = _mm256_extractf128_ps(v, 1);    // get high 2 complex values
v0 = _mm_add_ps(v0, v1);                     // add high and low
v1 = _mm_shuffle_ps(v0, v0, _MM_SHUFFLE(1, 0, 3, 2));
v0 = _mm_add_ps(v0, v1);                     // combine two halves of result