


























跑了下 5.5 xhigh 的说法,这应该不算 AI 答复吧。。:
这段代码确实有数据竞争;只是很多时候“看起来没错”,主要因为 GPU 的实际执行经常碰巧满足了你想要的顺序,尤其是同一个 warp 内。
关键点:
sum_buf 是 shared memory ,不是普通 cache 。它是 block 内所有 thread 共享的片上内存;一个 thread 写了,其他 thread 后续读是可以读到这个新值的。CUDA 不是因为“没有 cache coherence”所以读不到别的 thread 的写入。shared memory 的可见性和顺序要靠同步原语定义,尤其是 __syncthreads() 或 warp 内的 __syncwarp()。
你原代码的问题是这一句:
sum_buf[tid] = sum_buf[tid] + sum_buf[tid - iter];
同一轮里,tid=1 会写 sum_buf[1],而 tid=2 会读 sum_buf[1]。没有第二个 barrier 把“所有线程先读旧值”和“所有线程再写新值”隔开,所以 CUDA 语义上这是 race 。
为什么平时看不到的常见原因是:
同一个 warp 内很多指令近似 lockstep 执行。
编译后的指令通常是先 load ,再 add ,再 store 。
如果一个 warp 的所有 lane 基本一起执行 load ,那么 tid=2 很可能在 tid=1 store 之前已经读完旧的 sum_buf[1]。
小规模测试、固定输入、固定 GPU 架构上,调度顺序可能稳定,所以错误不暴露。
但这只是实现细节上的“碰巧”,不是 CUDA 保证。
问了下可能正确的代码:
```
for (int iter = 1; iter < 1024; iter *= 2) {
__syncthreads();
double x = 0.0;
if (tid >= iter) {
x = sum_buf[tid - iter];
}
__syncthreads();
if (tid >= iter) {
sum_buf[tid] += x;
}
}
```
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。