cudafy - Coding CUDA con C#?




alea gpu (5)

Ho cercato alcune informazioni sulla codifica di CUDA (il linguaggio nvidia gpu) con C #. Ho visto alcune delle librerie, ma sembra che aggiungano un po 'di overhead (a causa del p / invokes, ecc.).

  • Come dovrei usare CUDA nelle mie applicazioni C #? Sarebbe meglio codificarlo in C ++ e compilarlo in una DLL?
  • Questo sovraccarico dell'utilizzo di un wrapper avrebbe eliminato tutti i vantaggi che avrei tratto dall'uso di CUDA?
  • E ci sono dei buoni esempi di utilizzo di CUDA con C #?

Answers

Ci sono diverse alternative che puoi usare per usare CUDA nelle tue applicazioni C #.

  • Scrivi una libreria C ++ / CUDA in un progetto separato e usa P / Invoke. Il sovraccarico di P / invoca le chiamate native sarà probabilmente trascurabile.
  • Utilizzare un wrapper CUDA come ManagedCuda (che espone l'intera API CUDA). Non dovrai scrivere manualmente le tue DLLImport per l'intera API di runtime CUDA (che è conveniente). Sfortunatamente, dovrai ancora scrivere il tuo codice CUDA in un progetto separato.
  • ( consigliato ) È possibile utilizzare compilatori gratuiti / opensource / proprietari (che generano cuda (sorgente o binario) dal codice c #.

Puoi trovarne diversi online: dai un'occhiata a questa risposta per esempio.


Immagino che sia utile menzionare Hybridizer, spiegato here come post di blog su Nvidia. Here il relativo repo GitHub sembra.


C'è un wrapper Cuda 4.2 così completo come ManagedCuda. Semplicemente aggiungi il progetto c ++ cuda alla tua soluzione, che contiene il tuo progetto c #, quindi aggiungi

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"

per postare gli eventi nelle proprietà del progetto c #, compila il file * .ptx e lo copia nella directory di output del progetto c #.

Quindi è sufficiente creare un nuovo contesto, caricare il modulo dal file, caricare la funzione e lavorare con il dispositivo.

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

Questo è stato commentato sulla lista nvidia in passato:

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

sarebbe facile usare P / Invoke per usarlo in assiemi come questi:

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

È possibile aggiungere le DLL come risorse incorporate e quindi fare in modo che il programma venga decompresso nella directory dell'applicazione all'avvio (dopo aver verificato se sono già presenti).

I file di installazione sono così semplici da rendere, comunque, che non penso che ne varrebbe la pena.

EDIT: questa tecnica sarebbe facile con assiemi .NET. Con DLL non- .NET sarebbe molto più lavoro (dovresti capire dove decomprimere i file e registrarli e così via).





c# cuda