2012-03-14 101 views
6

所以我寫了一些數字代碼在C,但想從F#調用它。然而它運行得非常慢。爲什麼從F#調用我的C代碼非常慢(與本機相比)?

時報:

  • GCC -O3:4秒
  • GCC -O0:30秒
  • fsharp代碼調用優化GCC代碼:2分30秒。

作爲參考,C代碼是

int main(int argc, char** argv) 
{ 
    setvals(100,100,15,20.0,0.0504); 
    float* dmats = malloc(sizeof(float) * factor*factor); 
    MakeDmat(1.4,-1.92,dmats); //dmat appears to be correct 
    float* arr1 = malloc(sizeof(float)*xsize*ysize); 
    float* arr2 = malloc(sizeof(float)*xsize*ysize); 
    randinit(arr1); 
    for (int i = 0;i < 10000;i++) 
    { 
      evolve(arr1,arr2,dmats); 
      evolve(arr2,arr1,dmats); 
      if (i==9999) {print(arr1,xsize,ysize);}; 
    } 
    return 0; 
} 

我離開了的功能的實現。我正在使用的F#代碼是

open System.Runtime.InteropServices 
open Microsoft.FSharp.NativeInterop 

[<DllImport("a.dll")>] extern void main (int argc, char* argv) 
[<DllImport("a.dll")>] extern void setvals (int _xsize, int _ysize, int _distlimit,float _tau,float _Iex) 
[<DllImport("a.dll")>] extern void MakeDmat(float We,float Wi, float*arr) 
[<DllImport("a.dll")>] extern void randinit(float* arr) 
[<DllImport("a.dll")>] extern void print(float* arr) 
[<DllImport("a.dll")>] extern void evolve (float* input, float* output,float* connections) 

let dlimit,xsize,ysize = 15,100,100 
let factor = (2*dlimit)+1 
setvals(xsize,ysize,dlimit,20.0,0.0504) 
let dmat = Array.zeroCreate (factor*factor) 
MakeDmat(1.4,-1.92,&&dmat.[0]) 

let arr1 = Array.zeroCreate (xsize*ysize) 
let arr2 = Array.zeroCreate (xsize*ysize) 
let addr1 = &&arr1.[0] 
let addr2 = &&arr2.[0] 
let dmataddr = &&dmat.[0] 
randinit(&&dmat.[0]) 
[0..10000] |> List.iter (fun _ -> 
    evolve(addr1,addr2,dmataddr) 
    evolve(addr2,addr1,dmataddr) 
     ) 

print(&&arr1.[0]) 

F#代碼是在優化上編譯的。

調用C代碼的單一接口真的很慢(每個函數調用的開銷幾乎爲8ms)還是我只是在做一些愚蠢的事情?

+1

測試在Windows的代碼?可能是很多事情。 – leppie 2012-03-14 05:18:33

+7

另外:在F#中,'float'的意思是'double',它是8個字節。在C中,通常'float'是4個字節。您可能會遇到一個嚴重的簽名不匹配問題。 – JaredPar 2012-03-14 05:18:51

+1

@JaredPar - 這就是答案,我懷疑浮點數轉換會導致參數被更改爲導致執行速度更慢的參數。 F#的運行時間現在幾乎與普通的C相同。是否有一些方法來檢查這些簽名不匹配? – 2012-03-14 05:29:31

回答

11

看起來是問題的一部分是,你正在使用的F#和PInvoke的簽名的C面都float。在F#float實際上是System.Double,因此是8個字節。在C a float通常是4個字節。

如果是這樣的CLR下運行我希望你看到的PInvoke在調試過程中堆棧不平衡錯誤。我不確定莫諾是否有類似的檢查。但這可能與您看到的問題有關。

相關問題