c++ - CUDA 矩阵加法段错误

标签 c++ c nvidia cuda

我只是对我编写的 cuda 程序有疑问。它允许我输入矩阵的大小、列和行。假设我输入 ~1124 并且计算正常。但是说我输入 1149 它在设备中计算后出现段错误(我认为它是在复制回过程中出现段错误)。但是说我输入 2000 它会在设备中计算之前出现故障(我认为它会在复制过程中出现故障)。我认为我的问题全在于内存管理。如果你们能指出我正确的方向,我将不胜感激。

我更新了代码的调用方式。在新的编辑(底部)中,它包含:sumMatrix(空白矩阵,大小为 eleCount1,即整个矩阵的大小),matrixOne(第一个矩阵),matrixTwo(第二个矩阵,分配方式与 matrix1 相同) ,eleCount1(矩阵的整个大小)。 matrixOne 和 2 都是从文件中读入的。

不确定是否有人需要查看有关我的 GPU 的信息:

  • 常量内存总量:65536字节
  • 每个 block 的共享内存总量:49152 字节
  • 每个 block 可用的寄存器总数:32768
  • 经纱尺寸:32
  • 每个 block 的最大线程数:1024
  • block 的每个维度的最大尺寸:1024 x 1024 x 64
  • 网格每个维度的最大尺寸:65535 x 65535 x 65535

代码是:

void addKernel(float *c, float *a, float *b)
{
    int i = threadIdx.x;
    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    c[idx] = a[idx] + b[idx];
}
cudaError_t addWithCuda(float *c, float *a, float *b, size_t size)
{
  float *dev_a = 0;
  float *dev_b = 0;
  float *dev_c = 0;
  cudaError_t cudaStatus;
  blocksNeeded=(size/MAXTHREADS)+1;
  int threadsPerBlock = MAXTHREADS/blocksNeeded+1;
  cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(float));
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMalloc failed!");
      goto Error;
  }

  cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(float), cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

  cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(float), cudaMemcpyHostToDevice);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

  addKernel<<<blocksNeeded, size>>>(dev_c, dev_a, dev_b);
  cudaStatus = cudaDeviceSynchronize();

  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!\n", cudaStatus);
      goto Error;
  }
  cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(float), cudaMemcpyDeviceToHost);
  if (cudaStatus != cudaSuccess) {
      fprintf(stderr, "cudaMemcpy failed!");
      goto Error;
  }

Error:
  cudaFree(dev_c);
  cudaFree(dev_a);
  cudaFree(dev_b);

  return cudaStatus;
}
//edit: added how the matrix are allocated
    float* matrixOne = (float*)malloc(sizeof(float)*file1size);
int matrixIndex = 0;
readFromFile(fd,byte, matrixOneWidth, matrixOneHeight,  matrixOne);

//matrixOneHeight--;
eleCount1 = matrixOneHeight*matrixOneWidth;
matrixOne= (float*)realloc(matrixOne,eleCount1*sizeof(float));
//Edit: Added how the addWithCuda is called.
cudaStatus = addWithCuda(sumMatrix, matrixOne,matrixTwo,eleCount1);
//sumMatrix is created after we know how large the matrices are. 
float sumMatrix[eleCount1];

最佳答案

您没有在内核中测试计算范围。如果工作总量没有平均分配到一个 block 的大小,一些线程将尝试写入输出数组之外的索引。我建议你也将大小作为参数传递给内核并引入检查:

__global__ void addKernel(float *c, float *a, float *b, int size)
{
    int i = threadIdx.x;
    int idx = blockDim.x * blockIdx.x + threadIdx.x;
    if(idx < size) c[idx] = a[idx] + b[idx];
}

关于c++ - CUDA 矩阵加法段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8421678/

相关文章:

optimization - 分析时,大部分时间都花在 nvoglv64.dll 中。我应该推断出什么?

c++ - pthread_create 缓冲区大小。不够?

c++ - 从方法链中使用的临时 move

opengl - X失败的请求: BadMatch错误

cuda - 在应用程序运行时检查 CUDA MPS 服务器是否打开/关闭?

c - If 语句在 C KDMF 驱动程序中失败

c++ - 使用快速排序算法的类型问题

c++ - 如何在 Matlab 或 C++ 中实现简单的滑动窗口算法

c - 使用 autotools 时原始 .h 文件会发生什么情况?

c - 我如何使用 C 语言中的 stdarg 编写该代码