CUDA内核线程未执行完整内层循环的问题咨询
CUDA内核内层循环执行异常问题分析
首先看你提供的CUDA内核代码:
__global__ void bodyForce(Body *p, float dt, int n) { int index = threadIdx.x + (blockDim.x * blockIdx.x); int stride = blockDim.x * blockIdx.x; for (int i = index; i < n; i+= stride) { float Fx = 0.0f; float Fy = 0.0f; float Fz = 0.0f; for (int j = 0; j < n; j++) { float dx = p[j].x - p[i].x; float dy = p[j].y - p[i].y; float dz = p[j].z - p[i].z; float distSqr = dx*dx + dy*dy + dz*dz + SOFTENING; float invDist = rsqrtf(distSqr); float invDist3 = invDist * invDist * invDist; Fx += dx * invDist3; Fy += dy * invDist3; Fz += dz * invDist3; } p[i].vx += dt*Fx; p[i].vy += dt*Fy; p[i].vz += dt*Fz; } }
你的理解本身没错:每个线程分配到外层循环的一个i后,确实应该完整执行内层循环直到j达到n。问题出在stride的计算错误:
你当前写的stride = blockDim.x * blockIdx.x完全错误,正确的stride应该是整个CUDA网格的总线程数,也就是:
int stride = blockDim.x * gridDim.x;
错误的stride会导致外层循环逻辑彻底混乱:
- 如果当前线程所在的
blockIdx.x为0,stride会变成0,外层循环的i += stride会让i永远等于初始的index,线程陷入死循环,表现为内层循环一直卡在某个位置反复执行。 - 如果
blockIdx.x不为0,stride会是一个远大于合理值的数,外层循环可能只执行一次甚至直接跳出,让你误以为内层循环没正常执行。
修正stride的计算后,每个线程会正确处理i = index, index+stride, index+2*stride...这些元素,且每个元素对应的内层循环会完整执行到j=n。
额外提一句:当i==j时,dx/dy/dz都为0,这部分计算对最终的力没有贡献,后续优化时可以跳过这部分循环,能节省一定的计算资源。
内容的提问来源于stack exchange,提问作者SvnddA
相关产品推荐
相关产品推荐

