我遇到了一个性能问题atomicAdd
,float
在int
使用nv-nsight-cu-cli
. 检查生成的 SASS 后,我发现共享内存的生成 SASS 是打开的atomicAdd
,float
并且int
完全不相似。
在这里,我以最小的 cuda 代码展示了一个示例:
$ cat test.cu
__global__ void testAtomicInt() {
__shared__ int SM_INT;
SM_INT = 0;
__syncthreads();
atomicAdd(&(SM_INT), ((int)1));
}
__global__ void testAtomicFloat() {
__shared__ float SM_FLOAT;
SM_FLOAT = 0.0;
__syncthreads();
atomicAdd(&(SM_FLOAT), ((float)1.1));
}
$ nvcc -arch=sm_86 -c test.cu
$ cuobjdump -sass test.o
Fatbin elf code:
================
arch = sm_86
code version = [1,7]
producer = <unknown>
host = linux
compile_size = 64bit
code for sm_86
Function : _Z15testAtomicFloatv
.headerflags @"EF_CUDA_SM86 EF_CUDA_PTX_SM(EF_CUDA_SM86)"
/*0000*/ MOV R1, c[0x0][0x28] ; /* 0x00000a0000017a02 */
/* 0x000fc40000000f00 */
/*0010*/ STS [RZ], RZ ; /* 0x000000ffff007388 */
/* 0x000fe80000000800 */
/*0020*/ BAR.SYNC 0x0 ; /* 0x0000000000007b1d */
/* 0x000fec0000000000 */
/*0030*/ LDS R2, [RZ] ; /* 0x00000000ff027984 */
/* 0x000e240000000800 */
/*0040*/ FADD R3, R2, 1.1000000238418579102 ; /* 0x3f8ccccd02037421 */
/* 0x001fcc0000000000 */
/*0050*/ ATOMS.CAST.SPIN R3, [RZ], R2, R3 ; /* 0x00000002ff03738d */
/* 0x000e240001800003 */
/*0060*/ ISETP.EQ.U32.AND P0, PT, R3, 0x1, PT ; /* 0x000000010300780c */
/* 0x001fda0003f02070 */
/*0070*/ @!P0 BRA 0x30 ; /* 0xffffffb000008947 */
/* 0x000fea000383ffff */
/*0080*/ EXIT ; /* 0x000000000000794d */
/* 0x000fea0003800000 */
/*0090*/ BRA 0x90; /* 0xfffffff000007947 */
/* 0x000fc0000383ffff */
/*00a0*/ NOP; /* 0x0000000000007918 */
..........
Function : _Z13testAtomicIntv
.headerflags @"EF_CUDA_SM86 EF_CUDA_PTX_SM(EF_CUDA_SM86)"
/*0000*/ MOV R1, c[0x0][0x28] ; /* 0x00000a0000017a02 */
/* 0x000fc40000000f00 */
/*0010*/ STS [RZ], RZ ; /* 0x000000ffff007388 */
/* 0x000fe80000000800 */
/*0020*/ BAR.SYNC 0x0 ; /* 0x0000000000007b1d */
/* 0x000fec0000000000 */
/*0030*/ ATOMS.POPC.INC.32 RZ, [URZ] ; /* 0x00000000ffff7f8c */
/* 0x000fe2000d00003f */
/*0040*/ EXIT ; /* 0x000000000000794d */
/* 0x000fea0003800000 */
/*0050*/ BRA 0x50; /* 0xfffffff000007947 */
/* 0x000fc0000383ffff */
/*0060*/ NOP; /* 0x0000000000007918 */
..........
Fatbin ptx code:
================
arch = sm_86
code version = [7,5]
producer = <unknown>
host = linux
compile_size = 64bit
compressed
从上面生成的 SASS 代码中,我们可以清楚地得知,共享内存atomicAdd
在int
生成单个轻量级ATOMS.POPC.INC.32 RZ, [URZ]
,而在float
生成一堆 SASS 时具有重量级ATOMS.CAST.SPIN R3, [RZ], R2, R3
。
CUDA Binary Utilities没有告诉我CAST
or的含义SPIN
。但是,我猜想这意味着共享内存地址上的独占自旋锁。(纠正我,如果我猜错了。)在我的真实代码中,没有一个 SASSatomicAdd
有int
热点。但是,这比ofATOMS.CAST.SPIN
生成的其他 SASS 代码要热得多。atomicAdd
float
另外,我用编译器标志-arch=sm_86
和. 在那些 CC 下,生成的 SPSS 代码非常相似。另一个事实是,毫不奇怪, 的生成的SPSS 与.-arch=sm_80
-arch=sm_75
atomicAdd
float
atomicAdd
double
float
这个观察比问题更让我困惑。我会从我的分析经验中提出一些简单的问题,并希望我们能进行愉快的讨论。
- 具体是做什么
ATOMS.CAST.SPIN
的?我知道的唯一 SASS 文档是CUDA Binary Utilities。 - 为什么
atomicAdd
of应该float
生成更多的 SASS 代码并做更多的工作int
?我知道这是一个普遍的问题,很难回答。也许ATOMS.POPC.INC
根本不适用于数据类型float
或double
? - 如果它更容易受到更多共享内存加载和存储冲突的影响,因此of比of 的停顿时间更长?前者显然有更多要执行的指令和不同的分支。我的项目中有以下代码片段,其中两个函数的函数调用次数相同。然而,of在开启时不会造成运行时瓶颈。
atomicAdd
float
atomicAdd
int
atomicAdd
float
int
atomicAdd(&(SM_INT), ((int)1)); // no hotspot
atomicAdd(&(SM_FLOAT), ((float)1.1)); // a hotspot