到目前为止,我们已经学会了如何编写CUDA内核函数,以及如何通过大量线程配置和协调其执行。在本章中,我们将研究如何组织和定位数据,以便通过大量线程进行高效访问。我们在第2章中讨论了数据并行计算,即数据首先从主机内存传输到设备全局内存。在第3章,可扩展并行执行中,我们确定了如何使用其块索引和线程索引来指导线程从全局内存中访问其部分数据。我们还探索了资源分配和线程调度。虽然我们涵盖的范围是一个非常好的开始,但到目前为止,我们学到的CUDA内核可能只能实现底层硬件潜在速度的一小部分。**性能不佳可归因于全局内存的长访问延迟(数百个时钟周期)和有限访问带宽,这通常使用动态随机访问存储器实现。**虽然有许多线程可用于执行,理论上可以容忍长内存访问延迟,但人们很容易遇到global内存访问路径中的流量拥塞阻止除极少数线程外的所有线程进行进度,从而使一些流式多处理器(SM)闲置。为了规避这种拥塞,CUDA提供了许多额外的资源和方法来访问内存,这些资源和方法可以删除进出全局内存的大部分流量。在本章中,您将学习使用不同的内存类型来提高CUDA内核的执行效率。
我们可以通过计算图3.8中图像模糊内核代码中执行次数最多的部分的预期性能水平来说明内存访问效率的影响。在图4.1.中复制。就执行时间而言,内核最重要的部分是嵌套的for-loop,它通过模糊补丁执行像素值累积。
在内部循环的每次迭代中,都会为一个浮点加法执行一个全局内存访问。全局内存访问获取in[]数组元素。浮点加入操作将in[]数组元素的值累积到pixVal