6
私はCでいくつかの数値コードを書いたが、F#からそれを呼びたいと思った。しかし、それは信じられないほどゆっくりと実行されます。私のCコードをF#から呼び出すのがなぜ(ネイティブと比べて)非常に遅いのですか?
時間:
- GCC -03:4秒
- GCC -O0:2分30秒:最適化されたGCCコードを呼び出し、30秒
- fsharpコード。私は機能の実装を残し
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; }
は参考のために、Cコードです。私が使用している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コードを呼び出すためのモノラルインターフェイスは本当に遅いです(関数呼び出しごとにオーバーヘッドがほぼ8ミリ秒)か、何かばかげているだけですか?
Windowsでコードをテストしましたか?多くのことができます。 – leppie
脇に:F#で 'float'は実際には8バイトの' double'を意味します。 Cでは、通常、 'float'は4バイトです。そこにピンボークのシグネチャの不一致があります。 – JaredPar
@ JaredPar - それは答えでした。私は、浮動小数点数の変換によってパラメータが非常に遅い実行を引き起こしたものに変更されたと思われます。 F#ランタイムは現在、Cとほぼ同じです。これらのシグネチャのミスマッチをチェックする方法はありますか? –