Ansi C CUDA

0

Witam

Jestem nowym uzytko0wnikiem tego forum. Bardzo proszę o pomoc z programem do splotu maski z obrazem tiff z wykorzystaniem technologi CUDA.
Ten sam program działający na procesorze działa poprawnie. Podczas prób przerobienia go na GPU występuje problem. Program kompiluje się prawidłowo uruchamia się również ale niestety błędnie liczy.

Poniżej funkcja obliczeniowa dla CPU:

char splotCPU(unsigned char *wejscie,int rozmiar, int *maska)
	{
////////////////////////////////////////////////////////////////////////////////
//  Funkcja nakładająca maske na tablicę. Na wejsciu otrzymuje	  //
//  zestaw pikseli (9) oraz maskę do nałozenia, zwraca wartość	  //
//	piksela										  //
////////////////////////////////////////////////////////////////////////////////
	char wynik;							//wartość piksela po nałozeniu maski
	wynik=(	wejscie[0]* maska[0]+
			wejscie[1]* maska[1]+
			wejscie[2]* maska[2]+
			wejscie[3]* maska[3]+
			wejscie[4]* maska[4]+
			wejscie[5]* maska[5]+
			wejscie[6]* maska[6]+
			wejscie[7]* maska[7]+
			wejscie[8]* maska[8])/9 ;
	return wynik;
	}

podobna funkcja dla GPU:

__global__ void splotGPU(unsigned char *wejscie,int rozmiar, int *maska,unsigned char *wynik)
	{
////////////////////////////////////////////////////////////////////////////////
//  Funkcja nakładająca maske na tablicę. Na wejsciu otrzymuje	  //
//  zestaw pikseli (9) oraz maskę do nałozenia, zwraca wartość	  //
//	piksela										 //
///////////////////////////////////////////////////////////////////////////////

	//int id = blockIdx.x * blockDim.x + threadIdx.x;
	wynik[0]=(	wejscie[0]* maska[0]+
			wejscie[1]* maska[1]+
			wejscie[2]* maska[2]+
			wejscie[3]* maska[3]+
			wejscie[4]* maska[4]+
			wejscie[5]* maska[5]+
			wejscie[6]* maska[6]+
			wejscie[7]* maska[7]+
			wejscie[8]* maska[8])/9 ;

	}

Poniżej użycie funkcji dla CPU:

			wyR[i]=splotCPU(tabR,3, wekM);
			wyG[i]=splotCPU(tabG,3, wekM);
			wyB[i]=splotCPU(tabB,3, wekM);

gdzie:
wyR[i] - wektor wynikowy dla wartość R (czerwonych)
wyG[i] - wektor wynikowy dla wartość G (zielonych)
wyB[i] - wektor wynikowy dla wartość B (niebieskich)
wekM - wektor jednowymiarowy zawierający wartości maski Laplaca
tabR, tabG, tabG - wektory wejściowe dla poszczególnych kolorów

Program działa poprawnie wylicza odpowiednio dane.

Dla GPU:

cudaMemcpy(wynGR, tabGPU_R, size, cudaMemcpyHostToDevice);
splotGPU<<<dimGrid , dimBlock>>>(tabGPU_R , 3 , wekM , rezultat_Device_R);
cudaThreadSynchronize();   // synchronizacja
cudaMemcpy(rezultat_Device_R,temp_R, size_resultat, cudaMemcpyDeviceToHost);

gdzie:
wynGR - wektor z wejściowy dla GPU(Device) dla R(czerwony)
tabGPU_R - wektor z wejściowy dla CPU(Host) dla R(czerwony)
size - wielkość wynGR czyli "size_t size = sizeof(unsigned char) * 9;"
wekM - wektor jednowymiarowy zawierający wartości maski Laplaca
rezultat_Device_R - wektor wyjściowy dla GPU(Device) dla R(czerwony)
temp_R - wektor wyjściowy dla CPU(Host) dla R(czerwony)
size_resultat - wielkość rezultat_Device_R czyli "size_t size_resultat = sizeof(unsigned char);"

Identycznie postępuje z innymi kolorami.

Niestety ale temp_R , temp_G oraz temp_B czyli wartości zwracane z funkcji są zawsze stałe niezależnie od danych wejściowych. Są równe dla wszystkich kolorów chociaż wartości poszczególnych kolorów dla piksla są różne.

Bardzo proszę o pomoc.

0

splotCPU - wynik jest jako char
splotGPU - wynik jest jako unsigned char

O to cho?

1
 wejscie[0]* maska[0]+
                        wejscie[1]* maska[1]+
                        wejscie[2]* maska[2]+
                        wejscie[3]* maska[3]+
                        wejscie[4]* maska[4]+
                        wejscie[5]* maska[5]+
                        wejscie[6]* maska[6]+
                        wejscie[7]* maska[7]+
                        wejscie[8]* maska[8]

Hmmm, a pętle ukradli na poczcie?

0

Czy ma ktoś może jakiś pomysł z czym może być problem??

Czekam na opinie.

0

No tak, masz int maska i podajesz mu 3. Usuń

0

Ta 3 tyczy się rozmiaru a nie maski.

0

To twój pierwszy program w CUDA?

W OpenCL trzeba wziąć id wątku, grupy itp przed pobraniem wartości z tablicy wejściowej. Każdy wątek dostaje te same parametry oprócz wspomnianych id. Zresztą widzę, że w kodzie dla GPU masz wykomentowane liczenie numeru wątku: "//int id = blockIdx.x * blockDim.x + threadIdx.x;". Nie wiesz do czego to służy?

0

Tak to mój pierwszy program w CUDA.

Nie wiem do końca tak dokładnie

int id = blockIdx.x * blockDim.x + threadIdx.x;

Z tego co wiem to ten zapis powoduje tak jakby obliczenia przechodziły przez pętle po przez bloki i wątki bloków w GPU.

0

Nie wiesz co to są grupy wątków, nie wiesz że scheduler może rozmieszczać wątki w 1D, 2D i 3D, a zadajesz pytania na forum? Idź poszukaj jakiegoś tutoriala CUDA dla początkujących.

http://developer.amd.com/gpu/amdappsdk/documentation/pages/TutorialOpenCL.aspx
Tu masz tutorial jak w OpenCL zrobić Hello World'a. Przerób go, zrozum i możesz wtedy zadawać pytania na forum.

0
Wibowit napisał(a)

Nie wiesz co to są grupy wątków, nie wiesz że scheduler może rozmieszczać wątki w 1D, 2D i 3D, a zadajesz pytania na forum? Idź poszukaj jakiegoś tutoriala CUDA dla początkujących.

http://developer.amd.com/gpu/amdappsdk/documentation/pages/TutorialOpenCL.aspx
Tu masz tutorial jak w OpenCL zrobić Hello World'a. Przerób go, zrozum i możesz wtedy zadawać pytania na forum.

Dzięki wielkie za pomoc.
Jako pomoc podsyłasz tutorial w OpenCL ale niestety ja mam napisać w CUDA. Kwestie Hello World już przerobiłem w CUDA.

Może dla niektórych problem który mam jest błahy ale myślałem że po to są fora aby osoby o wielkiej wiedzy w danym segmencie nauki pomagały tym którzy się uczą.

0

No to szukaj po necie o co chodzi w tej wykomentowanej linijce. Ja tam wielkiej wiedzy nie mam, a w szczególności jeśli chodzi o CUDAczne wynalazki (mam Radeona). Jedyne co ci mogę poradzić to to, żebyć poszukał tutków dla początkujących.

Poza tym zobacz sobie do tego kodu OpenCL HelloWorld:

#pragma OPENCL EXTENSION cl_khr_byte_addressable_store : enable
__constant char hw[] = "Hello World\n";
__kernel void hello(__global char * out)
{
    size_t tid = get_global_id(0);
    out[tid] = hw[tid];
}

A w szczególności na te dwie linijki:

    size_t tid = get_global_id(0);
    out[tid] = hw[tid];

Global id ma podobną rolę zapewne co to id liczone w twoim kodzie. Jak widzisz używa się go do indeksowania tablic. Więc ty też spróbuj go użyć do indeksowania tablic.

1 użytkowników online, w tym zalogowanych: 0, gości: 1