Así que escribí un código numérico en C pero quería llamarlo desde F #. Sin embargo, funciona increíblemente lento.¿Por qué llamar mi código C desde F # es muy lento (en comparación con el nativo)?
tiempos:
- gcc -O3: 4 segundos
- gcc -O0: 30 segundo
- código FSharp que llama al código gcc optimizada: 2 minutos 30 segundos.
Como referencia, el código C es
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;
}
Salí a cabo la ejecución de las funciones. El F # código que estoy utilizando es
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])
el código F # se compila con optimizaciones sucesivamente.
¿La interfaz mono para llamar al código C es realmente tan lenta (casi 8ms de sobrecarga por llamada de función) o solo estoy haciendo algo estúpido?
¿Probó el código en Windows? Podrían ser muchas cosas – leppie
A un lado: en F # 'float' significa realmente' double' que es de 8 bytes. En C, generalmente 'float' tiene 4 bytes. Puede tener una coincidencia de firma pinvoke allí. – JaredPar
@JaredPar: esa fue la respuesta, sospecho que la conversión flotante hizo que los parámetros cambiaran a unos que causaron una ejecución mucho más lenta. El tiempo de ejecución de F # ahora es prácticamente idéntico al de la C. Existe alguna forma de verificar estas discrepancias de firmas? –