簡體   English   中英

用於矩陣加法的Cuda程序

[英]Cuda program for Matrix addition

我正在嘗試制作一個非常簡單的程序來執行矩陣加法。 我將代碼分為兩個文件,一個main.cu文件和一個matrix.cuh頭文件。 代碼是:

在main.cu:

#include <iostream>
#include <cuda.h>

#include "Matriz.cuh"

using std:: cout;

int main(void)
{

    Matriz A;
    Matriz B;
    Matriz *C = new Matriz;
    int lin = 10;
    int col = 10;

    A.lin = lin;
    A.col = col;
    B.lin = lin;
    B.col = col;
    C->lin = lin;
    C->col = col;
    C->matriz = new double[lin*col];

    A.matriz = new double[lin*col];
    B.matriz = new double[lin*col];

    for (int ii = 0; ii < lin; ii++)
        for (int jj = 0; jj < col; jj++)
        {
            A.matriz[jj*A.lin + ii] = 1./(float)(10.*jj + ii + 10.0);
            B.matriz[jj*B.lin + ii] = (float)(jj + ii + 1);
        }

    somaMatriz(A, B, C);

    for (int ii = 0; ii < lin; ii++)
    {
        for (int jj = 0; jj < col; jj++)
            cout << C->matriz[jj*C->lin + jj] << " ";
        cout << "\n";
    }

    return 0;

}

在matrix.cuh:

#include <cuda.h>
#include <iostream>
using std::cout;

#ifndef MATRIZ_CUH_
#define MATRIZ_CUH_

typedef struct{
    double *matriz;
    int    lin;
    int    col;
} Matriz;

__global__ void addMatrix(const Matriz A, const Matriz B, Matriz C)
{
    int idx = threadIdx.x + blockDim.x*gridDim.x;
    int idy = threadIdx.y + blockDim.y*gridDim.y;

    C.matriz[C.lin*idy + idx] = A.matriz[A.lin*idx + idy] + B.matriz[B.lin*idx + idy];
}

void somaMatriz(const Matriz A, const Matriz B, Matriz *C)
{
    Matriz dA;
    Matriz dB;
    Matriz dC;

    int BLOCK_SIZE = A.lin;

    dA.lin = A.lin;
    dA.col = A.col;
    dB.lin = B.lin;
    dB.col = B.col;
    dC.lin = C->lin;
    dC.col = C->col;

    cudaMalloc((void**)&dA.matriz, dA.lin*dA.col*sizeof(double));
    cudaMalloc((void**)&dB.matriz, dB.lin*dB.col*sizeof(double));
    cudaMalloc((void**)&dC.matriz, dC.lin*dC.col*sizeof(double));

    cudaMemcpy(dA.matriz, A.matriz, dA.lin*dA.col*sizeof(double), cudaMemcpyHostToDevice);
    cudaMemcpy(dB.matriz, B.matriz, dB.lin*dB.col*sizeof(double), cudaMemcpyHostToDevice);

    dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
    dim3 dimGrid(dA.lin/dimBlock.x, dA.col/dimBlock.y);

    addMatrix<<<dimGrid, dimBlock>>>(dA, dB, dC);

    cudaMemcpy(C->matriz, dC.matriz, dC.lin*dC.col*sizeof(double), cudaMemcpyDeviceToHost);
    cudaFree(dA.matriz);
    cudaFree(dB.matriz);
    cudaFree(dC.matriz);

   return;
}

#endif /* MATRIZ_CUH_ */

我得到的是:無論我做什么,矩陣C都充滿了。 我正在使用此程序來了解如何在GPU程序中使用可變大小的矩陣。 我的代碼有什么問題?

每當您遇到CUDA代碼問題時,最好執行正確的cuda錯誤檢查並使用cuda-memcheck運行代碼。 當我使用cuda-memcheck運行您的代碼時,我得到指示,表明內核正在嘗試進行越界讀取操作。 由於內核非常簡單,因此這意味着索引計算必須不正確。

您的程序至少需要進行兩項更改才能使其適用於小平方矩陣:

  1. 內核中A,B和C的索引計算應全部相同:

     C.matriz[C.lin*idy + idx] = A.matriz[A.lin*idx + idy] + B.matriz[B.lin*idx + idy]; 

    像這樣:

     C.matriz[C.lin*idy + idx] = A.matriz[A.lin*idy + idx] + B.matriz[B.lin*idy + idx]; 
  2. 您在內核中創建的x / y索引不正確:

     int idx = threadIdx.x + blockDim.x*gridDim.x; int idy = threadIdx.y + blockDim.y*gridDim.y; 

    他們應該是:

     int idx = threadIdx.x + blockDim.x*blockIdx.x; int idy = threadIdx.y + blockDim.y*blockIdx.y; 

通過上述更改,我能夠獲得合理的外觀輸出。

您的設置代碼似乎也無法正確處理較大的矩陣:

int BLOCK_SIZE = A.lin;
...
dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
dim3 dimGrid(dA.lin/dimBlock.x, dA.col/dimBlock.y);

您可能想要類似的東西:

int BLOCK_SIZE = 16;
...
dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
dim3 dimGrid((dA.lin + dimBlock.x - 1)/dimBlock.x, (dA.col + dimBlock.y -1)/dimBlock.y);

進行這些更改后,您應該向內核添加有效的線程檢查,如下所示:

__global__ void addMatrix(const Matriz A, const Matriz B, Matriz C)
{
    int idx = threadIdx.x + blockDim.x*blockIdx.x;
    int idy = threadIdx.y + blockDim.y*blockIdx.y;

    if ((idx < A.col) && (idy < A.lin))
      C.matriz[C.lin*idy + idx] = A.matriz[A.lin*idx + idy] + B.matriz[B.lin*idx + idy];
}

我也沒有驗證您是否將所有尺寸與適當的行或林限制進​​行了正確比較。 這是要驗證非平方矩陣的其他方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM