Why is C # code from F # very slow (compared to native)?

So, I wrote some numerical code in C, but wanted to call it from F #. However, it works incredibly slowly.

Time:

  • gcc -O3: 4 seconds
  • gcc -O0: 30 seconds
  • The fsharp code that invokes the optimized gcc code: 2 minutes 30 seconds.

For reference, code 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; } 

I did not consider the implementation of functions. The F # code I'm using is

 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 # code compiled with optimization.

Is the mono interface for calling C code really slow (almost 8 ms of overhead for calling a function), or am I just doing something stupid?

+6
source share
1 answer

It seems like part of the problem is that you are using float on the F # and C side of the PInvoke signature. In F # float really System.Double and therefore 8 bytes. In a float usually 4 bytes.

If it was running in the CLR, I expect that during debugging you will see an unbalanced PInvoke stack error. I'm not sure Mono has similar checks or not. But perhaps this is due to the problem you are seeing.

+11
source

Source: https://habr.com/ru/post/910662/


All Articles