如何解决C++ 重构内联 Double 以获得更快的代码 PolyBelp
使用来自 PolyBlep 振荡器的内联双代码来制作合成器。我想知道是否可以使用内在替换或仅重构代码使其更有效,以便编译器在编译时可以自动应用内在。任何其他不使用向量的方法只是简单的重构都可以,只是提高一些速度,因为它有点费力,谢谢!
inline double blep(double t,double dt) {
if (t < dt) {
return -square_number(t / dt - 1);
}
else if (t > 1 - dt) {
return square_number((t - 1) / dt + 1);
}
else {
return 0;
}
}
它使用了大量的减法和除法,但也使用了一些逻辑,想知道是否有办法稍微加快速度以更好地节省 CPU?
这是在 Visual Studio 2019 c++17 中使用 C++ 类型代码。任何建议将不胜感激谢谢!
源代码https://github.com/martinfinke/PolyBLEP
编辑:t 和 dt 是相位位置 (t) 和频率/音高 (dt) 的可变非静态传入值
解决方法
可能最简单和最有效的优化是用逆乘法代替除法(假设 dt
不变)。但是你也可以避开所有的分支。
注意你的函数是关于t=0.5
(假设为dt<0.5
)点对称的,即f(0.5-x) = -f(0.5+x)
,平方函数内部的表达式可以改写为(abs(t-0.5)-0.5)/dt+1)
(自 square(-x)=square(x)
)。
现在如果且仅两个分支都失败了
--> dt<t && t<1-dt
--> dt-0.5 < t-0.5 < 0.5-dt
--> abs(t-0.5) < 0.5-dt
--> abs(t-0.5) - 0.5 < -dt
--> (abs(t-0.5) - 0.5)/dt < -1
--> (abs(t-0.5) - 0.5)/dt + 1 < 0
这意味着,我们可以改写 max((abs(t-0.5) - 0.5)/dt + 1,0)
(当然,平方 0 仍然是 0)并总结:
bleb(t,dt) = sign(t-0.5)*square(max(0,(abs(t-0.5)-0.5)/dt+1))
或使用 C++:
double s = t-0.5;
return std::copysign(square_number(std::max(0.0,(std::abs(s)-0.5)*(1.0/dt)+1.0)),s);
1/dt
的计算当然应该被排除在外(您的编译器可能能够做到这一点),并且 copysign
和 abs
应该编译为一些简单的位操作(检查为您的编译器生成的程序集)。
所有操作都可以毫无问题地向量化,但您可能需要重构周围的代码才能做到这一点。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。