我正在用C/C++在Visual Studio 2012 Professional(Windows)中编写一个程序,其中包括使用pow()
计算许多功率。我运行了分析器,以找出为什么它需要这么长时间才能运行,我发现pow()
是瓶颈。
我重写了权力,pow(x,1.5)
到x*sqrt(x)
和pow(x,1.75)
至sqrt(x*x*x*sqrt(x))
这大大提高了程序的运行速度。
一些幂是pow(x,1.0/3.0)
类型的,所以我寻找了立方根函数cbrt()
来加快速度,但它似乎在Visual Studio中不可用,我很难想象,所以我的问题是:
在Visual Studio 2012 Professional中,我在哪里可以找到cbrt()
函数?如果没有,除了pow(x,1.0/3.0)
之外,还有哪些替代品?
谨致问候,
恩斯特·扬
3条答案
按热度按时间7cjasjjr1#
This site探索了几种在C中有效计算立方根的计算方法,并提供了一些源代码供您下载。
(编辑:在谷歌上搜索“快速立方根”,会出现几个看起来很有希望的结果。)
立方根是一个有趣的主题,因为它们在许多常见的公式中使用,而Microsoft Visual Studio中没有快速的立方根函数。
在没有特殊的立方根函数的情况下,一个典型的策略是通过幂函数(例如,pow(x,1.0/3.0))进行计算。这在速度方面可能存在问题,并且在负数处理不当时,在准确性方面可能存在问题。
他的网站上有一些关于所用方法的基准测试,它们都比
pow()
快得多。字符串
请参阅网站下载源。
g6ll5ycj2#
下面的实现比AVX-512 CPU上的std::pow快4倍,具有相对较高的容差(0.000001)。它由垂直自动向量化循环组成,用于每个基本操作,如乘法和除法,以便它一次计算8,16,32个元素,而不是水平向量化Newton-Raphson循环。
字符串
它只在GCC上测试,所以它可能需要在每个循环上使用额外的MSVC-pragmas来强制自动向量化。如果你有OpenMP,那么你也可以使用
#pragma omp simd safelen(Simd)
来实现同样的事情。性能仅在[0,1]范围内保持。要使用更大的值,您应该像这样使用范围缩小:
型
如果你只需要在低范围(如[0,1000])上有0.005的错误,并具有16倍的加速,你可以尝试下面使用多项式近似的实现(Horner Scheme应用于使用FMA指令进行计算,并且不需要显式的自动向量化,因为它不包括任何分支/循环):
型
e0bqpujr3#
MSC 2012一定是他们的最后一个版本,没有在math.h中实现cbrt。MS系统cbrt基准测试非常糟糕,但在真实的代码中并不差。尽管它不是最准确的。
我发现在大多数编译器上既准确又快速的cbrt公共代码的最佳组合是布鲁斯埃文斯的Kahan的魔术常数算法的Sun's implementation。英特尔在他们的2023编译器中的系统cbrt通过在最终改进中小心使用截断和FMA而令人难以置信地准确。
如果没有更好的选择,一个简单的选择是:
字符串
根据CPU架构的不同,这两种方法都值得一试。