有很多stackoverflow线程询问为什么使用纹理的内核不比使用全局内存访问的内核快。 答案和评论对我来说似乎总是有点深奥。
NVIDIA white paper on the Fermi architecture状态为白色黑色:
Fermi架构通过实现单个统一内存来应对这一挑战 请求加载和存储的路径,每个SM多处理器和统一的L2具有L1缓存 缓存为所有操作(加载,存储和纹理)提供服务。
那么为什么人们期望在费米设备上使用纹理存储器有任何加速,因为对于每次存储器获取(无论它是否与纹理绑定)都使用相同的L2高速缓存。实际上,对于大多数情况,直接访问全局内存应该更快,因为它也通过L1缓存,纹理提取不是。这也在stackoverflow上的一些相关问题中报告。
有人可以证实这一点或告诉我我缺少的东西吗?
答案 0 :(得分:8)
您忽略了每个Streaming Multiprocessor都有纹理缓存(请参见下图,说明Fermi的Streaming Multiprocessor)。
纹理缓存与L1 / L2缓存具有不同的含义,因为它针对数据位置进行了优化。数据局部性适用于必须访问有关常规,笛卡尔,1D,2D或3D网格的语义(非物理)相邻点的数据的所有情况。为了更好地解释这个概念,请考虑下图,说明二维或三维有限差分计算中涉及的模板
计算红点处的有限差分涉及访问与蓝点相关的数据。现在,这些数据不是红点的物理邻居,因为当将2D或3D阵列展平为1D时,它们不会在物理存储器中连续地物理存储。但是,它们是红点的语义邻居,而纹理内存正好适合缓存这些值。另一方面,当必须经常访问相同的数据或其物理邻居时,L1 / L2缓存很好。
奖牌的另一面是纹理缓存与L1 / L2缓存相比具有更高的延迟,因此,在某些情况下,不使用纹理可能不会导致性能的显着恶化,这要归功于L1 / L2缓存机制。从这个角度来看,纹理在早期的CUDA架构中具有最重要的意义,当时全局内存读取没有被缓存。但是,如Is 1D texture memory access faster than 1D global memory access?所示,费米的纹理记忆值得使用。
答案 1 :(得分:3)
如果通过纹理读取的数据是2D或3D,则CUDA阵列的块线性布局通常比间距线性布局提供更好的重用,因为缓存行包含2D或3D数据块而不是行。
但即使对于1D数据,纹理缓存也可以补充其他片上缓存资源。如果内核仅使用没有纹理加载的全局内存访问,则所有内存流量都通过per-SM L1缓存。如果某些内核的输入数据通过纹理读取,则每SM纹理缓存将减轻来自L1的一些压力,并使其能够为内存流量提供服务,否则这些流量将转移到L2。
在进行这些权衡时,重要的是要注意NVIDIA从一个芯片架构到下一个芯片架构的决策。 Maxwell中的纹理缓存与L1共享,这使得从纹理读取不太理想。
答案 2 :(得分:1)
我不会忽视纹理内存的用法。参见例如论文'通信 - 最小化GPU寄存器中的2D卷积' (http://parlab.eecs.berkeley.edu/publication/899)他们正在比较小型2D卷积的不同实现,从纹理存储器直接加载到寄存器的策略似乎是一种很好的方法。