我有一个相当复杂的函数,它需要几个 double 值,它们代表 3 空间中的两个向量(幅度、纬度、经度),其中纬度和经度以弧度和角度表示。该函数的目的是将第一个向量围绕第二个向量旋转指定的角度并返回结果向量。我已经验证了代码在逻辑上是正确的并且有效。
该函数的预期用途是用于图形,因此不需要双精度;但是,在目标平台上,采用浮点数(特别是sinf、cosf、atan2f、asinf、acosf 和 sqrtf)的 trig(和 sqrt)函数在双精度数上的工作速度比在浮点数上更快(可能是因为计算这些值的指令实际上可能需要double;如果传递了一个浮点数,则该值必须强制转换为双精度数,这需要将其复制到具有更多内存的区域——即开销)。结果,函数中涉及的所有变量都是双精度的。
这是问题所在:我正在尝试优化我的功能,以便每秒可以调用更多次。因此,我用对这些函数的浮点版本的调用替换了对 sin、cos、sqrt 等的调用,因为它们导致整体速度提高了 3-4 倍。这适用于几乎所有输入;但是,如果输入向量与标准单位向量(i、j 或 k)接近平行,则各种函数的舍入误差会累积到足以导致稍后调用 sqrtf 或逆触发函数(asinf、acosf、 atan2f) 来传递刚刚超出这些函数域的参数。
所以,我陷入了两难境地:要么我只能调用双精度函数并避免这个问题(最终限制为每秒大约 1,300,000 次向量操作),要么我可以尝试提出其他方法。最终,我想要一种方法来清理逆触发函数的输入以处理边缘情况(对于 sqrt 来说这样做很简单:只需使用 abs)。分支不是一种选择,因为即使是单个条件语句也会增加太多开销,以至于失去任何性能提升。
那么,有什么想法吗?
编辑:有人对我使用双精度和浮点运算表示困惑。如果我将所有值实际存储在双倍大小的容器(即双类型变量)中,则该函数比将它们存储在浮点大小的容器中要快得多。但是,出于显而易见的原因,浮点精度三角运算比双精度三角运算更快。