[c++][H ] Cuda Programmierung Linux (Pointer evtl?)

Alpha63

Mitglied
Hallo,

ich versuche mich gerade an der Cuda Programmierung unter linux.
Mein aktuelles beispiel soll 2 Matrizen Zusammen Addieren und in der Variable C speichern.
Anschließend soll es alles ausgeben. Leider Funktioniert es nich. Ich denke mal es ist ein Pointer Problem.

Ich hoffe ihr könnt mir helfen. Beim Debugen sagt er mir Segmantion faul bei der printf ausgabe von c.
Der Code funktioniert wenn man die array nicht dynamisch initialisiert. D.h. wenn ich gleich A[N][N]... schreibe. Ich will es aber dynamisch.

Code:
#include <cuda.h>
#include <stdio.h>
#include <stdlib.h>


#define N 5
#define BLOCK_DIM 5

__global__ void matrixAdd (int *a, int *b, int *c);
void InitData(int** data, int n);
void RandomInit(int** data, int n);

int main() 
{
   int** a;
   int** b;
   int** c;
   int*  dev_a;
   int*  dev_b;
   int*  dev_c;
   int size = N * N * sizeof(int);

   // initialize a and b with real values (NOT SHOWN)
   cudaMalloc((void**)&dev_a, size);
   cudaMalloc((void**)&dev_b, size);
   cudaMalloc((void**)&dev_c, size);

   a = (int**) malloc((N) * sizeof(int*));
   InitData(a, N);
   RandomInit(a, N);
   /*-------------------------------------------------------------------------*/
   b = (int**) malloc((N) * sizeof(int*));
   InitData(b, N);
   RandomInit(b, N);
   /*------------------------------------------------------------------------*/
   c = (int**) malloc((N) * sizeof(int*));
   InitData(c, N);

   cudaMemcpy(dev_a, a, size, cudaMemcpyHostToDevice);
   cudaMemcpy(dev_b, b, size, cudaMemcpyHostToDevice);

   dim3 dimBlock(BLOCK_DIM, BLOCK_DIM);
  
   dim3 dimGrid((int)ceil(N/dimBlock.x),(int)ceil(N/dimBlock.y)); 
   matrixAdd<<<dimGrid,dimBlock>>>(dev_a,dev_b,dev_c);

   cudaThreadSynchronize();
   cudaMemcpy(a, dev_a, size, cudaMemcpyDeviceToHost);
   cudaMemcpy(b, dev_b, size, cudaMemcpyDeviceToHost);
   cudaMemcpy(c, dev_c, size, cudaMemcpyDeviceToHost);

   for(int i = 0; i < N; i++)
   {
      for(int j = 0; j < N; j++)
      {
         printf("%i + %i \n", a[i][j],b[i][j]);
      }

   }
   
   for(int i = 0; i < N; i++)
   {
      for(int j = 0; j < N; j++)
      {
         printf("%i \n", c[i][j]);
      }

   }

   cudaFree(dev_a); 
   cudaFree(dev_b); 
   cudaFree(dev_c);
   free(a); 
   free(b); 
   free(c);
}

/*******************************************************************************
*******************************************************************************/
__global__ void matrixAdd (int *a, int *b, int *c) 
{
   int col = blockIdx.x * blockDim.x + threadIdx.x;
   int row = blockIdx.y * blockDim.y + threadIdx.y;
   int index = col * N + row;
   
   if (col < N && row < N) 
   {
      c[index] = a[index] + b[index];
   }
}


/*******************************************************************************
*******************************************************************************/
void RandomInit(int** data, int n)
{
   for(int i = 0; i < n; ++i)
   {
      for(int j = 0; j < n; ++j)
      {
         data[i][j] = rand()%(int)100;
      }
   }
}

/*******************************************************************************
*******************************************************************************/
void InitData(int** data, int n)
{
   for (int i = 0; i < N; ++i)
   {
      data[i] = (int*) malloc((N) * sizeof(int));
      if (data[i] == NULL)
      {
         printf("ERROR(%s, %d): Speicher konnte nicht alloziiert werden.\n",
                __FILE__, __LINE__);
      }
   }
}

Vielen Dank im vorraus
 
es könnte auch mit der größe zu tun haben bei der initialisierung von c.

leider imme noch keine Lösung gefunden
 
Nur keinen Stress ;-)
Bei welchen i bzw. j-Werten bricht denn das Programm ab?

Gruss
cwriter

//EDIT:
Bei der InitData() ist der Parameter 'n', du verwendest aber in der Funktion 'N'. Das ist zwar in diesem Fall nicht so schlimm, in anderen Fällen aber schon.
 
Zuletzt bearbeitet:
Wie schon cwriter gesagt hat, bei den Funktionen musst du das kleine n verwenden.

Am Ende des Programmes reicht nicht ein free(), du musst für jedes malloc() ein free() machen, das heißt auch wie beim malloc() eine schleife und die einzelnen Pointer freigeben und anschließend den pointer auf den pointer.

Ich habe das Programm bei mir einmal getestet, hab aber alle Sachen, die Cude betreffen entfernt, da ich über diese Bibliothek nicht verfüge und es funktioniert bei mir. Ich vermute also, dass dein Problem etwas mit dieser Cuda Bibliothek zu tun hat. Vielleicht wird der c Pointer irgendwo verstellt?

Lg
 
das mit dem malloc free war mir bewusst ist aber untergegangen beim programmieren. Danke für diesen Tipp. Auch danke für den Tipp mit dem "n".

Dennoch besteht das Problem. ich weiß nicht an welcher stelle er abbricht. Wenn ihr die host variablen nicht dynamisch anlegt sondern int a[N][N] b[N][N] c[N][N] funktioniert das programm auch.

Hat keiner eine idee? Es ist eine Pointer geschichte da bin ich mir fast sicher weil sonst wäre das problem auch ohne malloc.
 
Aber du hast schon einen Debugger angehängt, oder?
Welche Programme nutzt du denn? Welches System?

Gruss
cwriter
 
Aber du hast schon einen Debugger angehängt, oder?
Welche Programme nutzt du denn? Welches System?

Gruss
cwriter

Liest du überhaupt was ich schreibe? Ich bin dankbar das du mir hilfst aber die informationen sind alle schon da.

System: Linux
Sprache: C/C++
Compiler: nvcc
Compilerbefehl (linux): nvcc -g -o ll -lcudart ll.cu
Fehlerstelle: Printf ausgabe von C[ i ][ j ]

falls du den genauen fehler code meinst der beim debugen kommt dann sorry für die anschuldigung.

debug alles:
Code:
[Thread debugging using libthread_db enabled]
[New Thread 0x2aaaad16a700 (LWP 26501)]
[Context Create of context 0x6217f0 on Device 0]
[Launch of CUDA Kernel 0 (matrixAdd<<<(1,1,1),(5,5,1)>>>) on Device 0]
83 + 30
86 + 62
77 + 23
15 + 67
93 + 35
35 + 29
86 + 2
92 + 22
49 + 58
21 + 69
62 + 67
27 + 93
90 + 56
59 + 11
63 + 42
26 + 29
40 + 73
26 + 21
72 + 19
36 + 84
11 + 37
68 + 98
67 + 24
29 + 15
82 + 70

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401027 in main () at ll.cu:65
65               printf("%i \n", c[i][j]);

Fehler:
Code:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000401027 in main () at ll.cu:65
65               printf("%i \n", c[i][j]);
 
Achso, printf() wird gar nie ausgeführt. Dann sind i und j == 0, was bedeutet, dass man nicht aus dem allozierten Bereich hinausgeht, sondern der Bereich falsch oder gar nicht alloziert wurde. Oder dann hat irgendwas den Speicher zerschossen.

Was liefern denn die cudaMemcpy-Funktionen zurück? Alle cudaSuccess?
Liefert das malloc() von c auch != NULL zurück?
Ich vermute den Wurm allerdings in der MatrixAdd() bzw. der folgenden cudaMemcpy().
Ersetze in der InitData() mal das
C:
data[i] = (int*) malloc((N) * sizeof(int));
durch
C:
data[i] = (int*) calloc(N, sizeof(int));
So können wir sichergehen, dass es nicht an nicht-initialisierten Werten liegt.
Denn grundsätzlich funktionieren a und b ja, da sie in standard-c initialisiert wurden. c jedoch wird zur Zeit lediglich von cudaMemcpy() initialisiert.

Eine Frage zum Code allgemein hätte ich noch: Auf Zeile 48/49 kopierst du nicht-veränderte Werte wieder zum Ursprungsort. Muss das sein?

Es tut mir leid, dass ich nicht gleich eine Lösung habe und manchmal lieber öfters nachfrage als etwas falsches als die Lösung zu verkaufen, aber immer ins Blaue zu raten ist auch nicht lustig.

Gruss
cwriter
 
Zurück