2011-06-25 7 views
51

J'ai cherché des informations sur le codage CUDA (la langue nvidia gpu) avec C#. J'ai vu quelques-unes des bibliothèques, mais il semble qu'elles ajouteraient un peu de surcharge (à cause des p/invoke, etc.).Codage CUDA avec C#?

  • Comment utiliser CUDA dans mes applications C#? Serait-il préférable de le coder en C++ et de le compiler en dll?
  • Est-ce que cette surcharge d'utilisation d'un wrapper tuerait les avantages que j'obtiendrais de l'utilisation de CUDA?
  • Et y a-t-il de bons exemples d'utilisation de CUDA avec C#?

Répondre

39

Il y a un emballage cuda 4.2 aussi complet que ManagedCuda. Vous ajoutez simplement projet cuda C++ à votre solution, la vôtre contient C# projet, vous venez d'ajouter

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-construire des événements dans votre C# propriétés du projet, ce compile fichier * .ptx et la copie dans votre C# répertoire de sortie du projet.

Ensuite, il vous suffit de créer un nouveau contexte, de charger le module à partir du fichier, de charger la fonction et de travailler avec le périphérique.

//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

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

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

il serait facile à utiliser P/Invoke pour l'utiliser dans les assemblées comme ceci:

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

supprimé le lien. il n'y a pas besoin de montrer un mort lien plus loin. serait très gentil si vous supprimez votre commentaire. Les gens pourraient être irrités de cela. –

+0

Je ne savais pas que vous pouviez simplement invoquer les appels CUDA. Dommage que vous avez besoin d'acheter dans NVidia pour que cela fonctionne. –

2

Il existe plusieurs alternatives que vous pouvez utiliser pour utiliser CUDA dans vos applications C#. Ecrivez une bibliothèque C++/CUDA dans un projet séparé et utilisez P/Invoke.

  • Le surcoût de P/invoque les appels natifs sera probablement négligeable.
  • Utilisez un wrapper CUDA tel que ManagedCuda (qui affichera l'intégralité de l'API CUDA). Vous n'aurez pas à écrire manuellement vos DLLImports pour l'ensemble 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 les compilateurs libres/opensource/propriétaires (qui va générer cuda (soit la source ou binaire) à partir de votre code C#

Vous pouvez trouver plusieurs d'entre eux en ligne:. Un coup d'oeil à this answer par exemple.

2

Je suppose que hybrideur, a expliqué here comme un billet de blog sur Nvidia est également intéressant de mentionner. Here est son GitHub lié repo il semble.