我一直在玩一个简单的 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 = %dn", x);
printf("blockDim.x = %dn", blockDim.x);
printf("blockIdx.x = %dn", blockIdx.x);
printf("threadIdx.x = %dn", threadIdx.x);
}
if (y > (width-1)) {
printf("y = %dn", y);
printf("blockDim.y = %dn", blockDim.y);
printf("blockIdx.y = %dn", blockIdx.y);
printf("threadIdx.y = %dn", 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 经验的人都可以指出我可能做错了什么吗?
此问题似乎仅限于特定系统,并且是由某种硬件问题引起的。代码本身很好,更改为其他系统确认它工作正常。
[此答案已从评论中收集而成,并作为社区维基条目添加,以将他的问题从 CUDA 标签的未回答队列中移除]。