Ho cercato di capire come rendere quello che pensavo sarebbe un semplice kernel per prendere la media dei valori in una matrice 2d, ma sto riscontrando alcuni problemi che riguardano il mio processo di pensiero.determinare quanti blocchi e thread per un kernel CUDA e come usarli
In base al mio output deviceQuery, la mia GPU ha 16MP, 32cores/mp, i blocchi max è 1024x1024x64 e ho un massimo thread/blocco = 1024.
Quindi, sto lavorando ad alcune immagini di grandi dimensioni. Forse 5000px x 3500px o qualcosa del genere. Uno dei miei kernel sta prendendo una media di alcuni valori su tutti i pixel dell'immagine.
Il codice esistente ha le immagini memorizzate come un array 2D [righe] [colonne]. In modo che il kernel, in C, sembri come ci si aspetterebbe, con un ciclo su righe e un ciclo su colonne, con il calcolo nel mezzo.
Quindi, come si imposta la porzione di calcolo della quota di questo codice in CUDA? Ho visto il codice di riduzione nell'SDK, ma quello è per un array a dimensione singola. Non ha alcuna menzione su come impostare il numero di blocchi e fili per quando si dispone di 2D.
Sto pensando che avrei davvero bisogno di configurarlo in questo modo, e questo è dove mi piacerebbe che qualcuno carillon e aiuto:
num_threads=1024;
blocksX = num_cols/sqrt(num_threads);
blocksY = num_rows/sqrt(num_threads);
num_blocks = (num_rows*num_cols)/(blocksX*blocksY);
dim3 dimBlock(blocksX, blocksY, 1);
dim3 dimGrid(num_blocks, 1, 1);
Questo sembra avere senso per la configurazione ?
E poi nel kernel, per lavorare su una particolare riga o colonna, avrei dovuto usare
rowidx = (blockIdx.x * blockDim.x) + threadId.x colidx = (blockIdx. y * blockDim.y) + threadId.y
Almeno penso che avrebbe funzionato per ottenere una riga e una colonna.
Come potrei quindi accedere a quella particolare riga r e colonna c nel kernel? Nella guida di programmazione CUDA ho trovato il seguente codice:
// Host code int width = 64, height = 64;
float* devPtr; size_t pitch;
cudaMallocPitch(&devPtr, &pitch, width * sizeof(float), height);
MyKernel<<<100, 512>>>(devPtr, pitch, width, height);
// Device code __global__ void MyKernel(float* devPtr, size_t pitch, int width, int height)
{
for (int r = 0; r < height; ++r)
{
float* row = (float*)((char*)devPtr + r * pitch);
for (int c = 0; c < width; ++c)
{
float element = row[c];
}
}
}
che sembra simile a come devi usare malloc in C per dichiarare una matrice 2D, ma Esso non dispone alcuna menzione di accesso che matrice in un proprio kernel . Immagino nel mio codice, userò quella chiamata cudaMallocPitch e poi eseguirò una memcpy per ottenere i miei dati nell'array 2D sul dispositivo?
Qualsiasi consiglio apprezzato! Grazie!
Se capisco cosa sta facendo iDivUP, è possibile semplificare la logica un po 'grazie al troncamento dei numeri interi: return (a + b-1)/b; –