CUDA jak uzyskać siatkę, blok, rozmiar gwintu i obliczenie paraleli bez kwadratowej macierzy

Jestem nowy w CUDA i potrzebuję pomocy w zrozumieniu niektórych rzeczy. Potrzebuję pomocy przy tworzeniu tych dwóch pętli. W szczególności jak skonfigurować dimBlock i dimGrid, aby działał szybciej. Wiem, że wygląda to jak przykład vector add w sdk, ale ten przykład jest tylko dla macierzy kwadratowych i kiedy próbuję zmodyfikować ten kod dla mojej matrycy 128 x 1024 to nie działa poprawnie.

__global__ void mAdd(float* A, float* B, float* C)
{
    for(int i = 0; i < 128; i++)
    {
        for(int i = 0; i < 1024; i++)
        {
            C[i * 1024 + j] = A[i * 1024 + j] + B[i * 1024 + j];
        }
    }
}

Ten kod jest częścią większej pętli i jest najprostszą częścią kodu, więc postanowiłem spróbować paralleize thia i uczyć się CUDA w tym samym czasie. Przeczytałem poradniki, ale nadal nie rozumiem, jak uzyskać właściwy nr. siatek / bloków / wątków i efektywnie z nich korzystać.

Author: talonmies, 2011-04-13

1 answers

Jak to napisałeś, to jądro jest całkowicie seryjne. Każdy wątek uruchomiony do jego wykonania będzie wykonywał tę samą pracę.

Główną ideą CUDA (oraz OpenCL i innych podobnych modeli programowania typu "single program, multiple data") jest to, że bierzesz operację "data parallel" - czyli taką, w której ta sama, w dużej mierze niezależna, operacja musi być wykonywana wiele razy - i piszesz jądro, które wykonuje tę operację. Duża liczba (pół)autonomicznych wątków jest wtedy uruchomiony w celu wykonania tej operacji w całym zestawie danych wejściowych.

W przykładzie dodawania tablicy, operacja równoległa danych wynosi

C[k] = A[k] + B[k];

Dla wszystkich k pomiędzy 0 a 128 * 1024. Każda operacja dodawania jest całkowicie niezależna i nie ma żadnych wymagań dotyczących zamawiania, dlatego może być wykonana przez inny wątek. Aby wyrazić to w CUDA, można napisać jądro w następujący sposób:

__global__ void mAdd(float* A, float* B, float* C, int n)
{
    int k = threadIdx.x + blockIdx.x * blockDim.x;

    if (k < n)
        C[k] = A[k] + B[k];
}

[zastrzeżenie: kod napisany w przeglądarce, nie testowany, użyj na własne ryzyko]

Tutaj, wewnętrzna i zewnętrzna pętla z kodu seryjnego są zastępowane przez jeden wątek CUDA na operację, a ja dodałem kontrolę limitu w kodzie tak, że w przypadkach, gdy uruchamianych jest więcej wątków niż wymagane operacje, nie może wystąpić przepełnienie bufora. Jeśli jądro zostanie uruchomione w ten sposób:

const int n = 128 * 1024;
int blocksize = 512; // value usually chosen by tuning and hardware constraints
int nblocks = n / nthreads; // value determine by block size and total work

madd<<<nblocks,blocksize>>>mAdd(A,B,C,n);

Następnie 256 bloków, z których każdy zawiera 512 wątków zostanie uruchomionych na sprzęcie GPU, aby wykonać operację dodawania tablicy równolegle. Zauważ, że jeśli rozmiar danych wejściowych nie był wyrażalny jako nice okrągła wielokrotność rozmiaru bloku, liczba bloków musi być zaokrąglona w górę, aby pokryć pełny zestaw danych wejściowych.

Wszystko to jest niezwykle uproszczonym przeglądem paradygmatu CUDA dla bardzo banalnej operacji, ale być może daje wystarczająco dużo wglądu, abyś mógł kontynuować. CUDA jest raczej dojrzały w dzisiejszych czasach i istnieje wiele dobrych, darmowych materiałów edukacyjnych pływających po Internecie, prawdopodobnie można użyć do dalszego oświetlenia wielu aspektów modelu programowania I proszę o odpowiedź.

 34
Author: talonmies,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 06:08:23