我在GeForce GTX 580(Fermi-class)GPU上遇到了以下问题。
为了让您了解背景,我正在读取以以下方式打包的单字节样本文件:实数(信号1),虚数(信号1),实数(信号2),虚数(信号2)。 (每个字节都是有符号字符,取值范围在-128和127之间。)我将它们读入char4数组中,并使用下面给出的内核将它们复制到对应于每个信号的两个float2数组中。 (这只是更大程序的一个孤立部分。)
当我使用cuda-memcheck运行程序时,我会得到不合格的未指定的启动失败
,或者在随机线程和块索引处出现相同的消息,以及用户堆栈溢出或断点命中
或无效__global__写入大小8
。
下面再次复制主要内核和与启动相关的代码。奇怪的是,这段代码在我可以访问的非Fermi-class GPU上工作正常(且cuda-memcheck没有抛出错误)。我观察到的另一件事是,当N
小于16384时,Fermi没有出现任何错误。
#define N 32768
int main(int argc, char *argv[])
{
char4 *pc4Buf_h = NULL;
char4 *pc4Buf_d = NULL;
float2 *pf2InX_d = NULL;
float2 *pf2InY_d = NULL;
dim3 dimBCopy(1, 1, 1);
dim3 dimGCopy(1, 1);
...
/* i do check for errors in the actual code */
pc4Buf_h = (char4 *) malloc(N * sizeof(char4));
(void) cudaMalloc((void **) &pc4Buf_d, N * sizeof(char4));
(void) cudaMalloc((void **) &pf2InX_d, N * sizeof(float2));
(void) cudaMalloc((void **) &pf2InY_d, N * sizeof(float2));
...
dimBCopy.x = 1024; /* number of threads in a block, for my GPU */
dimGCopy.x = N / 1024;
CopyDataForFFT<<<dimGCopy, dimBCopy>>>(pc4Buf_d,
pf2InX_d,
pf2InY_d);
...
}
__global__ void CopyDataForFFT(char4 *pc4Data,
float2 *pf2FFTInX,
float2 *pf2FFTInY)
{
int i = (blockIdx.x * blockDim.x) + threadIdx.x;
pf2FFTInX[i].x = (float) pc4Data[i].x;
pf2FFTInX[i].y = (float) pc4Data[i].y;
pf2FFTInY[i].x = (float) pc4Data[i].z;
pf2FFTInY[i].y = (float) pc4Data[i].w;
return;
}
我在我的程序中还发现一件事情,那就是如果我将内核中的任意两个char-to-float赋值语句注释掉,就不会出现内存错误。 我在我的程序中还发现一件事情,那就是如果我注释掉内核中的前两个或后两个char-to-float赋值语句中的一个,就不会出现内存错误。如果我从前两个中注释掉一个 (pf2FFTInX
),从后两个中注释掉另一个 (pf2FFTInY
),错误仍然会出现,但出现的频率较低。当四个赋值语句都未被注释时,内核使用了6个寄存器,当有两个赋值语句被注释时,使用了5 4 个寄存器。
我尝试了32位工具包代替64位工具包、使用-m32
编译器选项进行32位编译、在没有X窗口的情况下运行等,但程序行为始终相同。
我在RHEL 5.6上使用CUDA 4.0驱动程序和运行时 (也尝试过CUDA 3.2)。GPU计算能力为2.0。
请帮帮忙!如果有人有兴趣在他们的Fermi卡上运行它,我可以发布整个代码。
更新:只是为了好玩,在 pf2FFTInX
和pf2FFTInY
赋值语句之间插入了一个__syncthreads()
,对于N
=32768,内存错误就消失了。但是在N
=65536时,仍然会出现错误。<--
这没有持续很久。仍然出现错误。
更新:继续出现奇怪的行为,当我使用cuda-memcheck运行程序时,屏幕上随机分布着这些16x16个多种颜色像素的块。如果我直接运行程序,则不会发生这种情况。