Умножение матриц с использованием CUDA - PullRequest
8 голосов
/ 16 февраля 2011

Я поражен умножением матриц на CUDA. Результирующая матрица продуктов всегда равна нулю. Я прочитал несколько примеров кодов, таких как умножение матриц в cuda для решения моей проблемы, но все напрасно.

Помимо ошибочного результата 0, максимальный размер "Width" (код ниже) даже не 512. Я не смог отладить, где проблема. Может быть, мы можем обсудить это на StackOverflow.

Я имею в виду "Программирование массово параллельных процессоров"

#include<cuda.h>
#include<stdio.h>

int main(void) {
    void MatrixMultiplication(float *, float *, float *, int);
    const int Width = 5;
    float M[Width*Width], N[Width*Width], P[Width*Width];
    for(int i = 0; i < (Width*Width) ; i++) {
        M[i] = 5;
        N[i] = 5;
        P[i] = 0;
    }
    MatrixMultiplication(M, N, P, Width);
    for(int i = 0; i < (Width*Width) ; i++) {
        printf("%d \n", P[i]);
    }
    int quit;
    scanf("%d",&quit);
    return 0;
}

//Matrix multiplication kernel - thread specification
__global__ void MatrixMulKernel(float *Md, float *Nd, float *Pd, int Width) {
    //2D Thread ID
    int tx = threadIdx.x;
    int ty = threadIdx.y;

    //Pvalue stores the Pd element that is computed by the thread
    float Pvalue = 0;

    for(int k = 0; k < Width ; ++k) {
        float Mdelement = Md[ty*Width + k];
        float Ndelement = Nd[k*Width + tx];
        Pvalue += (Mdelement*Ndelement);
    }

    Pd[ty*Width + tx] = Pvalue;
}

void MatrixMultiplication(float *M, float *N, float *P, int Width) {
    int size = Width*Width*sizeof(float);
    float *Md, *Nd, *Pd;

    //Transfer M and N to device memory
    cudaMalloc((void**)&Md, size);
    cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice);
    cudaMalloc((void**)&Nd, size);
    cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice);

    //Allocate P on the device
    cudaMalloc((void**)&Pd,size);

    //Setup the execution configuration
    dim3 dimBlock(Width,Width);
    dim3 dimGrid(1,1);

    //Launch the device computation threads!
    MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width);

    //Transfer P from device to host
    cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost);

    //Free device matrices
    cudaFree(Md);
    cudaFree(Nd);
    cudaFree(Pd);
}

Ответы [ 3 ]

4 голосов
/ 17 февраля 2011

До этого момента все было в порядке:

for(int i = 0; i < (Width*Width) ; i++) {
    printf("%d \n", P[i]);
}

Я изменил его на% f (потому что он с плавающей точкой), и все они печатаются красиво:)

$ ./test.exe
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
125.000000
1 голос
/ 17 февраля 2011

Я понял, что случилось. Давайте проанализируем это:

Точка 1: квест по удалению монотонного "нулевого значения"

Как уже отмечалось, вы должны заменить printf("%d \n", P[i]); на printf("%f \n", P[i]);

Точка 2: почему происходит сбой программы со значением Width 512?

На самом деле это не удастся даже для небольшого значения, например 23. Почему? Потому что 23 * 23> 512 (максимальное количество потоков, которое может иметь графический процессор на блок на сегодняшний день!)

0 голосов
/ 17 февраля 2011

В вашей функции MatrixMulKernel ваш цикл for имеет вид

for(int k = 0; k < Width ; ++k) 
{
    //rest of code      
}

Вместо Width, вы должны использовать Width*Width, поскольку ваш массив имеет размер Width*Width.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...