web-dev-qa-db-fra.com

Coder CUDA avec C #?

Je cherchais des informations sur le codage de CUDA (le langage nvidia gpu) avec C #. J'ai vu quelques-unes des bibliothèques, mais il semble qu'elles ajouteraient un peu de surcharge (à cause des invocations p /, etc.).

  • Comment dois-je utiliser CUDA dans mes applications C #? Serait-il préférable de le coder en C++ par exemple et de le compiler dans une DLL?
  • Est-ce que cette surcharge d'utilisation d'un wrapper tuerait les avantages que j'obtiendrais de l'utilisation de CUDA?
  • Et existe-t-il de bons exemples d'utilisation de CUDA avec C #?
56
Ben

Il existe un tel wrapper cuda 4.2 complet comme ManagedCuda . Vous ajoutez simplement le projet C++ cuda à votre solution, qui contient le vôtre projet c #, puis vous ajoutez simplement

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"

pour post-générer des événements dans les propriétés de votre projet c #, cela compile le fichier * .ptx et le copie dans le répertoire de sortie de votre projet c #.

Ensuite, vous devez simplement créer un nouveau contexte, charger le module à partir du fichier, charger la fonction et travailler avec l'appareil.

//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);
44
Insomnious

Cela a été commenté sur la liste nvidia dans le passé:

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

il serait facile d'utiliser P/Invoke pour l'utiliser dans des assemblys comme ceci:

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

Je suppose que Hybridizer, a expliqué ici comme un article de blog sur Nvidia mérite également d'être mentionné. Ici est son référentiel GitHub apparent, semble-t-il.

5
Ebrahim Byagowi

Il existe plusieurs alternatives que vous pouvez utiliser pour utiliser CUDA dans vos applications C #.

  • Écrivez une bibliothèque C++/CUDA dans un projet distinct et utilisez P/Invoke. La surcharge de P/invoque sur les appels natifs sera probablement négligeable.
  • Utilisez un wrapper CUDA tel que ManagedCuda (qui exposera l'intégralité de l'API CUDA). Vous n'aurez pas à écrire vos DLLImports à la main pour l'intégralité de l'API d'exécution CUDA (ce qui est pratique). Malheureusement, vous devrez toujours écrire votre propre code CUDA dans un projet distinct.
  • ( recommandé ) Vous pouvez utiliser des compilateurs gratuits/opensource/propriétaires (qui généreront des cuda (source ou binaires) à partir de votre code c #.

Vous pouvez en trouver plusieurs en ligne: jetez un œil à cette réponse par exemple.

2
Regis Portalez