2013-06-13 11 views
5

Sto cercando di risolvere il problema alla fine della lezione 1 del corso Udacity ma non sono sicuro se ho appena fatto uno stupido errore di battitura o se il codice reale è sbagliato.Confusione sulle dimensioni della griglia e del blocco

void your_rgba_to_greyscale(const uchar4 * const h_rgbaImage, uchar4 * const d_rgbaImage, unsigned char* const d_greyImage, size_t numRows, size_t numCols) 
{ 
    size_t totalPixels = numRows * numCols; 
    size_t gridRows = totalPixels/32; 
    size_t gridCols = totalPixels/32; 
    const dim3 blockSize(32,32,1); 
    const dim3 gridSize(gridCols,gridRows,1); 
    rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols); 
    cudaDeviceSynchronize(); checkCudaErrors(cudaGetLastError()); 
} 

L'altro metodo è:

void rgba_to_greyscale(const uchar4* const rgbaImage, unsigned char* const greyImage, int numRows, int numCols) 
{ 
    int x = (blockIdx.x * blockDim.x) + threadIdx.x; 
    int y = (blockIdx.y * blockDim.y) + threadIdx.y; 
    uchar4 rgba = rgbaImage[x * numCols + y]; 
    float channelSum = 0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z; 
    greyImage[x * numCols + y] = channelSum; 
} 

Messaggio di errore dice quanto segue: libdc1394 Errore: Impossibile inizializzare libdc1394 errore Cuda a student_func.cu:76 non specificato fallimento del lancio cudaGetLastError() non siamo stati in grado di eseguire il tuo codice. Hai impostato correttamente la griglia e/o la dimensione del blocco?

Il tuo codice compilato! error uscita: error libdc1394: Impossibile inizializzare libdc1394 errore Cuda a student_func.cu:76 specificato cudaGetLastError fallimento del lancio()

linea 76 è l'ultima linea nel primo blocco di codice e per quanto a conoscenza im Havent cambiato qualcosa in esso. Non riesco a trovare la dichiarazione di cudaGetLastError().

Mi sono occupato principalmente delle mie conoscenze sulla configurazione delle dimensioni della griglia/blocco + se il primo approccio ai metodi era corretto per quanto riguarda la mappatura tra una matrice 1D di posizioni in pixel e i miei thread.

MODIFICA: Immagino che io abbia frainteso qualcosa. Il numero = numero di pixel nella verticale? numCols = pixel in direzione orizzontale? Il mio blocco è composto da 8 x 8 thread, in cui ogni thread rappresenta 1 pixel? In tal caso, supponendo che sia il motivo per cui ho dovuto dividere per 4 nel calcolo delle righe di griglia in quanto l'immagine non è quadrata? Im supponendo che avrei potuto anche fare un blocco che era colonne 2: 1: righe?

Screen shot

EDIT 2: Ho appena cercato di cambiare blocco in modo che fosse rapporto 2: 1, così ho potuto quindi dividere numRows e NumCol dallo stesso numero ma la sua ora mostra aree vuote alla il fondo e il lato. Perché ci sono aree vuote sia nella parte inferiore che laterale. Non ho cambiato le dimensioni y di griglia o blocco.

enter image description here

+0

c'è un errore di più nel kernel, si veda la risposta. anche tu non devi dividere per numeri diversi o coprirai alcuni pixel due volte o mancherai un po 'di – ShPavel

risposta

9

ogni blocchi processi a 32 * 32 pixel, e ci sono (/ 32 totalPixels) blocchi (totalPixels/32) *, in modo da elaborare totalPixels^2 pixel - che sembra sbagliato

prima era sbagliato, questo dovrebbe essere quella giusta:

const dim3 blockSize(32,32,1); 

size_t gridCols = (numCols + blockSize.x - 1)/blockSize.x; 
size_t gridRows = (numRows + blockSize.y - 1)/blockSize.y; 

si tratta di un modello abbastanza comune per 2d - si può ricordare

nel dimensioni dell'immagine campione non è potenza di due e si desidera bloccare per coprire tutte le immagine (o anche più)

così la prossima deve essere corretta: gridCols * blockSize.x> = numColonne gridRows * blockSize.y> = numRows

si sceglie la dimensione del blocco e basando su di esso si somma calcolo dei blocchi è necessario per coprire tutti image

dopo che, nel kernel, è necessario controllare che non sei 'di immagine' , per i casi con cattive dimensioni

un altro problema è nel kernel, deve essere (numColonne y * + x), non oposite

kernel:

int x = (blockIdx.x * blockDim.x) + threadIdx.x; 
int y = (blockIdx.y * blockDim.y) + threadIdx.y; 

if(x < numCols && y < numRows) 
{ 
    uchar4 rgba = rgbaImage[y * numCols + x]; 
    float channelSum = 0.299f * rgba.x + 0.587f * rgba.y + 0.114f * rgba.z; 
    greyImage[y * numCols + x] = channelSum; 
} 

chiamata Codice:

const dim3 blockSize(4,32,1); // may be any 

size_t gridCols = (numCols + blockSize.x - 1)/blockSize.x; 
size_t gridRows = (numRows + blockSize.y - 1)/blockSize.y; 

const dim3 gridSize(gridCols,gridRows,1); 
rgba_to_greyscale<<<gridSize, blockSize>>>(d_rgbaImage, d_greyImage, numRows, numCols); 
cudaDeviceSynchronize(); 
checkCudaErrors(cudaGetLastError()); 

dannazione, mi sento come se sto facendo le cose ancora più difficile da capire (

+0

sì proprio sul fatto che i miei gridrows e gridcols sono sbagliati, grazie per quello. Perché stai + 1 su gridRows e gridCols? –

+0

Sì, ok, sono stato fortunato che quei parametri si adattano. Penso di capirlo ora, è abbastanza ordinato assegnare più thread rispetto ai pixel e quindi semplicemente assicurandoti che il thread corrente sia all'interno del raggio dei pixel. Mi chiedevo cosa fare se l'immagine non fosse esatta per blocchi di 32. Un'ultima domanda, quando dichiari il dim3 per blocco e griglia, è sempre x, y, z dove x = orizzontale ecc? Grazie ancora per il tuo aiuto +1 :) –

+1

non sono sicuro di cosa stai chiedendo) ha sempre 3 coordinate, ma non ha legami reali per essere 'orizzontale' o 'verticale'. È semplicemente più facile immaginarli come se fossi solito x y z dims, ma nulla ti impedisce di usare la coordinata 'y' o 'z' per indicizzare righe o colonne o qualsiasi altra cosa – ShPavel

Problemi correlati