2014-09-29 93 views
0

我正在寫一些代碼作爲非線性迴歸工具的一部分,我試圖找出一種方法來返回給定函數的第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 
+0

有,你可以轉換爲常數,這可能有助於一些公共子 - 例如'b * c * x'。如果您知道某些參數總是大或小,則可能會以犧牲準確性爲代價簡化某些表達式。另外,如果你可以接受精確度懲罰,float32比float更快。 – 2014-09-29 22:09:39

+0

@JohnPalmer我確定我讀過float32通常比float更慢的原因,因爲計算實際上是在FPU中以相同的精度完成的,但對於float32,在截斷值時有更多的舍入操作。 – phoog 2014-09-29 22:27:59

+0

Profiler實際上是否表示速度增加是由於乘法的數量減少?檢查你的GC統計數據 - 這使我更有可能獲得改進的性能。 – phoog 2014-09-29 22:49:59

回答

1

匿名函數導致性能問題的最可能的原因是每次調用getPartials函數時都會創建一個新的堆對象。如果您只有少數不同的paramVect s,那麼您可能通過緩存匿名函數獲得一些性能優勢。

至於第二個表達式的值,你可以試試這個(以約翰·帕爾默的建議,以消除常見的子表達式):

fun x -> let bcx = b * c * x 
      let bcx1 = bcx + 1.0 
      a * bcx1 ** (-(b+1.0)/b) * (bcx1 * Math.Log bcx1 - bcx)/(b*b) 
+0

感謝您的回覆。我對OP進行了一些更改,以反映我嘗試過的一些新更改(符合您的&JohnPalmers建議)。拋棄匿名函數最終將事情推上了很多倍。ParamVector改變了數千次,所以我無法緩存它。 – NMR 2014-09-29 22:51:44