![](/img/trans.png)
[英]Android Preferences: Is it possible to optimize OnPreferenceChangeListener?
[英]Is it possible to optimize this function?
經過剖析后,我發現這種方法占用了大部分計算時間。 我真的沒有看到優化的方法,因為它是一個可怕的功能。 (它是......)也許有人能給我一些好主意嗎?
public static double perceivedLoudness(double L_G, double L_ETQ, double a0) {
double t1 = 1d + 1 / 4d * Math.pow(10d, 0.1d * (L_G - a0 - L_ETQ));
double t2 = Math.pow(t1, 0.25);
return 0.064d * Math.pow(10, 0.025 * L_ETQ) * (t2 - 1);
}
這是改進版本:
public static double perceivedLoudness(double L_G, double L_ETQ, double a0) {
double x = L_G - a0 - L_ETQ;
double t1 = 0.25 * Math.exp(0.230259 * x) + 1;
double t2 = Math.sqrt(Math.sqrt(t1));
return ltqFactors[(int)L_ETQ] * (t2 - 1);
}
對ltqFactors的查找就是這樣的。 ltqValues從給定的ltq函數中保持20個點,大約應該是足夠的。
for( int i = 0; i < etqValues.length; ++i) {
ltqFactors[(int)etqValues[i]] = 0.064d * Math.exp(etqValues[i] * 0.05756462732485114210d);
}
編輯:經過更多文件的測試運行后,我加速了~100%:
謝謝你到目前為止!
Edit2:我不知道接受哪個答案。 :(與其他一些改進(主要是查找表)9000聲音文件的處理時間從4:30min下降到3:28min。
我將保持這個問題,看看是否有其他想法,但接受一個答案。
編輯:我現在有點沮喪。 我使用JFace treeviewer讓用戶瀏覽結果,它需要更多的時間來更新計算本身。 :/
你的函數似乎是解析的,我建議用插值方法完全替換它。 這樣,您就可以Math.Pow
的昂貴調用減少到幾個算術運算。
在這種情況下,最好的應該是有理函數逼近。 你的函數可能在復平面上有極點,這通常會使多項式插值失效。
請注意,您有兩個變量: L_G - a0 - L_ETQ
和L_ETQ
。 插值應僅在一個變量中執行。
我將t2
有理函數逼近作為L_G - a0 - L_ETQ
。 看一下Numerical Recipes的實現技巧。
另外,對於最后一部分,替換
Math.pow(10, 0.025 * L_ETQ);
通過
Math.exp(L_ETQ * 0.05756462732485114210d)
(為exp(L_ETQ * 0.025 * log(10))
)。
所以你應該對一些算術運算和指數運算很好。
編輯: 查看t2
的圖表作為L_G - a0 - L_ETQ
。
編輯:替換
double t1 = 1d + 1 / 4d * Math.pow(10d, 0.1d * (L_G - a0 - L_ETQ));
double t2 = Math.pow(t1, 0.25);
通過
double x = L_G - a0 - L_ETQ;
double t1 = 0.25 * Math.exp(0.230259 * x) + 1;
double t2 = Math.sqrt(Math.sqrt(t1));
而你應該獲得更多%。 在這一點上,理性近似可能是過度工程:你有兩個exp,兩個sqrt。
數學並不會立即看起來像是可以重新排序以避免任何重復計算,因此采用的方法取決於此函數的使用方式以及所需的准確結果。
最好的方法是避免重新計算同一組輸入值的值。 您的代碼可以保存相同輸入值的計算結果嗎? 如果沒有,你可以有一個值的緩存,但要注意雙打可以有很多值,你可能想要將雙打折疊成一個已知的間隔(例如從0到1折疊成0到99之間的整數)。
我猜
double t2 = Math.sqrt(Math.sqrt(t1));
比...更快
double t2 = Math.pow(t1, 0.25);
看一下你引用的那篇論文,似乎L_ETQ和a0只是聲音頻率(Bark)的函數。
因此,至少你可以得到一個表格,列出給定頻率的各種計算結果。 例如,緩存結果:
.064 * Math.pow(10, 0.025 * L_ETQ)
按頻率。 [還可以緩存(a0 + L_ETQ)* .1]
此外,可能是微小的影響,如果有的話,但我會將1/4轉換為0.25。
為程序可以處理的輸入范圍預先生成查找表。
它沒有比這更快! :)
根據輸入參數緩存輸出可能會有所幫助:
這還沒有提到,所以我會。
您可能需要考慮從浮點數學轉換為整數。 操作速度要快得多。 由於添加和存儲浮點數,圖形傾向於使用整數數學而不是浮動。 你必須要進行轉換,但我相信你會獲得相當大的性能提升。 整數數學的唯一問題是你必須定義你願意接受多少精度。
我會采取一些反對意見 ,以消除猜測。 這樣我就可以確定在其他地方沒有采取時間,比如讀取數據並將其轉換為浮點數,或打開/關閉文件。 當我確定這個例程占用了大部分時間時,我很確定它幾乎會花費所有時間來調用Math函數,並將L_ETQ轉換為整數。 有可能記住那些數學函數。 然后,正如亞歷山大所說,你可以用插值來完成所有這些工作。
問題是,你可能有不止一件事要優化。 如果這需要180秒,如果50%,比如那個時間,這個例程在堆棧上,那么如果你將時間縮短一半,你將時間減少了45秒到135秒。 但是,現在這個例程只在堆棧上持續45/135秒或1/3。 這意味着其他一些東西正在使用其他2/3或90秒,我敢打賭,你可以優化一些東西。 如果你可以將那些減少到45秒,那么總數減少到90,並且數學例程所占的百分比回升到50%,所以也許你可以從中擠出更多。 就是這樣。 每次你削減它的一部分,其他部分的百分比增加,所以你可以一遍又一遍地追逐它們,直到你真的盡可能地擠壓它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.