2010-12-10 17 views
6

Pracuję nad projektem z CUDA. Aby uzyskać powiesić, mam następujący kod.Początkujący CUDA - prosty przyrost var nie działa

#include <iostream> 

using namespace std; 

__global__ void inc(int *foo) { 
    ++(*foo); 
} 

int main() { 
    int count = 0, *cuda_count; 
    cudaMalloc((void**)&cuda_count, sizeof(int)); 
    cudaMemcpy(cuda_count, &count, sizeof(int), cudaMemcpyHostToDevice); 
    cout << "count: " << count << '\n'; 
    inc <<< 100, 25 >>> (&count); 
    cudaMemcpy(&count, cuda_count, sizeof(int), cudaMemcpyDeviceToHost); 
    cudaFree(cuda_count); 
    cout << "count: " << count << '\n'; 
    return 0; 
} 

Wyjście jest

count: 0 
count: 0 

czym problem?

Z góry dziękuję!

+0

powinieneś pracować przez kilka przykładów w przewodniku programowym. Twoja składnia ma rozbieżności w stosunku do tego, co jest sugerowane w przewodniku programowania. – Marm0t

Odpowiedz

6

znalazłem rozwiązanie. Po prostu musiałem użyć funkcji atomowej, tj. Funkcji, która jest wykonywana bez interferencji z innych wątków. Innymi słowy, żaden inny wątek nie może uzyskać dostępu do określonego adresu, dopóki operacja nie zostanie zakończona w trybie .

Kod:

#include <iostream> 

using namespace std; 

__global__ void inc(int *foo) { 
    atomicAdd(foo, 1); 
} 

int main() { 
    int count = 0, *cuda_count; 
    cudaMalloc((void**)&cuda_count, sizeof(int)); 
    cudaMemcpy(cuda_count, &count, sizeof(int), cudaMemcpyHostToDevice); 
    cout << "count: " << count << '\n'; 
    inc <<< 100, 25 >>> (cuda_count); 
    cudaMemcpy(&count, cuda_count, sizeof(int), cudaMemcpyDeviceToHost); 
    cudaFree(cuda_count); 
    cout << "count: " << count << '\n'; 
    return 0; 
} 

wyjściowa:

count: 0 
count: 2500 

Dziękuję, że mi zrozumieć ten błąd, że byłem zobowiązującego.

8

Powinieneś przekazać cuda_count do swojej funkcji jądra. Poza tym wszystkie twoje wątki próbują zwiększyć tę samą lokalizację pamięci. Efekt tego nie jest dobrze zdefiniowany (co najmniej jeden zapis się powiedzie, ale więcej niż jeden).

Trzeba temu zapobiec tylko przez jeden wątek pozwalając wykonać pracę:

__global__ void inc(int *foo) { 
    if (blockIdx.x == 0 && threadIdx.x == 0) 
    ++*foo; 
} 

(niesprawdzone)

+0

Co za moja wina. Jednak wynik jest nadal błędny. To daje mi 1 zamiast oczekiwanego 2500. –

+5

@Renato: tak nie działa CUDA. Zobacz moją zaktualizowaną odpowiedź: jest po prostu niezdefiniowana, aby pisać do tej samej lokalizacji w pamięci z różnych wątków. To, czego chcesz, to tak zwana operacja zbierania. Wdrożenie tego nie jest trywialne. –

+0

Próbowałem twojej szybkiej poprawki, ale wynik był 2. –

0

Problem z kodem polega na przekazywaniu wskaźnika jądra urządzenia do wskaźnika. Nie wskaźnik do zliczania. One '&' zbyt dużo

Linia ta

inc <<< 100, 25 >>> (&count); 

Powinny być

inc <<< 100, 25 >>> (count);