gpt4 book ai didi

c++ - 如何使用标量 SIMD 内在函数最小化开销加载到 simd 寄存器中

转载 作者:搜寻专家 更新时间:2023-10-31 01:30:23 27 4
gpt4 key购买 nike

在 godbolt.org 使用 gcc 7.2 我可以看到以下内容 code在汇编程序中翻译得非常好。我看到 1 次加载、1 次添加和 1 次存储。

#include <immintrin.h>

__attribute__((alwaysinline)) double foo(double x, double y)
{
return x+y;
}

void usefoo(double x, double *y, double *z)
{
*z = foo(x, *y);
}

结果是:

usefoo(double, double*, double*):
addsd xmm0, QWORD PTR [rdi]
movsd QWORD PTR [rsi], xmm0
ret

但是,如果我尝试使用内在函数和模板实现相同的 code下面,我可以看到添加了一些开销。特别是,指令的重点是什么:movq xmm0, xmm0

#include <immintrin.h>

__attribute__((alwaysinline)) double foo(double x, double y)
{
return _mm_cvtsd_f64(_mm_add_sd(__m128d{x}, __m128d{y}));
}

void usefoo(double x, double *y, double *z)
{
*z = foo(x, *y);
}

结果是:

usefoo(double, double*, double*):
movq xmm1, QWORD PTR [rdi]
movq xmm0, xmm0
addsd xmm0, xmm1
movlpd QWORD PTR [rsi], xmm0
ret

如何使用标量内在函数实现与编译器生成的代码等效的代码?

如果您想知道我为什么要这样做,请考虑替换 +<= : 如果我写 x<y编译器将结果转换为 bool,而内在函数会将其保留为双位掩码。因此对于我的用例,写作 x<y不是一个选项。但是使用 +很简单,足以说明问题。

最佳答案

“无关的”movq 正在清除 __m128d 中的第二个元素,正如您在列表初始化 __m128d{x} 中所请求的.

When the source operand is an XMM register, the low quadword is moved; when the destination operand is an XMM register, the quadword is stored to the low quadword of the register, and the high quadword is cleared to all 0s.

请记住,当提供的初始化器数量少于成员数量时,所有剩余的成员都将进行值初始化(为零)。

我希望进行更高级别的优化,以确保从不使用第二个元素,并删除多余的指令。另一方面,即使未使用,第二个值也不允许在加法操作期间捕获,显式清除它可能是确保它不会被捕获的最安全方法。

关于c++ - 如何使用标量 SIMD 内在函数最小化开销加载到 simd 寄存器中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48055973/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com