C++ 模数(浮动)与分支

C++ 模数(浮动)与分支,c++,c,modulus,branch-prediction,C++,C,Modulus,Branch Prediction,给定两个执行相同操作的表达式([-3.14,3.14]->[0,6.28]): 或 这两者在性能上有一般性差异吗 编辑: 假设这样一个表达式被多次调用(因此性能是相关的),并且输入a每次都不同。(使问题更直接地得到回答) 这两者在性能上有一般性差异吗 当然,分析是最好的,但作为一般指导,考虑优化潜力。 编译器通常会在A类型的整个范围内进行优化,而不是[-3.14,3.14]t是一个简单的计算,易于优化 此外,在C中,m计算被强制进入double,当然还有一个函数调用。更多的限制意味着更少的优化可

给定两个执行相同操作的表达式(
[-3.14,3.14]->[0,6.28]
):

这两者在性能上有一般性差异吗

编辑: 假设这样一个表达式被多次调用(因此性能是相关的),并且输入
a
每次都不同。(使问题更直接地得到回答)

这两者在性能上有一般性差异吗

当然,分析是最好的,但作为一般指导,考虑优化潜力。

编译器通常会在
A
类型的整个范围内进行优化,而不是[-3.14,3.14]
t
是一个简单的计算,易于优化

此外,在C中,
m
计算被强制进入
double
,当然还有一个函数调用。更多的限制意味着更少的优化可能性
t
可以使用最佳FP宽度

推荐
a>0?a:a+6.28
作为一般首选方法


给出了两个做相同事情的表达式

但是他们在域上做了而不是做同样的事情
[-3.14,3.14]

大约四分之一的
double
在[0…1.0]范围内
m
使用
a+6.28
将在该加法中丢失至少3到所有位的精度。优点:
t

范围不同:
t
的范围是[0,6.28]
m
的范围是[0,6.28],而不是[0,6.28]


考虑更高的目标

很明显,这段代码正在尝试三角范围缩减。要做到这一点,比基本的正弦、余弦、切线计算本身要困难。请参阅

如果代码是以度而不是弧度开始的,那么首先考虑范围缩小的范围。


大画面


根据
a
的派生方式或
t
m
的使用方式,甚至可能会有更好的性能想法。因此,如果性能确实是一个问题,则需要周围的代码,否则我们会错误地进行微优化。

有一个非常简单的答案:测量。编写一个基准测试并尝试一下(确保已打开优化器)。这是知道一件事是否比另一件事快的唯一方法。当然,但我想我正在寻找一个更符合经验的答案。如果没有,那很好。但我想知道一件事是否比另一件事有普遍的好处。godbolt.org对此很有帮助。请参阅您的两个解决方案与gcc一起生成的程序集:另外,C++的另一个选择。通常在使用角度时,人们更喜欢从[0, 2π]映射到[]。−π、 π]而不是相反,从接近零的浮点精度的提高中获益。将较小的负值映射为较大的值会失去精度。
a > 0? a : a + 6.28
fmod(a + 6.28, 6.28)
// Tertiary
t = a > 0? a : a + 6.28
// vs fmod
m = fmod(a + 6.28, 6.28)