我继承了一个可能效率低下的Visual Studio / VB.Net数值模拟项目。分析表明该函数被称为批量(100万次加),并且在该函数中花费了整个计算的约50%。这是有问题的部分
结果=(A *(E ^ C))/(D ^ C * B)(其中A-C是局部双变量和D& E全局双变量)
然后将结果与可能还有其他改进的阈值进行比较,但我会在另一天留下它们
任何想法或帮助将不胜感激
史蒂夫
答案 0 :(得分:1)
一个简单的加速就是
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();
}
这是输出
slow: 26062 result: 7.077390271736578E-272
fast: 12661 result: 7.077392136525382E-272
数字有一些偏差。我认为更快的版本更精确(但这只是一种感觉,因为我无法想到原因)。
答案 1 :(得分:1)
指数运算符(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
我使用StopWatch类计时,它与原始表达式一样快。当然不是巧合。通过某种方式能够预先计算Math.Log(e) - Math.Log(d)项,你将获得成功。
答案 2 :(得分:0)
为分析做得好。我还会在每次通话时检查A-C是否不同。换句话说,调用者是否可能一次又一次地计算相同的值?如果是这样,请更改它以便缓存答案。
答案 3 :(得分:0)
对于Math.Floor()函数,请访问: http://bitsbyta.blogspot.com/2010/12/math-floor-function-vbnet.html
vb.net中数学库的所有功能均可在以下位置获得: http://www.bitsbyta.blogspot.com/