2012-03-14 24 views
6

Vì vậy, tôi đã viết một số mã số trong C nhưng muốn gọi nó từ F #. Tuy nhiên nó chạy rất chậm.Tại sao gọi mã C của tôi từ F # rất chậm (so với bản địa)?

Times:

  • gcc-O3: 4 giây
  • gcc -O0: 30 giây
  • đang fsharp trong đó kêu gọi các mã gcc tối ưu hóa: 2 phút 30 giây.

Để tham khảo, các mã c là

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; 
} 

tôi rời ra việc thực hiện các chức năng. Mã F # tôi đang sử dụng là

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]) 

Mã F # được biên dịch với tối ưu hóa.

Giao diện mono để gọi mã C thực sự là chậm (gần 8ms trên đầu cho mỗi cuộc gọi hàm) hay tôi chỉ làm điều gì đó ngu ngốc?

+1

Đã kiểm tra mã trên Windows? Có thể là nhiều thứ. – leppie

+7

Bên cạnh: Trong F # 'float' thực sự có nghĩa là' double' là 8 byte. Trong C thường 'float' là 4 byte. Bạn có thể có một chữ ký pinvoke không khớp ở đó. – JaredPar

+1

@ JaredPar - đó là câu trả lời, tôi nghi ngờ chuyển đổi phao khiến các thông số được thay đổi thành các thông số gây ra thực thi chậm hơn nhiều. Thời gian chạy F # bây giờ hầu như giống hệt C. Bạn có cách nào để kiểm tra những sự không khớp chữ ký này không? –

Trả lời

11

Có vẻ như một phần của sự cố là bạn đang sử dụng float trên cả mặt F # và C của chữ ký PInvoke. Trong F # float thực sự là System.Double và do đó là 8 byte. Trong C a float thường là 4 byte.

Nếu điều này đang chạy trong CLR, tôi mong bạn sẽ thấy một lỗi PInvoke stack không cân bằng trong khi gỡ lỗi. Tôi không chắc liệu Mono có kiểm tra tương tự hay không. Nhưng có thể điều này liên quan đến vấn đề bạn đang gặp phải.

Các vấn đề liên quan