Cuda Pointer

Alpha63

Mitglied
Hallo,

ich würde gerne bei meinem Cuda Projekt structuren verwenden bei der Matrixaddition.
Leider funktioniert das nicht. Kann einer helfen? Ich denke mal das der Fehler bei cudaMemcpy liegt oder generell mit den Pointern.

Main.c
Code:
/*******************************************************************************
*******************************************************************************/
int main() 
{
   /*---------------------------------------------------------------------------
   * Host variables have the prefix h.
   * Device variables have the prefix d.
   --------------------------------------------------------------------------*/
   MATRIX* h_a;
   MATRIX* h_b;
   MATRIX* h_c;
   int i, j;

   /*---------------------------------------------------------------------------
    * Initial 2 Dim array with random values.
    --------------------------------------------------------------------------*/
   h_a = (MATRIX*) malloc(sizeof(MATRIX));
   h_a->width  = 4;
   h_a->height = 4;
   h_a->elements = (int*) malloc(h_a->width * h_a->height * sizeof(int));
   RandomInit(&h_a);
   /*---------------------------------------------------------------------------*/
   h_b = (MATRIX*) malloc(sizeof(MATRIX));
   h_b->width  = 4;
   h_b->height = 4;
   h_b->elements = (int*) malloc(h_b->width * h_b->height * sizeof(int));
   RandomInit(&h_b);
   /*-------------------------------------------------------------------------*/
   h_c = (MATRIX*) malloc(sizeof(MATRIX));
   h_c->width  = 4;
   h_c->height = 4;
   h_c->elements = (int*) malloc(h_c->width * h_c->height * sizeof(int));
   
   matrixAdd(h_a, h_b, h_c);
   
   printMatResult(h_a);
   printf("   +\n");
   printMatResult(h_b);
   printf("============================\n");
   printMatResult(h_c);

   DeleteMat(h_a);
   DeleteMat(h_b);
   DeleteMat(h_c);
   
   return 0;
}

Main funktioniert.
ich denke in der.cu datei ist der fehler.
Code:
extern "C" int matrixAdd(const MATRIX* A, const MATRIX* B, MATRIX* C)
{
   /*---------------------------------------------------------------------------
    * Device variables have the prefix d.
    --------------------------------------------------------------------------*/  
   MATRIX* d_A;
   int size_a = A->height * A->width * sizeof(int);
   /*-------------------------------------------------------------------------*/
   MATRIX* d_B;
   int size_b = B->height * B->width * sizeof(int);
   /*-------------------------------------------------------------------------*/
   MATRIX* d_C;
   int size_c = C->height * C->width * sizeof(int);

   /*---------------------------------------------------------------------------
    * initialize a, b and c on the device (NOT SHOWN).
    --------------------------------------------------------------------------*/
   cudaMalloc((void**)&d_A, size_a);
   cudaMalloc((void**)&d_B, size_b);
   cudaMalloc((void**)&d_C, size_c);

   cudaMemcpy(d_A, A, size_a, cudaMemcpyHostToDevice);
   cudaMemcpy(d_B, B, size_b, cudaMemcpyHostToDevice);
   cudaMemcpy(d_C, C, size_c, cudaMemcpyHostToDevice);

   dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
   dim3 dimGrid(B->height / dimBlock.x, A->width / dimBlock.y);

   // kernel
   matrixAddKernel<<<dimGrid,dimBlock>>>(d_A, d_B, d_C);
   cudaThreadSynchronize();

   // find a error
   check_cuda_errors(__FILE__, __LINE__);

   // Read C from device memory  
   cudaMemcpy(C, d_C, size_c, cudaMemcpyDeviceToHost);
   
   // Free device memory   
   cudaFree(d_A);
   cudaFree(d_B);
   cudaFree(d_C);

   return 0;
}

kernel aufruf der auch angepasst werden muss wegen den Pointern denk ich mal.

Code:
/*******************************************************************************
*******************************************************************************/
__global__ void matrixAddKernel(const MATRIX* A, const MATRIX* B, MATRIX* 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->elements[index] = A->elements[index] + B->elements[index];
   }
}

hoffe einer kann mir helfen.
 
Hallo

Wie immer mit der Prämisse, dass ich das nicht testen kann.

C:
h_a = (MATRIX*) malloc(sizeof(MATRIX));
h_a->width  = 4;
h_a->height = 4;
h_a->elements = (int*) malloc(h_a->width * h_a->height * sizeof(int));
RandomInit(&h_a);
//-----------oder---------------------
MATRIX* d_A;
int size_a = A->height * A->width * sizeof(int);
cudaMalloc((void**)&d_A, size_a);
Du hast einen Pointer auf die struct(?) MATRIX, d.h. der ist unter x86 4 Byte und unter x64 8 Byte gross. MATRIX dürfte 2 ints und einen int* beinhalten, wenn ich mir den Code so anschaue. Das sind 2*4 Bytes und einmal 4 oder 8 Bytes. Wenn du nun die Höhe und die Breite zusammen mit 4 Bytes (=sizeof(int)) multiplizierst, kommst du auf 4^3=64 Bytes. Passt gerade. Doch damit hast du erst
C:
d_A = (MATRIX*)(malloc(sizeof(MATRIX));
gemacht. Wie ich das sehe, müsstest du den Pointer von d_A->elements auch noch korrekt initialisieren.
Also im Klartext:
C:
cudaMalloc((void**)&d_A, sizeof(MATRIX)); //oder d_A = (MATRIX*)(malloc(sizeof(MATRIX));
cudaMalloc((void**)&d_A->elements,size_a);

cudaMemcpy(d_A, A, sizeof(MATRIX), cudaMemcpyHostToDevice);
cudaMemcpy(d_A->elements, A->elements, size_a, cudaMemcpyHostToDevice);

Wie gesagt ungetestet. Es würde helfen, könntest du sagen, was genau denn geschieht.

Gruss
cwriter
 
Zuletzt bearbeitet:
Im anhang ist der Komplette Code mit Makefile.

Benötigt wird ein cuda compiler und gcc.

Hoffe das hilft weiter. Deine Lösung funktioniert leider erstmal nicht. Programm wird unter Linux Programmiert.
 

Anhänge

  • matrixCuda.zip
    9,6 KB · Aufrufe: 7
das ganze programm funktioniert ohne pointer einwandfrei. daraum bin ich mir sehr sicher das es ein pointer problem ist. weil seit ich heute damit angefangen habe wieder mal dran rum zu doktor ist es zerschossen.
 
Gut, ich habe das ganze mal etwas überarbeitet, die CUDA-Teile umgeschrieben, damit es auch bei mir läuft.
C:
//main.c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>

#include "matrix_cuda.h"

/*******************************************************************************
*******************************************************************************/

int addElement(int index, const MATRIX* m1, const MATRIX* m2)
{
	return m1->elements[index] + m2->elements[index];
}

int matrixAdd(const MATRIX* A, const MATRIX* B, MATRIX* C)
{
   /*---------------------------------------------------------------------------
    * Device variables have the prefix d.
    --------------------------------------------------------------------------*/  
	int integ = 0;
	int integ2 = 0;
   MATRIX* d_A;
   int size_a = A->height * A->width * sizeof(int);
   /*-------------------------------------------------------------------------*/
   MATRIX* d_B;
   int size_b = B->height * B->width * sizeof(int);
   /*-------------------------------------------------------------------------*/
   MATRIX* d_C;
   int size_c = C->height * C->width * sizeof(int);
 
   /*---------------------------------------------------------------------------
    * initialize a, b and c on the device (NOT SHOWN).
    --------------------------------------------------------------------------*/
   d_A = (MATRIX*)malloc(sizeof(MATRIX));
   d_A->elements = (int*)malloc(size_a);
   d_B = (MATRIX*)malloc(sizeof(MATRIX));
   d_B->elements = (int*)malloc(size_b);
   d_C = (MATRIX*)malloc(sizeof(MATRIX));
   d_C->elements = (int*)malloc(size_c);
   
   memcpy(d_A,A,sizeof(MATRIX));
   memcpy(d_A->elements,A->elements,size_a);
   memcpy(d_B,B,sizeof(MATRIX));
   memcpy(d_B->elements,B->elements,size_b);
   memcpy(d_C,C,sizeof(MATRIX));

   while(integ < C->width)
   {
	   integ2 = 0;
	   while(integ2 < C->height)
	   {
		   d_C->elements[integ2*C->height + integ] = addElement(integ2*C->height + integ,A,B);
		   integ2++;
	   }
	   integ++;
   }

  //Hier habe ich einen grossen Teil rausgeschnitten
   
   memcpy(C,d_C,sizeof(MATRIX));
   
   // Free device memory   
	free(d_A);
	free(d_B);
	free(d_C);
   return 0;
}

int main() 
{
   /*---------------------------------------------------------------------------
   * Host variables have the prefix h.
   * Device variables have the prefix d.
   --------------------------------------------------------------------------*/
   MATRIX* h_a;
   MATRIX* h_b;
   MATRIX* h_c;
   int i, j;
   //int N = 10;
   //int M = 10;
   //int BLOCK_DIM = 4;
   //int BLOCK_DIM_M = 4;

   /*---------------------------------------------------------------------------
    * Initial 2 Dim array with random values.
    --------------------------------------------------------------------------*/
   h_a = (MATRIX*) malloc(sizeof(MATRIX));
   h_a->width  = 4;
   h_a->height = 4;
   h_a->elements = (int*) malloc(h_a->width * h_a->height * sizeof(int));
   RandomInit(&h_a);
   /*---------------------------------------------------------------------------*/
   h_b = (MATRIX*) malloc(sizeof(MATRIX));
   h_b->width  = 4;
   h_b->height = 4;
   h_b->elements = (int*) malloc(h_b->width * h_b->height * sizeof(int));
   RandomInit(&h_b);
   /*-------------------------------------------------------------------------*/
   h_c = (MATRIX*) malloc(sizeof(MATRIX));
   h_c->width  = 4;
   h_c->height = 4;
   h_c->elements = (int*) malloc(h_c->width * h_c->height * sizeof(int));
   
   //matrixInvertAdd(h_a, h_c);
   matrixAdd(h_a, h_b, h_c);
   
   printMatResult(h_a);
   printf("   +\n");
   printMatResult(h_b);
   printf("============================\n");
   printMatResult(h_c);

  // matrix_invert(h_a, h_b, N);
  // printMat(h_a, N);
   DeleteMat(h_a);
   DeleteMat(h_b);
   DeleteMat(h_c);

   _getch();
   return 0;
}
Geht das bei dir?
Wenn ja kannst du die Teile wieder zum CUDA-Standard umschreiben.
Die Allozierung des Speichers scheint ein Problem gewesen zu sein, allerdings hätte mein voriger Vorschlag in diesem Fall schon geholfen...
Was genau macht die matrixAddKernel()?

Gruss
cwriter
 
Alpha63 hat gesagt.:
naja der kernel berechnet eine matrix addition auf der gpu
Habe ich mir beinahe gedacht. Ich finde dazu aber keine Dokumentation, ausser:
https://sites.google.com/site/5kk73gpu2012/examples/example-memory-access-grouping

Und dort werden die Pointer direkt behandelt, d.h., dass die Werte direkt übergeben werden müssen.
C:
//Demnach müsste das hier
matrixAddKernel<<<dimGrid,dimBlock>>>(d_A, d_B, d_C);
//das hier sein:
matrixAddKernel<<<dimGrid,dimBlock>>>(d_A->elements, d_B->elements, d_C->elements);

Aber der Code in meinem letzten Post funktioniert bei dir schon, oder?

Gruss
cwriter
 
Zurück