我最近遇到了Uncorrectable ECC error所示的问题。简而言之,我不时收到一个不可纠正的ECC错误,我的动态并行代码会产生不正确的结果。不可纠正的ECC错误的最可能的假设是驱动程序堆栈已损坏,这也已被另一用户的经验间接证实(参见上面的帖子)。现在我想面对第二个问题,即算法问题。为此,我正在处理下面报告的重现器,由于生成不正确结果的原始代码使用动态并行性,因此也使用此CUDA特性。错误的CUDA动态并行代码结果
我没有看到这个代码的任何明显的问题。我认为关于子内核启动的同步应该是正确的:第一个__syncthreads()
不应该是必需的,并且cudaDeviceSynchronize()
应该确保子内核的所有内存写入在printf
之前完成。
我的问题是:这段代码是错误的还是错误的结果是由于非编程问题?
我的配置:CUDA 5.0,Windows 7,4 GPU系统,配备Kepler K20c,驱动程序327.23。
#include <stdio.h>
#include <conio.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) { getch(); exit(code); }
}
}
int iDivUp(int a, int b) { return ((a % b) != 0) ? (a/b + 1) : (a/b); }
__global__ void child_kernel(double* P1)
{
int m = threadIdx.x;
P1[m] = (double)m;
}
__global__ void parent_kernel(double* __restrict__ x, int M)
{
int i = threadIdx.x + blockDim.x * blockIdx.x;
if(i<M) {
double* P1 = new double[13];
dim3 dimBlock(2*K+1,1); dim3 dimGrid(1,1);
__syncthreads();
child_kernel<<<dimGrid,dimBlock>>>(P1);
cudaDeviceSynchronize();
for(int m=0; m<2*K+1; m++) printf("%f %f\n",P1[m],(double)m);
}
}
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());
getch();
return 0;
}
当你说你有不正确的结果时,它们是什么?你确定这不像'printf'缓冲区溢出那么简单吗? – talonmies
@talonmies通常,第一次启动代码时,我会收到“或多或少”正确的结果,因为同一行中的两个数字大部分是重合的。随后我启动它,越来越多的'P1 [m]'与'(double)m'不同,具有不合理的'double'值。不,我不确定这不是'printf'缓冲区溢出。要检查它,我应该分流'printf'并使用调试器或将'P1'传递给'main',这是我在接下来几个小时内无法做的测试,因为机器暂时处于忙碌状态。 – JackOLantern
@talonmies但是,你能不能指出一些已知的方向来避免'printf'缓冲区溢出,这无论如何都很好知道? – JackOLantern