#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
ord_p
5. @talonmies вы были правы, я не заметил. но функция assert возвращает ошибку, которую я не могу найти.
Ответ №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;
-
Матричные операции в ваших вычислительных функциях не совпадают друг с другом. Ядро:
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;
Это имеет последствия для следующей проблемы.
-
malloc
не инициализирует данные. Поскольку эта операция создает выходной массив, который будет использоваться кодом хоста, который выполняет суммирование к нему, мы должны инициализировать это выделение нулем:h_p_seq=(int*)malloc(bytes); memset(h_p_seq, 0, bytes); // must add this line to initialize to zero
-
Вычисление размера ваших массивов в байтах слишком велико. Вы определили, что ваши массивы должны иметь тип
int
. Но ваш расчет размера выглядит следующим образом:size_t bytes=n*n*sizeof(bytes);
int
— это 4-байтовая величина, тогда какsize_t
переменная likebytes
— это 8-байтовая величина. Это не вызывает реальной проблемы, но в этом нет необходимости. Я бы предложил изменить его на:size_t bytes=n*n*sizeof(int);
С учетом вышеуказанных элементов ваш код работает корректно для меня.