CUDA 地址越界

标签 c cuda gpu

我一直在玩一个简单的 CUDA 程序,它只是将全局内存清零。下面是设备代码和主机代码:

#include <stdio.h>

__global__ void kernel(float *data, int width) {
    int x = blockDim.x * blockIdx.x + threadIdx.x;
    int y = blockDim.y * blockIdx.y + threadIdx.y;

    if (x > (width-1)) {
        printf("x = %d\n", x);
        printf("blockDim.x = %d\n", blockDim.x);
        printf("blockIdx.x = %d\n", blockIdx.x);
        printf("threadIdx.x = %d\n", threadIdx.x);
    }   

    if (y > (width-1)) {
        printf("y = %d\n", y);
        printf("blockDim.y = %d\n", blockDim.y);
        printf("blockIdx.y = %d\n", blockIdx.y);
        printf("threadIdx.y = %d\n", threadIdx.y);
    }   

    data[y * width + x] = 0.0;
}

int main(void) {
    const int MATRIX_SIZE = 256;
    float *data, *dataGPU;
    int sizeOfMem;
    int x = MATRIX_SIZE;
    int y = MATRIX_SIZE;

    cudaDeviceReset();
    cudaDeviceSynchronize();

    sizeOfMem = sizeof(float) * x * y;

    data = (float *)malloc(sizeOfMem);
    cudaMalloc((void **)&dataGPU, sizeOfMem);

    cudaMemcpy(dataGPU, data, sizeOfMem, cudaMemcpyHostToDevice);

    //int threads = 256;
    //int blocks = ((x * y) + threads - 1) / threads;

    dim3 threads(16, 16);
    dim3 blocks(x / 16, y / 16);

    kernel<<<blocks, threads>>>(dataGPU, MATRIX_SIZE);
    cudaThreadSynchronize();

    cudaMemcpy(data, dataGPU, sizeOfMem, cudaMemcpyDeviceToHost);

    cudaFree(dataGPU);

    free(data);

    return 0;
}

当使用 cuda-memcheck 运行我的代码时,我继续收到地址越界错误消息。但这仅适用于我创建的矩阵的维度为 128 或更大的情况。如果我的维度小于 128,则错误发生的频率较低(我几乎从未收到错误)。您可能会注意到我在内核函数中包含了 print 语句。只有当我收到错误消息时才会打印这些语句,因为 x 和 y 永远不应大于 width-1,或者在本例中为 255。如果我正确地完成了我的数学运算,那么这个语句是正确的,我相信我做到了。以下是我从 cuda-memcheck 收到的错误消息:

  ========= CUDA-MEMCHECK
  ========= Invalid __global__ write of size 4
  =========     at 0x00000298 in kernel(float*, int)
  =========     by thread (3,10,0) in block (15,1,0)
  =========     Address 0x2300da6bcc is out of bounds
  =========     Saved host backtrace up to driver entry point at kernel launch time
  =========     Host Frame:/usr/lib64/nvidia/libcuda.so.1 (cuLaunchKernel + 0x2c5) [0x472225]
  =========     Host Frame:./test_reg_memory [0x16c41]
  =========     Host Frame:./test_reg_memory [0x31453]
  =========     Host Frame:./test_reg_memory [0x276d]
  =========     Host Frame:./test_reg_memory [0x24f0]
  =========     Host Frame:/lib64/libc.so.6 (__libc_start_main + 0xf5) [0x21b15]
  =========     Host Frame:./test_reg_memory [0x25cd]
  =========
  y = 2074
  blockDim.y = 16
  blockIdx.y = 1
  threadIdx.y = 10

这个输出对我来说没有意义,因为如果我计算一下,

y = blockDim.y * blockIdx.y + threadIdx.y = 16 * 1 + 10 = 26 (not 2074)

我花了一些时间查看 CUDA 编程论坛,但似乎没有任何帮助。我读到的一个线程表明我可能损坏了寄存器内存。但是,启动该线程的线程在使用不同的 GPU 时会出现此问题。该线程有点不相关,但我还是包含了链接。

https://devtalk.nvidia.com/default/topic/498784/memory-corruption-on-a-fermi-class-gpu-error-only-on-fermis-program-works-on-non-fermis-/?offset=6

下面我包含了 nvcc 版本。

 nvcc: NVIDIA (R) Cuda compiler driver
 Copyright (c) 2005-2015 NVIDIA Corporation
 Built on Tue_Aug_11_14:27:32_CDT_2015
 Cuda compilation tools, release 7.5, V7.5.17

此外,这是我正在使用的 GPU。

 Device 0: "GeForce GT 640"
 CUDA Driver Version / Runtime Version 8.0 / 7.5
 CUDA Capability Major/Minor version number: 3.0

任何有 CUDA 经验的人都可以指出我可能做错的地方吗?

最佳答案

这个问题似乎仅限于特定系统并且是由某种硬件问题引起的。代码本身没有问题,更改为不同的系统后确认它可以正常工作。

[此答案已从评论中汇集并添加为社区 wiki 条目,以将他的问题从 CUDA 标记的未回答队列中移除]。

关于CUDA 地址越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36786191/

相关文章:

c - 为什么我从 libusb 批量传输的 usb 输出中收到 0 字节的数据?

c - Realloc - 分配时不兼容的类型

c - 追踪 cuda 内核寄存器的使用

cuda - 使用cudaMalloc分配矩阵

optimization - 在 TensorFlow 中进行多 GPU 训练有什么优势?

ubuntu - 在 ubuntu 14.04 上找不到 libsiftgpu.so

c - 在两个 digis 数组之间执行求和

cuda - CUDA 中的动态共享内存

memory - 达到理论 GPU 全局内存带宽

c - 使用 C 中的 pthread 库为大数组开发合并排序