Vb.net 优化除法/指数计算

Vb.net 优化除法/指数计算,vb.net,optimization,math,Vb.net,Optimization,Math,我继承了一个Visual Studio/VB.Net数值模拟项目,该项目的计算效率可能很低。分析表明该函数调用了很多次(超过100万次),并且在该函数中花费了大约50%的总计算量。这里是有问题的部分 结果=(A*(E^C))/(D^C*B)(其中A-C为局部双变量,D&E为全局双变量) 然后将结果与阈值进行比较,阈值可能也会有额外的改进,但我会在另一天再讨论 如有任何想法或帮助,将不胜感激 史蒂夫一个简单的加速是 Result = (A/B) * (E/D)^C 至少你少做了一件事。 根据C是

我继承了一个Visual Studio/VB.Net数值模拟项目,该项目的计算效率可能很低。分析表明该函数调用了很多次(超过100万次),并且在该函数中花费了大约50%的总计算量。这里是有问题的部分

结果=(A*(E^C))/(D^C*B)(其中A-C为局部双变量,D&E为全局双变量)

然后将结果与阈值进行比较,阈值可能也会有额外的改进,但我会在另一天再讨论

如有任何想法或帮助,将不胜感激


史蒂夫

一个简单的加速是

Result = (A/B) * (E/D)^C
至少你少做了一件事。 根据C是什么,可能有更快的方法。比如C是一个小整数

编辑: 添加证据以证明这一点更快

    public static void main(String[] args) {
    StopWatch sw = new StopWatch();

    float e = 1.123F;
    float d = 4.456F;
    float c = 453;
    sw.start();
    int max = 5000;
    double result = 0;
    for (int a = 1; a < max; a++) {
        for (float b = 1; b < max; b++) {
            result = (a * (Math.pow(e, c))) / (Math.pow(d, c) * b);
        }
    }
    sw.split();
    System.out.println("slow: " + sw.getSplitTime() + " result: " + result);
    sw.stop();
    sw.reset();

    sw.start();
    result = 0;
    for (int a = 1; a < max; a++) {
        for (float b = 1; b < max; b++) {
            result = a / b * Math.pow(e/d, c);
        }
    }

    sw.split();
    System.out.println("fast: " + sw.getSplitTime() + " result: " + result);
    sw.stop();
    sw.reset();
}
这些数字有些偏差。我认为更快的版本更精确(但这只是一种感觉,因为我想不出确切的原因)。

指数运算符(Math.Pow)不是很快,没有专门的CPU指令来计算它。你提到D和E是全局变量。如果你能将他们的变化隔离开来,那么这就为加快速度带来了一线希望。使用对数重写方程式:

log(r) = log((a x e^c) / (b x d^c))
       = log(a x e^c) - log (b x d^c)
       = log(a) + log(e^c) - log(b) - log(d^c)
       = log(a) + c*log(e) - log(b) - c*log(d)
       = log(a) - log(b) + c x (log(e) - log(d))
result = exp(r)
它提供此函数来计算结果:

  Function calculate(ByVal a As Double, ByVal b As Double, ByVal c As Double, ByVal d As Double, ByVal e As Double) As Double
    Dim logRes = Math.Log(a) - Math.Log(b) + c * (Math.Log(e) - Math.Log(d))
    Return Math.Exp(logRes)
  End Function

我在秒表课上计时,它和你最初的表情一样快。当然不是巧合。通过某种方式预先计算Math.Log(e)-Math.Log(d)项,您将获得成功。

评测做得很好。我还要检查A-C在每次通话中是否不同。换句话说,调用方是否可能一次又一次地计算相同的值?如果是,请将其更改为缓存答案。

有关Math.Floor()函数,请访问:

vb.net中数学库的所有功能可在以下位置获得:

+1询问“global”之前的评测,您是否暗示他们永远不会改变?您可以设置“F=E/D”一次,然后执行F^C而不是下面我的答案中提到的“(E/D)^C”。
  Function calculate(ByVal a As Double, ByVal b As Double, ByVal c As Double, ByVal d As Double, ByVal e As Double) As Double
    Dim logRes = Math.Log(a) - Math.Log(b) + c * (Math.Log(e) - Math.Log(d))
    Return Math.Exp(logRes)
  End Function