Cuda 开普勒如何实施全球原子操作?使用gmem比使用原子学的性能要差

Cuda 开普勒如何实施全球原子操作?使用gmem比使用原子学的性能要差,cuda,gpu-atomics,Cuda,Gpu Atomics,我想知道全球原子学在开普勒的实施情况 请参见这段代码: 1. if (threadIdx.x < workers) { 2. temp = atomicAdd(dst, temp + rangeOffset); 3. if (isLastPartialCalc(temp)) { 4. atomicAdd(dst,-300000.0f); 5. } 6. } 1。if(螺纹IDX.x

我想知道全球原子学在开普勒的实施情况

请参见这段代码:

1. if (threadIdx.x < workers) {
2.    temp = atomicAdd(dst, temp + rangeOffset);
3.    if (isLastPartialCalc(temp)) {                            
4.        atomicAdd(dst,-300000.0f);
5.    }
6. }
1。if(螺纹IDX.x<工人){
2.温度=原子添加(dst,温度+量程偏移);
3.如果(isLastPartialCalc(temp)){
4.atomicAdd(dst,-300000.0f);
5.    }
6. }
如果我为此更改第4行:

*dst-=300000.0f

性能较低!更改是安全的,因为不再有线程写入此值(输出相同)

使用原子的内核:~883us 直接使用gmem的内核:~903us

我已经跑了好几次了,每次换车我都会被罚20美元

更新
似乎没有使用原子的存储总是在L2中产生未命中,而原子版本总是产生命中。。。因此,我猜在L2中不允许尝试写入标记为“原子”的位置(或其他位置),并且它会向gmem发出另一个请求此缓存线更新显然比第二次全局原子访问成本更高(在您的特定代码中)

从单个SM到开普勒GK110(例如K20)上的全局内存的单个全局原子访问实际上相当快

如图所示,与费米相比,开普勒提高了全球原子学的速度

提高了到公共全局内存地址的原子操作吞吐量 每时钟9倍于一次操作

原子学有“火和遗忘”的语义。这意味着内核调用原子操作并让实际的原子操作由缓存执行(不在SM上),并且内核将在下一条指令上移动,而不等待实际的原子操作完成。这仅在原子操作没有返回值时有效,本例就是这样。fire-and-forget语义允许SM继续进行计算,将原子的计算卸载到缓存中


如果另一个线程不打算使用该位置,这非常好。它还提供了让一个线程快速处理多个数据位置的可能性,因为如果您按顺序执行多个原子操作,线程就可以直接触发它们。将它们放在相邻的内存中,合并可能会减少内存带宽。

谢谢Robert,但原子操作是在L2中执行的,对吗?我的内核中的所有存储都是使用原子操作执行的。缓存命中率相当高(实际上是100%),除非我做了更改。