2013-12-10 18 views
5

Per esempio, allocare queste seguenti punti:In CUDA, come copiare una serie di puntatori di dispositivo nella memoria del dispositivo?

float *data_1, *data_2, *data_3, *data_4; 

//Use malloc to allocate memory and fill out some data to these pointers 
...... 
//Filling complete 

float *data_d1,*data_d2,*data_d3,*data_d4; 

cudaMalloc((void **)&data_d1,size1); 
cudaMalloc((void **)&data_d2,size2); 
cudaMalloc((void **)&data_d3,size3); 
cudaMalloc((void **)&data_d4,size4); 

cudaMemcpy(data_d1,data_1,size1,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d2,data_2,size2,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d3,data_3,size3,cudaMemcpyHostToDevice); 
cudaMemcpy(data_d4,data_4,size4,cudaMemcpyHostToDevice); 

Dopo questo, devo già ottenere 4 puntatori ai dispositivi contenenti i dati esatti come puntatori ospitanti fanno. Ora mi piacerebbe memorizzare questi puntatori in una matrice di puntatori come seguendo,

float *ptrs[4]; 

ptrs[0] = data_d1; 
ptrs[1] = data_d2; 
ptrs[2] = data_d3; 
ptrs[3] = data_d4; 

ora vorrei trasferire questa array di puntatori a kernel CUDA. Tuttavia, so che dal momento che ptrs [4] è in realtà sulla memoria host, ho bisogno di allocare un nuovo puntatore sul dispositivo. Così ho fatto questo,

float **ptrs_d; 
size_t size = 4 * sizeof(float*); 
cudaMalloc((void ***)&ptrs_d,size); 
cudaMemcpy(ptrs_d,ptrs,size,cudaMemcpyHostToDevice); 

E poi invocare il kernel:

kernel_test<<<dimGrid,dimBlock>>>(ptrs_d, ...); 
//Declaration should be 
//__global__ void kernel_test(float **ptrs_d, ...); 

Nel kernel_test, caricare i dati nel seguente sintassi:

if (threadIdx.x < length_of_data_1d) 
{ 
    float element0 = (ptrs[0])[threadIdx.x]; 
} 

Compilazione va bene, ma quando il debug , dà un errore di violazione di accesso.

Forse ci sono molti errori nel mio codice. Ma voglio solo capire perché non riesco a passare i puntatori di dispositivo in questo modo e qual è il modo corretto per accedervi se è permesso in CUDA di passare una serie di puntatori di dispositivo alla funzione del kernel.

Quindi, come posso risolvere questo problema? Qualsiasi suggerimento è apprezzato. Grazie in anticipo.

+2

Non vedo alcun problema evidente con il metodo. Ho creato un codice semplice attorno a ciò che hai mostrato e sembra funzionare correttamente per me, è [qui] (http://pastebin.com/n1S63xLb). La tua violazione di accesso potrebbe semplicemente essere un array fuori limite in base alla lunghezza dei tuoi dati e un codice che non hai mostrato qui. Potrebbe non avere nulla a che fare con il metodo di base per copiare una serie di puntatori di dispositivo. Ti suggerisco di fornire un codice completo che riproduca il problema, piuttosto che una sequenza di frammenti. Il problema è in qualcosa che non hai mostrato qui. –

+0

Grazie mille per il tuo suggerimento. Ho provato a eseguire il debug alcune volte e infine ho appreso che questo metodo era effettivamente applicabile. Il problema reale sembra molto probabilmente il problema dei fuori limite, come hai suggerito e ora sto cercando di capire. Grazie ancora per il tuo aiuto reattivo. –

+1

Certamente, l'esecuzione del debugger dovrebbe consentire di avere un'idea di cosa sta andando storto. Anche l'esecuzione del codice con 'cuda-memcheck' può far luce sul problema. –

risposta

2

Una possibilità è allocare un puntatore vuoto, come CUDA si aspetta anche come standard. Quando lo passi nel tuo kernel, puoi lanciarlo su float**. L'ho fatto in questo modo:

void* ptrs_d = 0; 
cudaMalloc(&ptrs_d, 4*sizeof(float*)); 
cudaMemcpy(ptrs_d, ptrs, 4*sizeof(float*), cudaMemcpyHostToDevice); 
kernel_test<<<dimGrid, dimBlock>>>((float**)ptrs_d); 
+1

Quale problema ha questo indirizzo? –

+0

@robert È possibile passare una serie di puntatori in un kernel di cuda. – hubs

+1

Non è necessario eseguire il cast da float a void e back to float, per ottenere ciò che viene richiesto. Il codice che ho fornito nel mio link di commento lo dimostra. –

Problemi correlati