2010-04-15 84 views
2

我已經繼承了Visual Studio/VB.Net數值模擬項目,其計算可能效率低下。分析表明該函數被稱爲很多(100萬次以上),並且在該函數中花費了總體計算的大約50%。下面是有問題的部分優化劃分/指數計算

結果=(A *(E^C))/(d^C * B)(其中,AC是局部雙變量和d &Ë全局雙變量)

結果然後相比可能有更多的改進以及閾值,但我會離開他們的一天

任何想法或幫助將不勝感激

史蒂夫

+0

+1用於分析由 「全球」 問 – 2010-04-15 20:02:59

+1

之前你暗示他們從不改變?你可能可以設置「F = E/D」一次,然後按照下面我的回答中所提到的做F^C而不是「(E/D)^ C」。 – mlathe 2010-04-15 20:12:09

回答

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

指數運算符(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)項。

0

做好分析。我也會在每次通話時檢查A-C是不同的。換句話說,有可能調用者實際上一遍又一遍地計算相同的值嗎?如果是這樣,請更改它以緩存答案。