2011-02-16 22 views
7

Jestem pod wrażeniem mnożenia macierzy na CUDA. Wynikowa macierz produktu ma zawsze wartość zero. Przeczytałem kilka przykładowych kodów, takich jak matrix multiplication in cuda, aby rozwiązać mój problem, ale wszystko na próżno.Mnożenie macierzy za pomocą CUDA

Poza błędnym wynikiem 0, maksymalny rozmiar "Szerokość" (kod poniżej) wynosi nawet 512. Nie byłem w stanie debugować, gdzie leży problem. Możemy to omówić na StackOverflow.

mam na myśli „Programowanie procesorów masowo równoległych”

#include<cuda.h> 
#include<stdio.h> 

int main(void) { 
    void MatrixMultiplication(float *, float *, float *, int); 
    const int Width = 5; 
    float M[Width*Width], N[Width*Width], P[Width*Width]; 
    for(int i = 0; i < (Width*Width) ; i++) { 
     M[i] = 5; 
     N[i] = 5; 
     P[i] = 0; 
    } 
    MatrixMultiplication(M, N, P, Width); 
    for(int i = 0; i < (Width*Width) ; i++) { 
     printf("%d \n", P[i]); 
    } 
    int quit; 
    scanf("%d",&quit); 
    return 0; 
} 

//Matrix multiplication kernel - thread specification 
__global__ void MatrixMulKernel(float *Md, float *Nd, float *Pd, int Width) { 
    //2D Thread ID 
    int tx = threadIdx.x; 
    int ty = threadIdx.y; 

    //Pvalue stores the Pd element that is computed by the thread 
    float Pvalue = 0; 

    for(int k = 0; k < Width ; ++k) { 
     float Mdelement = Md[ty*Width + k]; 
     float Ndelement = Nd[k*Width + tx]; 
     Pvalue += (Mdelement*Ndelement); 
    } 

    Pd[ty*Width + tx] = Pvalue; 
} 

void MatrixMultiplication(float *M, float *N, float *P, int Width) { 
    int size = Width*Width*sizeof(float); 
    float *Md, *Nd, *Pd; 

    //Transfer M and N to device memory 
    cudaMalloc((void**)&Md, size); 
    cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice); 
    cudaMalloc((void**)&Nd, size); 
    cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice); 

    //Allocate P on the device 
    cudaMalloc((void**)&Pd,size); 

    //Setup the execution configuration 
    dim3 dimBlock(Width,Width); 
    dim3 dimGrid(1,1); 

    //Launch the device computation threads! 
    MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width); 

    //Transfer P from device to host 
    cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost); 

    //Free device matrices 
    cudaFree(Md); 
    cudaFree(Nd); 
    cudaFree(Pd); 
} 
+2

Aby uzyskać prawidłowe formatowanie kodu, musisz wcięcie całego kodu z 4 spacji. Możesz to łatwo zrobić podświetlając swój kod i naciskając 'Ctrl + K'. –

+0

Dzięki Jeff! Zamierzał to zrobić –

+0

Jeśli nie musisz trzymać się własnego kodu, CUDA C Programming Guide ma wspaniałą implementację matrix-mul, która może obsługiwać matryce o innych wymiarach niż moce dwóch i jest zoptymalizowana przy użyciu pamięci współużytkowanej. Gorąco polecam go do użytku w świecie rzeczywistym i do nauki. –

Odpowiedz

1

zorientowali się, co było źle. Przeanalizujmy go:

Punkt 1: Dążenie do usunięcia kiedykolwiek monotoniczny „zero”

Jak już wspomniano, należy wymienić printf("%d \n", P[i]); jak printf("%f \n", P[i]);

Punkt 2: Dlaczego program nie o wartości Szerokość 512?

W rzeczywistości nie powiedzie się nawet dla małej wartości, takiej jak 23. Dlaczego? Ponieważ 23 * 23 jest> 512 (Maksymalna liczba wątków, które GPU może mieć na blok od dzisiaj!)

0

w twojej MatrixMulKernel działają swój pętli for jest jak

for(int k = 0; k < Width ; ++k) 
{ 
    //rest of code  
} 

Zamiast Width, należy użyć Width*Width jako macierzy jest wielkości Width*Width.

+1

Cały problem z paralelizmem CUDA polega na wyeliminowaniu narzutów obliczeniowych. W takim przypadku każdy wątek odpowiada tylko za jeden wynik macierzy produktu. Jeden wynik (element) macierzy produktów można znaleźć za pomocą iteracji "Szerokość". Więc Szerokość * Szerokość w żadnym wypadku nie zadziała. –

+0

takie jak @Gaurav powiedział, Szerokość * Szerokość tylko wysadzi w pamięci ... – ardiyu07

4

ci szło dobrze aż do tego punktu:

for(int i = 0; i < (Width*Width) ; i++) { 
    printf("%d \n", P[i]); 
} 

zmieniłem go na% f (bo to float) i wszystkie one druk ładnie :)

$ ./test.exe 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
+0

Rzeczywiście! Chociaż zorientowałem się, nie czytając twojej odpowiedzi i po prostu ją opublikuję. –

Powiązane problemy