我最近碰到了Uncorrectable ECC error所示的问题。简而言之,我不时会收到 Uncorrectable ECC error ,而我的动态并行代码会产生不正确的结果。无法纠正的ECC错误最可能的假设是损坏的驱动程序堆栈,这也被另一个用户的经验间接证实(参见上面的帖子)。我现在想面对第二个问题,即算法问题。为此,我正在处理下面报告的重现器,由于原始代码生成不正确的结果使用动态并行,因此也使用此CUDA功能。
我没有看到这个代码有任何明显的问题。我认为关于子内核启动的同步应该没问题:第一个__syncthreads()
不应该是必需的,cudaDeviceSynchronize()
应该确保子内核的所有内存写入都在{{1}之前完成}}
我的问题是:这个代码是错误的还是错误的结果是由于非编程问题?
我的配置:CUDA 5.0,Windows 7,4-GPU系统配备Kepler K20c,驱动程序327.23。
printf
答案 0 :(得分:2)
我很确定你超过launch pending limit。几乎不可能按原样判断你的代码,但是我修改了它并在子内核启动时添加了错误检查。
当我这样做时,我会发现启动错误,由打印输出!
表示。跳过启动错误案例,我对P1[m]
与m
的所有内核检查都会通过(我根本没有*
打印输出。)
#include <stdio.h>
#define K 6
#define BLOCK_SIZE 256
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) { exit(code); }
}
}
int iDivUp(int a, int b) { return ((a % b) != 0) ? (a / b + 1) : (a / b); }
__global__ void child_kernel(unsigned long long* P1)
{
int m = threadIdx.x;
P1[m] = (unsigned long long)m;
}
__global__ void parent_kernel(double* __restrict__ x, int M)
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
if(i<M) {
unsigned long long* P1 = new unsigned long long[13];
dim3 dimBlock(2*K+1,1); dim3 dimGrid(1,1);
__syncthreads();
child_kernel<<<dimGrid,dimBlock>>>(P1);
cudaDeviceSynchronize();
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess) printf("!");
else for(unsigned long long m=0; m<dimBlock.x; m++) if (P1[m] != m) printf("*");
}
}
int main() {
const int M = 19000;
//gpuErrchk(cudaSetDevice(0));
double* x = (double*)malloc(M*sizeof(double));
for (int i=0; i<M; i++) x[i] = (double)i;
double* d_x; gpuErrchk(cudaMalloc((void**)&d_x,M*sizeof(double)));
gpuErrchk(cudaMemcpy(d_x,x,M*sizeof(double),cudaMemcpyHostToDevice));
dim3 dimBlock(BLOCK_SIZE,1); dim3 dimGrid(iDivUp(M,BLOCK_SIZE));
parent_kernel<<<dimGrid,dimBlock>>>(d_x,M);
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
return 0;
}
随意在父内核中添加err
变量的进一步解码,以说服自己超过启动暂挂限制。作为另一项测试,您可以在主机代码中将M
设置为2048而不是19000,并且所有!
打印输出都会消失。 (启动待定限制默认值== 2048)
正如我在评论中所述,我认为无法纠正的ECC错误是一个单独的问题,我建议尝试在评论中链接的驱动程序321.01。