原文地址:http://blog.sina.com.cn/s/blog_70684c2a0100vjif.html
2.使用更少线程隐藏内存访问延迟
隐藏内存访问延迟,使用相同的说明方式,但针对内存操作。
所需并行度 = 延迟 * 吞吐量
所以隐藏内存延迟意味着保持100KB的数据读取速率,当然如果kernel是计算限制(compute bound)的,则这个数值可以变小。
那么,多少线程可以达到100KB呢,有多种方法:
1.
2.
3.
每个线程做更多的工作,则线程数量可以更少:每个线程取回(fetch)4 Byte,需要25000个线程,取回100B,仅需要1000个线程。
经验验证:
每个线程拷贝一个浮点数:
运行多个线程块,通过动态分配共享内存来控制SM占用率。
每个线程拷贝单个浮点数(GTX480)
只能通过最大化占用率来隐藏延迟吗?不,也可以每个线程做更多的并行工作。
注意,线程并不会被存储访问阻塞,它只会因为数据依赖性而阻塞。
每个线程拷贝2个浮点数
虚线部分为原曲线,所以我们可以减少占用率了。
注意,本地数组会尽量分配在寄存器中,以下是每个线程拷贝4个浮点数
可以看到,仅仅25%的占用率就足够了,那么我们究竟能做到什么程度?
以下是拷贝8个浮点数:
每个线程拷贝8个float2型数据
每个线程拷贝8个float4型数据
只通8%的占用率就达到了87%的pin带宽!
每个线程拷贝14个float4型数据
只通过4%的占用率就达到了峰值的84%。
有两种方法来隐藏内存访问开销
谬误:“低占用率常常会影响GPU隐藏内存延迟的能力,从而导致性能下降。”(CUDA Best Practices Guide)。
我们刚才看到,仅仅4%的占用率就可以达到峰值的84%,注意这已经超过了cudaMemcpy所能达到的最好性能(71%)。
谬误:“一般来说,需要更多的warps,如果对片下内存的访问指令比例。。。”(CUDA Programming Guide)错,
我们刚才看到了,在一个内存访问密集型的kernel中,每个SM仅仅只有4个warps就可以达到87%的内存性能峰值。