Проблема с обнаружением проблемы в моем коде | CUDA c

#cuda

#cuda

Вопрос:

Мне трудно понять, где ошибка в моем коде.

Цель проекта — умножить две матрицы и сравнить время между последовательным и параллельным.

Когда я печатаю матрицы, я вижу, что матрица устройства в основном пуста.

Кроме того, я обработал матрицы как массив размером n * n .

Спасибо!

 //This program computes the multiplication of two Matrices  GPU using CUDA

#include <stdio.h>
#include <cassert>


__global__ void matrixMul(int * m,int * n,int * p,int size)
{
    //Calculate Row and Column
   int row=threadIdx.y*blockDim.y threadIdx.y;
    int column=threadIdx.x*blockDim.x threadIdx.x;
   int p_sum=0;

   for (int i = 0; i < size; i  )
   {
      p_sum  = m[row*size   i] * n[i*size  column];

   }
   p[row*size   column] = p_sum;

}

void matrixMul_seq(int * m,int * n,int * p,int size){
    for(int i = 0; i < size; i  ){
        for(int j = 0; j < size; j  ){
            for(int k = 0; k < size; k  ){
                p[i*size  j]  = m[i*size  k]  n[k*size  j];
            }
        }
    }
}



//Initialize matricies
void init_matricies(int * mat,int n){
    for(int i = 0; i < n; i  ) {
        for (int j = 0; j < n; j  )
        {
            mat[i*n j]=rand()24;
        }
        
    }
}

int main(int argc,char **argv)
{

   //Set our problem Size(Default = 2^10 == 1024)
   int n = 1<<10;
   printf("Square Matrix of size:%dn",n);

   //Size in Bytes
   size_t bytes=n*n*sizeof(bytes);

   //Host matricies
   int *h_m;
   int *h_p;    
   int *h_n;
   int *h_p_seq;
   //Host matricies
   int *d_m;
   int *d_p;    
   int *d_n;


   //Memory allocation for Host Matricies
   h_m=(int*)malloc(bytes);
   h_n=(int*)malloc(bytes);
   h_p=(int*)malloc(bytes);
   h_p_seq=(int*)malloc(bytes);



   init_matricies(h_m,n);
   init_matricies(h_n,n);

   //Allocate memory on device side
   cudaMalloc(amp;d_n, bytes);
   cudaMalloc(amp;d_m, bytes);
   cudaMalloc(amp;d_p, bytes);

   //Copy data to Device
   cudaMemcpy(d_m,h_m, bytes, cudaMemcpyHostToDevice);
   cudaMemcpy(d_n,h_n, bytes, cudaMemcpyHostToDevice); 

    
   int threads_per_block =16;
   dim3 block_size(threads_per_block,threads_per_block);
   dim3 grid_size( n / block_size.x , n / block_size.y);

   printf("Grid size  X:%d, Grid size y:%dn",grid_size.x,grid_size.y);
   printf("THE RESULT OF THE SIZES: 2^6 * 2^4 * 2^6 * 2^4  n");

   matrixMul <<<grid_size,block_size>>>(d_m,d_n,d_p,n);
   matrixMul_seq(h_m,h_n,h_p_seq,n);
   cudaMemcpy(h_p,d_p, bytes, cudaMemcpyDeviceToHost);   

    for(int i = 0; i < n; i  ){
        for(int j = 0; j < n; j  ){
        //printf("Grid size  X:%d, Grid size y:%dn",h_p[ n * i   j],h_p_seq[ n * i   j]);

            assert(h_p[ n * i   j]==h_p_seq[ n * i   j]);
    }
 }
    free(h_m);
    free(h_p);
    free(h_n);
    free(h_p_seq);

    cudaFree(d_m);
    cudaFree(d_n);
    cudaFree(d_p);
  

     return 0;
  

}
  

Комментарии:

1. Я не вижу выделения памяти устройства ни для одного из этих трех массивов на графическом процессоре. Как вы себе представляете, что это могло бы работать без них?

2. что вы имеете в виду?? для всех них есть распределение

3. size_t bytes=n n sizeof(байт); h_m=(int*)malloc(байт); h_n=(int*)malloc(байт); h_p =(int*)malloc(байт); h_p_seq=(int*)malloc(байт); cudaMemcpy (d_m, h_m, байт, cudaMemcpyHostToDevice); cudaMemcpy ( d_n,h_n, байты, cudaMemcpyHostToDevice); cudaMemcpy(h_p, d_p, байты, cudaMemcpyDeviceToHost);

4. Нигде в этом коде нет выделения d_m , d_n or d_p

5. @talonmies вы были правы, я не заметил. но функция assert возвращает ошибку, которую я не могу найти.

Ответ №1:

У вас есть множество проблем в вашем коде:

  1. Вы неправильно вычисляете переменные индекса ядра. Это неверно:

     int row=threadIdx.y*blockDim.y threadIdx.y;
    int column=threadIdx.x*blockDim.x threadIdx.x;
      

    это должно быть:

     int row=blockIdx.y*blockDim.y threadIdx.y;
    int column=blockIdx.x*blockDim.x threadIdx.x;
      
  2. Матричные операции в ваших вычислительных функциях не совпадают друг с другом. Ядро:

     p_sum  = m[row*size   i] * n[i*size  column];
                             ^
                             multiplication
      

    код хоста:

     p[i*size  j]  = m[i*size  k]  n[k*size  j];
                                 ^
                                 addition
      

    мы также наблюдаем, из приведенного выше, что основной код выполняет суммирование с выходной переменной ( = ), в то время как ядро выполняет присвоение выходной переменной ( = ):

     p[row*size   column] = p_sum;
      

    Это имеет последствия для следующей проблемы.

  3. malloc не инициализирует данные. Поскольку эта операция создает выходной массив, который будет использоваться кодом хоста, который выполняет суммирование к нему, мы должны инициализировать это выделение нулем:

     h_p_seq=(int*)malloc(bytes);
    memset(h_p_seq, 0, bytes);  // must add this line to initialize to zero
      
  4. Вычисление размера ваших массивов в байтах слишком велико. Вы определили, что ваши массивы должны иметь тип int . Но ваш расчет размера выглядит следующим образом:

     size_t bytes=n*n*sizeof(bytes);
      

    int — это 4-байтовая величина, тогда как size_t переменная like bytes — это 8-байтовая величина. Это не вызывает реальной проблемы, но в этом нет необходимости. Я бы предложил изменить его на:

     size_t bytes=n*n*sizeof(int);
      

С учетом вышеуказанных элементов ваш код работает корректно для меня.