GPU 如何处理随机访问?

How do GPUs handle random access?

我阅读了一些关于如何在 opengl 4.3 计算着色器中实现光线追踪器的教程,这让我想起了困扰我一段时间的事情。 GPU 究竟如何处理实现类似功能所需的大量随机访问读取?每个流处理器都有自己的数据副本吗?似乎系统会因内存访问而变得非常拥塞,但这只是我自己的直觉,可能是不正确的。

流多处理器 (SM) 有缓存,但它们相对较小,无助于真正的随机访问。

相反,GPU 正试图掩盖内存访问延迟:也就是说,每个 SM 分配的执行线程数多于其内核数。在每个空闲时钟上,它都会安排一些未因内存访问而阻塞的线程。当线程所需的数据不在 SM 缓存中时,线程将停止,直到该数据到达,让其他线程执行。

请注意,此掩码仅在计算量超过等待数据所花费的时间(例如每像素光照计算)时才起作用。如果不是这种情况(例如,只是对大量 32 位浮点数求和),那么您可能会遇到内存总线带宽瓶颈,并且大多数时候您的线程将停止等待它们的位到达。

有助于 SM 利用率的相关内容是 data-locality。当多个线程访问附近的内存位置时,一次缓存行提取将带来多个线程所需的数据。例如,当对一个透视扭曲的三角形进行纹理处理时,即使每个片段的纹理坐标可以是 'random',附近的片段仍然可能从纹理中读取附近的纹素。因此,线程之间共享许多公共数据。

另一方面,光线追踪在数据局部性方面非常糟糕。二次射线往往会发散很多,并在几乎随机的位置撞击不同的表面。这使得很难将 SM 架构用于光线场景相交或着色目的。