GPU加速优化之前,我们先看看GPU的性能衡量。
- FLOPS
- Occupancy
FLOPS(Floating-point-operations-per-second)
每秒浮点运算量,是衡量GPU硬件计算能力的指标。
Occupancy
占有率,每个SM的活动线程束(possible active warps)数量与实际的活动线程束(active warps)数量的比值。它是衡量CUDA硬件执行效率的指标。CUDA上的线程指令是串行执行的。因此,在某些warp被暂停或者阻塞的时候,启动另外的warp来保持硬件的busy,对于提升硬件执行效率来说非常重要。
尽管更高的占有率并不总是意味着更高的效率,但是低的占有率却会影响掩盖内存延迟的能力,进而引起效率的退化。当占有率达到50%后,我们不会再寻求通过提高占有率来提升效率。
影响Occupancy的因素有3个:
寄存器资源(register availability, thread私有)
Register 保存了线程中的局部变量,具有最低的存取延迟。但是能分配给SM上每个block以及每个thread的寄存器数量是有限的。Registers是一次性被分给一个block。如果每个thread拥有太多寄存器,则能驻存与SM上的block数量就会减少,从而降低Occupancy。因此每个thread能拥有的寄存器数目设置非常关键,这个值可以在编译时通过maxrregcount或者__lauch_bounds_手动设置。nvcc --ptxas options=v 可以查看每个kernel的每个线程的可用寄存器数量。
共享内存资源(shared memory,block内的thread共享)
通常,一个kernel要求的shared memeory是和block size有关的。每个block的thread是共享shared memory。分配给单个block的shared memory越多,则SM上能驻存的block越少,则Occupancy就会下降。
SM最大并发threads数量,SM最大并发warps数量,SM最大并发blocks数量
SM对于最大并发thread数,最大并发warps数,最大并发blocks数都是有限制的。如果这些数量超过了限制值,则多出的thread和warp和block就会等待,直到轮到自己的时候才开始工作。这样的话SM是无法到达Occupancy的理论最大值的,且性能也会降低。