使用 CUDA 进行矩阵操作

Matrix manipulation using CUDA

我正在尝试使用 C/CUDA 编写一个矩阵计算程序。 我有以下程序:

在main.cu

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

int main(void)
{
 const int Ndofs = 2;
 const int Nel   = 4;
 double *Gh   = new double[Ndofs*Nel*Ndofs*Nel];
 double *Gg;
 cudaMalloc((void**)& Gg, sizeof(double)*Ndofs*Nel*Ndofs*Nel);
 for (int ii = 0; ii < Ndofs*Nel*Ndofs*Nel; ii++)
  Gh[ii] = 0.;
 cudaMemcpy(Gh, Gg, sizeof(double)*Ndofs*Nel*Ndofs*Nel, cudaMemcpyHostToDevice);
 integraG<<<256, 256>>>(Nel, Gg);
 cudaMemcpy(Gg, Gh, sizeof(double)*Ndofs*Nel*Ndofs*Nel, cudaMemcpyDeviceToHost);
 for (int ii = 0; ii < Ndofs*Nel*Ndofs*Nel; ii++)
  cout << ii  + 1 << " " << Gh[ii] << "\n";
 return 0;
}

在mtrx.cuh

#ifndef TESTE_CUH_
#define TESTE_CUH_

__global__ void integraG(const int N, double* G)
{

    const int szmodel = 2*N;
    int idx = threadIdx.x + blockIdx.x*blockDim.x;
    int idy = threadIdx.y + blockIdx.y*blockDim.y;
    int offset = idx + idy*blockDim.x*gridDim.x;
    int posInit = szmodel*offset;

    G[posInit + 0] = 1;
    G[posInit + 1] = 1;
    G[posInit + 2] = 1;
    G[posInit + 3] = 1;
}

#endif

结果(应该是一个用 1 填充的矩阵)被复制回主机数组;问题是:没有任何反应!显然,我的程序没有调用 gpu 内核,我仍然得到一个全为零的数组。

我是 CUDA 编程的新手,我正在使用 CUDA 示例 (Jason Sanders) 作为参考书。

我的问题是:

  1. 我的代码有什么问题?
  2. 这是使用矩阵向量化形式使用 GPU 处理矩阵的最佳方式吗?
  3. 是否有其他参考资料可以提供更多关于使用 GPU 的矩阵的示例?

这些是你的问题:

我的代码有什么问题?

这是使用矩阵矢量化形式使用 GPU 处理矩阵的最佳方式吗?

是否有其他参考资料可以提供更多关于使用 GPU 的矩阵的示例?

关于你的第一个问题。首先,您的问题应该明确定义。你想用这段代码做什么?你想在矩阵上做什么样的计算?

尝试正确检查错误 THIS 是一个很好的方法。您的代码中也有一些明显的错误。你的一些错误:

  1. 您将错误的地址指针传递给 cudaMemcpy,传递给源和目标的指针必须相互交换,检查 here

将它们更改为:

  1. "NdofsNelNdofs*Nel"说明你对数组的前64个数字的值感兴趣,那么为什么要调用256个线程和256个块?

  2. 您的这部分代码:

    int idx = threadIdx.x + blockIdx.xblockDim.x; int idy = threadIdx.y + blockIdx.yblockDim.y;

表明你想使用2-Dim线程和块;为此,您需要使用 Dim 类型。

通过进行以下更改:

 cudaMemcpy(Gg, Gh, sizeof(double)*Ndofs*Nel*Ndofs*Nel, cudaMemcpyHostToDevice); //HERE
 dim3 block(2,2); //HERE
 dim3 thread(4,4); //HERE
 integraG<<<block, thread>>>(Nel, Gg); //HERE
 cudaMemcpy(Gh, Gg, sizeof(double)*Ndofs*Nel*Ndofs*Nel, cudaMemcpyDeviceToHost); //HERE

您将得到如下结果:

1 1
2 1
3 1
4 1
5 0
6 0
7 0
8 0
9 1
10 1
11 1
12 1
.
.
.
57 1
58 1
59 1
60 1
61 0
62 0
63 0
64 0

总之,如果你把你的问题和目标说的更清楚,可以给你更好的建议。

关于你最后两个问题:

在我看来 CUDA C PROGRAMMING GUIDE and CUDA C BEST PRACTICES GUIDE 是开始使用 CUDA 时必须阅读的两个文档,它们还包括矩阵计算的示例。