我正在寫一些代碼作爲非線性迴歸工具的一部分,我試圖找出一種方法來返回給定函數的第n個偏導數,快速。函數(以及部分的分析表示)在運行時是已知的,可以對它們進行硬編碼。這裏是我到目前爲止(工作):優化反覆稱爲數學函數
let getPartials (paramVect: array<float>) idx =
let a = paramVect.[0]
let b = paramVect.[1]
let c = paramVect.[2]
match idx with
| 1 -> (fun x -> (1.0+b+c*x)**(-1.0/b)) // df(x)/da
| 2 -> (fun x -> ((a*(1.0+c*b*x)**(-(b+1.0)/b))*((b*c*x+1.0)*Math.Log(b*c*x+1.0)-b*c*x))/(b*b)) // df(x)/db
| 3 -> (fun x -> -a*x*(b*c*x+1.0)**(-(b+1.0)/b)) // df/dc
| _ -> (fun x -> 0.0) //everything else is zero
我用這是先建立一個部分功能與參數向量所以,我儘量減少需要在傳遞次數的方式然後我重複地調用(getPartials(i)x_val)來構造一個jacobian。這個函數在程序的生命週期中被調用了很多次。
但是,我認爲它可以得到改善,我得到了非常可以接受的性能。分析表明,對第二功能計算(長計算)的評估是一個cpu排放 - 可以優化嗎?我不確定,如果匿名函數創建一個性能問題,爲可讀,因爲它是...
我全新到F#編程,所以請讓你發現任何egregarious問題,我知道,無論是風格/形式或表演!
謝謝
更新:落實JohnPalmer和重構建議修改完成後,不用返回其接受x值作爲參數的匿名功能,而不是做整個計算就地而言,我看到的速度大約提高了300%。能夠返回部分功能更方便,但不值得花費。
let getPartials (paramVect: array<float>) idx x =
let a = paramVect.[0]
let b = paramVect.[1]
let cbx = paramVect.[1] * paramVect.[2] * x
match idx with
| 1 -> (1.0+cbx)**(-1.0/b) // df(x)/da
| 2 -> ((a*(1.0+cbx)**(-(b+1.0)/b))*((cbx+1.0)*Math.Log(cbx+1.0)-cbx))/(b**2.0) // df(x)/db
| 3 -> -a*x*(cbx+1.0)**(-(b+1.0)/b) // df/dc
| _ -> 0.0 //everything else is zero
有,你可以轉換爲常數,這可能有助於一些公共子 - 例如'b * c * x'。如果您知道某些參數總是大或小,則可能會以犧牲準確性爲代價簡化某些表達式。另外,如果你可以接受精確度懲罰,float32比float更快。 – 2014-09-29 22:09:39
@JohnPalmer我確定我讀過float32通常比float更慢的原因,因爲計算實際上是在FPU中以相同的精度完成的,但對於float32,在截斷值時有更多的舍入操作。 – phoog 2014-09-29 22:27:59
Profiler實際上是否表示速度增加是由於乘法的數量減少?檢查你的GC統計數據 - 這使我更有可能獲得改進的性能。 – phoog 2014-09-29 22:49:59