2011-06-25 31 views
51

Szukałem informacji o kodowaniu CUDA (język nvidia gpu) z C#. Widziałem kilka bibliotek, ale wydaje się, że dodadzą trochę narzutów (z powodu p/invokes, itp.).Kodowanie CUDA za pomocą C#?

  • Jak powinienem używać CUDA w aplikacjach C#? Czy byłoby lepiej napisać kod w C++ i skompilować go do biblioteki dll?
  • Czy to obciążenie związane z używaniem wrappera zabiłoby wszelkie korzyści, jakie uzyskałbym dzięki CUDA?
  • A czy są jakieś dobre przykłady używania CUDA z C#?

Odpowiedz

39

Istnieje takie ładne opakowanie pełne cuda 4.2 jako ManagedCuda. Wystarczy dodać projekt cuda C++ do roztworu, który zawiera twoje C# projektu, a następnie po prostu dodać

call "%VS100COMNTOOLS%vsvars32.bat" 
for /f %%a IN ('dir /b "$(ProjectDir)Kernels\*.cu"') do nvcc -ptx -arch sm_21 -m 64 -o "$(ProjectDir)bin\Debug\%%~na_64.ptx" "$(ProjectDir)Kernels\%%~na.cu" 
for /f %%a IN ('dir /b "$(ProjectDir)Kernels\*.cu"') do nvcc -ptx -arch sm_21 -m 32 -o "$(ProjectDir)bin\Debug\%%~na.ptx" "$(ProjectDir)Kernels\%%~na.cu" 

odpowiedzieć-zbudować wydarzenia w C# właściwości projektu, to kompiluje * .ptx plik i kopie go w C# katalog wyjściowy projektu.

Następnie wystarczy utworzyć nowy kontekst, załadować moduł z pliku, wczytać funkcję i pracować z urządzeniem.

//NewContext creation 
CudaContext cntxt = new CudaContext(); 

//Module loading from precompiled .ptx in a project output folder 
CUmodule cumodule = cntxt.LoadModule("kernel.ptx"); 

//_Z9addKernelPf - function name, can be found in *.ptx file 
CudaKernel addWithCuda = new CudaKernel("_Z9addKernelPf", cumodule, cntxt); 

//Create device array for data 
CudaDeviceVariable<cData2> vec1_device = new CudaDeviceVariable<cData2>(num);    

//Create arrays with data 
cData2[] vec1 = new cData2[num]; 

//Copy data to device 
vec1_device.CopyToDevice(vec1); 

//Set grid and block dimensions      
addWithCuda.GridDimensions = new dim3(8, 1, 1); 
addWithCuda.BlockDimensions = new dim3(512, 1, 1); 

//Run the kernel 
addWithCuda.Run(
    vec1_device.DevicePointer, 
    vec2_device.DevicePointer, 
    vec3_device.DevicePointer); 

//Copy data from device 
vec1_device.CopyToHost(vec1); 
11

Zostało skomentował listy nvidia w przeszłości:

http://forums.nvidia.com/index.php?showtopic=97729

byłoby łatwe w użyciu P/Invoke go używać w złożeniach tak:

[DllImport("nvcuda")] 
    public static extern CUResult cuMemAlloc(ref CUdeviceptr dptr, uint bytesize); 
+1

usunięto link. nie ma potrzeby, aby pokazać martwy link dalej byłby bardzo uprzejmy, jeśli usuniesz swój komentarz. Ludzie mogliby zostać wyalienowani z tego. –

+0

Nie zdawałem sobie sprawy, że można po prostu wywołać połączenia CUDA. Szkoda, że ​​musisz kupić NVidię, żeby to zadziałało. –

2

Istnieje kilka alternatyw, których można użyć do korzystania z CUDA w aplikacjach C#.

  • Napisz bibliotekę C++/CUDA w oddzielnym projekcie i użyj P/Invoke. Narzut P/invokes na połączenia natywne będzie prawdopodobnie znikomy.
  • Użyj opakowania CUDA, takiego jak ManagedCuda (które spowoduje odsłonięcie całego interfejsu API CUDA). Nie będziesz musiał ręcznie pisać swoich DLLImportów dla całego API środowiska wykonawczego CUDA (co jest wygodne). Niestety, będziesz nadal musiał napisać swój własny kod CUDA w osobnym projekcie.
  • (zaleca) Można wykorzystać wolny/opensource/zastrzeżonych kompilatory (która będzie generować CUDA (zarówno źródła lub binarny) od C# kodu

Można znaleźć kilka z nich w trybie online. Mają wyglądać w this answer np.

2

Chyba Hybridizer wyjaśnił here jak blogu na Nvidia warto również wspomnieć. Here jest powiązane z GitHub repo wydaje.

Powiązane problemy