CUDA:sum[0]的值随每次执行而变化 \uuuu全局\uuuuu无效gpu热量(浮点*h,浮点*g,浮点*sum,整数N){ 国际nbx,bx,nby,by; 浮差=0.0; nbx=(N-2)/blockDim.x; bx=nbx/gridDim.x; nby=(N-2)/blockDim.y; by=nby/gridDim.y; 无符号整数ii=blockIdx.x*blockDim.x+threadIdx.x; 无符号int jj=blockIdx.y*blockDim.y+threadIdx.y; 无符号整数jid=(ii)*(N-2)+(jj); 对于(inti=1+ii*bx;i>=1){ 如果(jid
您正在启动具有多个块的GPU内核。当一个块中的线程仍在第一个CUDA:sum[0]的值随每次执行而变化 \uuuu全局\uuuuu无效gpu热量(浮点*h,浮点*g,浮点*sum,整数N){ 国际nbx,bx,nby,by; 浮差=0.0; nbx=(N-2)/blockDim.x; bx=nbx/gridDim.x; nby=(N-2)/blockDim.y; by=nby/gridDim.y; 无符号整数ii=blockIdx.x*blockDim.x+threadIdx.x; 无符号int jj=blockIdx.y*blockDim.y+threadIdx.y; 无符号整数jid=(ii)*(N-2)+(jj); 对于(inti=1+ii*bx;i>=1){ 如果(jid,c,cuda,reduction,C,Cuda,Reduction,您正在启动具有多个块的GPU内核。当一个块中的线程仍在第一个for循环中计算其sum时,其他一些块可能在第二个for循环中并行缩减。这两个for循环具有数据依赖性。因为块的调度r流式多处理器发生在幕后,每次运行可能会有所不同,每次都会得到不同的结果。\uuu syncthreads();betweenfor循环同步块内的线程,但在多个块之间没有同步机制或指令,除非返回主机并发出另一个内核 在您的情况下,即使您只是为循环分离,您将得到的结果仍然可能是错误的,因为您的缩减发生在多个块上,并且块的调度
for
循环中计算其sum
时,其他一些块可能在第二个for
循环中并行缩减。这两个for
循环具有数据依赖性。因为块的调度r流式多处理器发生在幕后,每次运行可能会有所不同,每次都会得到不同的结果。\uuu syncthreads();
betweenfor
循环同步块内的线程,但在多个块之间没有同步机制或指令,除非返回主机并发出另一个内核
在您的情况下,即使您只是为循环分离
,您将得到的结果仍然可能是错误的,因为您的缩减发生在多个块上,并且块的调度也不是确定性的。您可以发布内核的函数调用,以及用于初始化内核的网格和块参数吗,正如上面所说,这有助于找出它失败的原因,但如果它改变了每次调用,这意味着你的代码中存在竞争条件!@Bharat我已经添加了你所要求的代码部分。@1---1是的,似乎有。如果我简单地注释掉内核的缩减部分,并在CPU中累积和矩阵,它将是fine:/无法找出问题所在。@1---1我已经解决了问题。很明显,这是因为我在同一个内核中减少了求和矩阵,并且没有将求和矩阵的访问限制为一个线程块。因此产生了某种竞争条件。现在我使用单独的内核调用来减少“求和”而且它工作正常。尽管如此,我仍然不确定它生成争用条件的确切原因。感谢您的澄清。我错误地认为syncthreads()与cudaDeviceSynchronize()一样同步内核的所有线程。
__global__ void gpu_Heat (float *h, float *g, float * sum, int N) {
int nbx, bx, nby, by;
float diff = 0.0;
nbx = (N-2)/blockDim.x;
bx = nbx/gridDim.x;
nby = (N-2)/blockDim.y;
by = nby/gridDim.y;
unsigned int ii = blockIdx.x*blockDim.x+threadIdx.x;
unsigned int jj = blockIdx.y*blockDim.y+threadIdx.y;
unsigned int jid = (ii)*(N-2)+(jj);
for (int i=1+ii*bx; i<=min((ii+1)*bx, N-2); i++)
for (int j=1+jj*by; j<=min((jj+1)*by, N-2); j++) {
g[i*N+j]= 0.25 * (h[ i*N + (j-1)]+
h[ i*N +(j+1) ]+
h[ (i-1)*N + j]+
h[ (i+1)*N + j]);
diff = g[i*N+j] - h[i*N+j];
sum[(i-1)*(N-2)+(j-1)] = diff * diff;
}
__syncthreads();
for(unsigned int s=((N-2)*(N-2))/2; s>0; s>>=1){
if(jid<s){
sum[jid]+=sum[jid+s];
}
__syncthreads();
}
}
dim3 Grid = (16,16);
dim3 Block = (16,16);
gpu_Heat<<<Grid,Block>>>(dev_u, dev_uhelp, dev_sum, np);
cudaThreadSynchronize(); // wait for all threads to complete
cudaErrorCheck(cudaMemcpy(param.u,dev_u,np*np*sizeof(float),cudaMemcpyDeviceToHost));
cudaErrorCheck(cudaMemcpy(param.uhelp,dev_uhelp,np*np*sizeof(float),cudaMemcpyDeviceToHost));
cudaErrorCheck(cudaMemcpy(sum,dev_sum,sum_size*sizeof(float),cudaMemcpyDeviceToHost));