【问题标题】:Code optimisation of math.asin function vb.netmath.asin函数vb.net的代码优化
【发布时间】:2013-05-20 08:45:40
【问题描述】:

我有以下代码行:

SomeDouble= constant1/ ((a * b) * (Math.Asin((c- a) / (a * d)) + constant2))

这两个常数是不同的,是在循环之外计算出来的,a - d是每次都会变化的变量。

从表面上看,它的平均速度相当快 0.002 毫秒(26,508,249 次点击为 47,633.588 秒)。我遇到的问题是它会被调用数十亿次,每次运行软件时都会有大约 200 亿次点击。因此,如果我可以将其减少到 0.001 毫秒,那么差异将是巨大的。我知道除法是一个非常缓慢的过程,我希望计算 arcsin 也很慢。如果有人可以建议是否有更快的计算 arcsin 的方法或任何其他有助于加快这行代码的速度,那就太好了。附带说明一下,关于 vb.net 的内置数学函数是否针对速度进行了优化的任何建议都会很棒我注意到 math.sqrt(somevalue) 比 (somevalue)^0.5 更快。

提前致谢!

【问题讨论】:

  • 你需要多少精度?
  • 好问题。精度越高越好。话虽这么说,如果有一种方法可以以牺牲准确性为代价提高速度,我绝对希望听到它,以便我可以考虑。我没有专门研究这个变量所需的精度(somedouble)。我在代码的后面确实有一些精度要求,我现在会去看看这里失去精度的代价是什么。
  • 计算之间是否有任何变量保持不变?还是以可预测的方式发生变化?
  • 很遗憾没有。每个变量与其在任何其他迭代中的对应变量完全无关。
  • a、b、c 和 d 的取值范围是否存在界限?

标签: vb.net math optimization


【解决方案1】:

我会做一些测试以确保 Math.Asin 确实是公式中最慢的部分。如果它相对于其他乘法和除法真的很慢,那么您可以尝试为 Math.Asin 实现自己的查找表。换句话说,预先计算数百万个 Math.Asin 值,并将它们编码到您的程序中。这会以你的程序大小换取速度,所以如果程序大小无关紧要,它可能会有所帮助。

【讨论】:

    【解决方案2】:

    您可以对Asin 使用以下近似值,在我的测试中,它的速度几乎是Math.Asin 的两倍(32 位,如果手动内联更好,在 64 位下它比两倍快),看起来相当准确,但您必须测试准确性是否可以接受。

    static double Asin(double x)
    {
        double x2 = x * x;
        double x3 = x2 * x;
        const double piover2 = 1.5707963267948966;
        const double a = 1.5707288;
        const double b = -0.2121144;
        const double c = 0.0742610;
        const double d = -0.0187293;
        return piover2 - Math.Sqrt(1 - x) * (a + b * x + c * x2 + d * x3);[]
    
    
    }
    

    (这当然是 C#,但我敢肯定你可以转换它)

    [编辑] 这是VB版本。

    Shared Function Asin(ByVal x As Double) As Double
        Dim x2 As Double = x * x
        Dim x3 As Double = x2 * x
        Const piover2 As Double = 1.5707963267948966
        Const a As Double = 1.5707288
        Const b As Double = -0.2121144
        Const c As Double = 0.0742610
        Const d As Double = -0.0187293
        Return piover2 - Math.Sqrt(1 - x) * (a + b * x + c * x2 + d * x3)
    End Function
    

    【讨论】:

    • 这些系数是如何得出的?
    • @EricPostpischil 我不知道,我只是在某个地方找到了它们,不过它们在我的测试中运行良好
    【解决方案3】:

    您可以尝试将series expansion 实现为您需要的任何精度,并将其与随机建议的查找表(很可能是Math.asin 最终计算它的方式)进行比较,以建立所需的精度。但是,您似乎不太可能享受将处理时间减半的情况。

    如果计算没有有意义地相互依赖(或者如果依赖关系可以隔离到不同的批次中),您可以尝试并行运行它们(无论是在不同的系统上还是使用不同的处理器),但要小心 - - 我在一个空间物理实验室工作,我们发现当我们在不同的系统上运行测试时,我们需要的精度会产生真的恼人的异常情况。

    (我还必须说,我非常好奇为什么需要运行数十亿次反正弦计算。)

    【讨论】:

    • 为了回答你的好奇心,我正在模拟许多物体随时间移动的进程。由于这是基于概率的(至少出于我的目的),我运行了 100 次蒙特卡罗模拟。每个模拟有大约 20k 个对象和大约 20k 个步骤。所以 20k*20k*100 = 40,000,000,000... 我已经将所有数字四舍五入了一点,但你明白了。 :) 感谢您提供的信息,我会尽快查看 :)
    • Wolfram Alpha 提供的级数展开对于在一个区间内逼近函数来说是很糟糕的。它们仅用于分析目的(研究函数的属性、协助某些证明、教学生等等)。函数逼近应该使用极小极大多项式或类似的东西。
    猜你喜欢
    • 1970-01-01
    • 2019-09-09
    • 2017-05-20
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多