如何在不将输入矩阵的大小限制为块大小的倍数的情况下进行矩阵乘法?

时间:2019-02-20 14:34:11

标签: c matrix-multiplication

我需要修改代码,以消除输入矩阵的尺寸必须为块大小的倍数的限制,但不知道如何执行此操作。

我要遵循的指南说要对此 main 方法进行更改,但是据我所知, main 中的代码只是填充数组并调用内核。

下面是我的代码,它是一个基本的矩阵乘法计算器。

#include <stdio.h>
#include <stdlib.h>

#include <cuda.h>
#define BLOCK_SIZE 16

// Matrices are stored in row-major order
typedef struct {
int width;
int height;
float* elements;
} Matrix;

__global__ void MatrixMultKern(const Matrix A, const Matrix B, const Matrix C) {
    // Calculate the column index of C and B
    int col = blockIdx.x * blockDim.x + threadIdx.x;
    // Calculate the row index of C and of A
    int row = blockIdx.y * blockDim.y + threadIdx.y;

    if ((row < A.height) && (col < B.width)) {
        float Cvalue = 0;
        // each thread computes one element of the block sub-matrix
        for (int k = 0; k < A.width; ++k) {
            Cvalue += A.elements[row * A.width + k] * B.elements[k*B.width + col];
        }
        C.elements[row * C.width + col] = Cvalue;
    }
}

// Matrix multiplication - Host Code
// Matrix dimensions are assumed to be multiples of BLOCK_SIZE
void MatrixMult(const Matrix h_A, const Matrix h_B, Matrix h_C)
{
    // Load A and B into device memory
    Matrix d_A;
    d_A.width = h_A.width; d_A.height = h_A.height;
    size_t size = h_A.width * h_A.height * sizeof(float);
    cudaMalloc(&d_A.elements, size);
    cudaMemcpy(d_A.elements, h_A.elements, size, cudaMemcpyHostToDevice);

    Matrix d_B;
    d_B.width = h_B.width; d_B.height = h_B.height;
    size = h_B.width * h_B.height * sizeof(float);
    cudaMalloc(&d_B.elements, size);
    cudaMemcpy(d_B.elements, h_B.elements, size, cudaMemcpyHostToDevice);

    // Allocate C in Device memory
    Matrix d_C;
    d_C.width = h_C.width; d_C.height = h_C.height;
    size = h_C.width * h_C.height * sizeof(float);
    cudaMalloc(&d_C.elements, size);

    // Invoke Kernel
    dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
    dim3 dimGrid(d_B.width / dimBlock.x, d_A.height / dimBlock.y);
    MatrixMultKern<<< dimGrid, dimBlock >>>(d_A, d_B, d_C);

    // Read C from Device to Host
    cudaMemcpy(h_C.elements, d_C.elements, size, cudaMemcpyDeviceToHost);

    // Free Device Memory
    cudaFree(d_A.elements);
    cudaFree(d_B.elements);
    cudaFree(d_C.elements);
}

int main(int argc, char* argv[]) {
    Matrix A, B, C;
    // Read Dimensions of A and B
    A.height = atoi(argv[1]);
    A.width = atoi(argv[2]);
    B.height = A.width;
    B.width = atoi(argv[3]);

    //Allocate memory
    A.elements = (float*)malloc(A.width * A.height * sizeof(float));
    B.elements = (float*)malloc(B.width * B.height * sizeof(float));
    C.height = A.height;
    C.width = B.width;
    C.elements = (float*)malloc(C.width * C.height * sizeof(float));

    //populates arrays with random numbers
    for(int i = 0; i < A.height; i++)
        for(int j = 0; j < A.width; j++)
            A.elements[i*A.width + j] = (float)(rand() % 3);
    for(int i = 0; i < B.height; i++)
        for(int j = 0; j < B.width; j++)
            B.elements[i*B.width + j] = (float)(rand() % 2);
    MatrixMult(A, B, C);

    for(int i = 0; i < A.height; i++){
        for(int j = 0; j < A.width; j++)
            printf("%f ", A.elements[i*A.width + j]);
        printf("\n");
    }
    printf("\n");
    for(int i = 0; i < B.height; i++){
        for(int j = 0; j < B.width; j++)
            printf("%f ", B.elements[i*B.width + j]);
        printf("\n");
    }
    printf("\n");
    for(int i = 0; i < C.height; i++){
        for(int j = 0; j < C.width; j++)
            printf("%f ", C.elements[i*C.width + j]);
        printf("\n");
    }
    printf("\n");

    return 0;
}

0 个答案:

没有答案