2016-03-22 6 views
-2

Ich bin ein Anfänger in CUDA. Ich schreibe ein Programm, um zwei Matrizen ohne gemeinsamen Speicher zu multiplizieren. Hier ist mein Programm, wo ich 4x4 Matrizen mit 1 gefüllt multiplizieren.Matrix-Multiplikation mit CUDA: Falscher Ausgang

Der Ausgang ist 26853932, wobei der korrekte Ausgang 4 sein sollte.

Kann mir bitte jemand sagen, wo ich falsch liege. Vielleicht habe ich einen sehr naiven Fehler gemacht?

#include "cuda_runtime.h" 
#include "device_launch_parameters.h" 
#include <stdio.h> 
#include<stdlib.h> 

//kernel deifnition 

__global__ void mulKernel(int *d_M, int *d_N, int *d_P,int width) 
{ 
int row = blockIdx.y*blockDim.y + threadIdx.y; 
int col = blockIdx.x*blockDim.x + threadIdx.x; 


if (row < width && col < width) 
{ 
    int pvalue=0; 
    for (int k = 0; k < width; k++) 
    { 
     pvalue = pvalue + (d_M[row*width + k] * d_N[k*width + col]); 
    } 

    d_P[row*width + col] = pvalue; 
} 
} 

int main() 
{ 
const int block_size = 2; 
const int array_width = 4; 
int h_M[array_width][array_width] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 

int h_N[array_width][array_width] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 
int h_P[array_width][array_width]; 

int size = array_width*array_width*(sizeof(int)); 
int *d_M, *d_N, *d_P; 

//memory allocation 
cudaMalloc((void**)&d_M, size); 
cudaMalloc((void**)&d_N, size); 
cudaMalloc((void**)&d_P, size); 

//copy data from host to memory 
cudaMemcpy(d_M, h_M, size, cudaMemcpyHostToDevice); 
cudaMemcpy(d_N, h_N, size, cudaMemcpyHostToDevice); 

dim3 grid(array_width/block_size, array_width/block_size, 0);  //grid size 
dim3 block(block_size, block_size, 0); //block size 

mulKernel << <grid, block >> >(d_M,d_N,d_P,array_width); 

cudaMemcpy(h_P, d_P, size, cudaMemcpyDeviceToHost); 

printf("%d", h_P[0][0]); 

printf("Press enter to exit....\n"); 
getchar(); 


} 
+3

Der Fehler ist, dass Sie die Z-Ausdehnung Ihres Blocks und Grids auf "0" setzen. Ein 2D-Gitter ist ein 3D-Gitter, bei dem eine Dimension die Länge 1 hat. Wenn Sie das letzte Argument für "dim3" weglassen, wird es automatisch auf "1" gesetzt. Löschen Sie einfach ', 0' und Ihr Code funktioniert. Für zukünftige Beiträge: Es ist nicht notwendig, ein völlig irrelevantes Bild der Ausgabe einzufügen. Schreiben Sie stattdessen die falsche Ausgabe ** und ** die erwartete Ausgabe in Text. – havogt

+1

@havogt Wenn Sie eine Antwort schreiben möchten, würde ich upvote. Die Verwendung von "0", wie Sie angeben, würde tatsächlich einen CUDA-Laufzeitfehler auslösen, nach dem der gesendete Code nicht sucht. –

Antwort

2

Das Problem ist in den Zeilen

dim3 grid(array_width/block_size, array_width/block_size, 0);  //grid size 
dim3 block(block_size, block_size, 0); //block size 

wo das Gitter Ausmaß in Z-Richtung auf 0. Die korrekte Darstellung eines 2D-Objekts in einem 3D-Gitter gesetzt wird, ist das Ausmaß, in einem setzen der Richtungen zu 1.

der Code funktioniert nach dem 0 mit 1 oder durch Weglassen der dritte Argument ersetzt (dann ist es standardmäßig auf 1 initialisiert):

dim3 grid(array_width/block_size, array_width/block_size); 
dim3 block(block_size, block_size); 

mit dem falschen Setup des Laufzeitfehler invalid configuration argument auf dem Kernel-Aufruf ausgelöst. Sie könnten dies selbst leicht gefunden haben, indem Sie proper CUDA error checking verwenden (oder indem Sie Ihr Programm mit cuda-memcheck ausführen).

+0

Danke Mann, wie naiv meinerseits einen so dummen Fehler zu machen.Umgezählt! –

1

Die Initialisierung von GRID & BLOCK Konfiguration ist falsch.

Jetzt:

dim3 grid(array_width/block_size, array_width/block_size, 0);  //grid size 
dim3 block(block_size, block_size, 0); //block size 

Erwartet:

dim3 grid(array_width/block_size, array_width/block_size, 1);  //grid size 
dim3 block(block_size, block_size, 1); //block size 

Seine gute Gewohnheit CUDA Fehler Statements zu verwenden. Im Folgenden ist das sehr einfache Beispiel, ersetzen Sie einfach stmt mit Ihrer erwarteten Code-Anweisung.

#define wbCheck(stmt) do{ 
cudaError_t err = stmt; 
if (err != cudaSuccess) { 
printf("Failed to run stmt %d ", __LINE__); 
printf("Got CUDA error ... %s ", cudaGetErrorString(err)); 
return -1; 
} 
} while(0)