2013-06-13 10 views
5

Próbuję rozwiązać problem na końcu lekcji 1 kursu Udacity, ale nie jestem pewien, czy zrobiłem głupią literówkę, czy też kod jest nieprawidłowy.Zamieszanie przez siatkę i wymiary bloku

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()); 
} 

Druga metoda to:

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; 
} 

Komunikat o błędzie mówi, co następuje: libdc1394 błędu: Nie można zainicjować libdc1394 błąd Cuda na student_func.cu:76 nieokreślony awarii uruchomienie cudaGetLastError() nie mogliśmy wykonać Twojego kodu. Czy poprawnie ustawiłeś siatkę i/lub rozmiar bloku?

Twój kod skompilowany! błąd wyjścia: libdc1394 błąd: Nie można zainicjować libdc1394 błąd Cuda na student_func.cu:76 nieokreślonym cudaGetLastError awarii Launch()

Linia 76 jest ostatni wiersz w pierwszym bloku kodu i ile im świadomość i przystań zmieniłem cokolwiek w nim. Nie mogę znaleźć deklaracji cudaGetLastError().

Mam głównie na uwadze moją wiedzę na temat ustawiania wymiarów siatki/bloku + czy pierwsze podejście do metody było właściwe w odniesieniu do mapowania między tablicą 1D pozycji piksela a moimi wątkami.

EDYCJA: Chyba coś źle zrozumiałem. NumRows = liczba pikseli w pionie? numCols = piksele w kierunku poziomym? Mój blok składa się z wątków 8 x 8, gdzie każdy wątek reprezentuje 1 piksel? Jeśli tak, zakładam, że to dlatego musiałem podzielić przez 4 przy obliczaniu siatkiRozmiar, ponieważ obraz nie jest kwadratowy? Zakładam, że mógłbym również utworzyć blok, który byłby kolumnami 2: 1: wiersze?

Screen shot

EDIT 2: po prostu starał się zmienić swój blok tak, że było 2: 1 stosunek, więc mogę podzielić NumRows i numCol o tym samym numerze, ale jego teraz pokazując puste obszary w dno i bok. Dlaczego istnieją puste obszary zarówno na dole, jak i na boku. Nie zmieniłem wymiarów y według siatki lub bloku.

enter image description here

+0

jest jeszcze jeden błąd w jądrze, zobacz odpowiedź. również nie trzeba dzielić przez różne numery lub dwa razy pokryjesz kilka pikseli lub stracisz trochę – ShPavel

Odpowiedz

9

każdy bloki przetwarza 32 * 32 pikseli, a istnieją (totalPixels/32) * (totalPixels/32) blokuje, więc przetwarzać totalPixels^2 piksele - to wydaje się błędne

1-ty było źle, to powinien być prawidłowa:

const dim3 blockSize(32,32,1); 

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

jest to dość powszechne wzór 2D - można zapamiętać to

w próbka rozmiar obrazu nie jest potęgą dwójki i chcesz zablokować aby pokryć wszystkie swoje zdjęcie (lub nawet więcej)

więc następnym muszą być poprawne: gridCols * blockSize.x> = numCols gridRows * bloku.y> = NumRows

wybrać rozmiar bloku i w oparciu o to ty ilości obliczeniowej bloków trzeba pokryć wszystkie obrazu

potem, w jądrze, należy sprawdzić, czy nie są „z obrazu” , w przypadkach, o złym rozmiarze

inny problem jest w jądrze, to musi być (y * numCols + x), nie oposite

jądra:

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; 
} 

powołanie Kod:

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

cholera, ja czuję się robić rzeczy jeszcze trudniej zrozumieć (

+0

tak, tak, prawda, że ​​moje siatki i gridy są błędne, dzięki za to. Dlaczego u + 1 do gridRows i gridCols? –

+0

Tak, więc miałem szczęście, że te parametry pasują. Myślę, że rozumiem teraz, że jest całkiem uporządkowany, przypisując więcej wątków niż pikseli, a następnie po prostu upewniając się, że bieżący wątek znajduje się w zasięgu pikseli. Zastanawiałem się, co zrobić, jeśli obraz nie był dokładnie dopasowany do bloków 32. Jedno ostatnie pytanie, kiedy deklarujemy dim3 dla bloku i siatki, czy to zawsze x, y, z gdzie x = horyzontalne itp? Jeszcze raz dziękuję za pomoc +1 :) –

+1

nie jestem pewien, o co pytasz) zawsze ma 3 współrzędne, ale nie ma prawdziwych powiązań z "poziomymi" lub "pionowymi". Łatwiej jest wyobrazić je jak zwykłe xy z dims, ale nic nie stoi na przeszkodzie, aby użyć współrzędnej "y" lub "z" do indeksowania wierszy lub kolumn, czy cokolwiek innego, – ShPavel