本地内存的动态索引
所以我对此进行了一些挖掘,因为我也想了解这一点。如果您指的是本地内存的动态索引,则不是 tile_static
(或用 CUDA 的说法,“共享内存”)。在上面的示例中,staticArray
应声明为:
int staticArray[128]; // not tile_static
这不能被动态索引,因为一个数组int staticArray[128]
实际上存储为 128 个寄存器并且这些不能被动态访问。无论如何分配这样的大型数组都是有问题的,因为它会占用大量的寄存器,而这些寄存器是 GPU 上的有限资源。每个线程使用过多的寄存器,您的应用程序将无法使用所有可用的并行性,因为一些可用线程将停止等待寄存器可用。
在 C++ AMP 的情况下,我什至不确定 DX11 提供的抽象级别是否会使这有点无关紧要。我不是 DX11 的专家知道。
这里有一个很好的解释,在 CUDA 内核中,如何将数组存储在“本地线程内存”中?
银行冲突
平铺静态存储器被划分为称为银行的多个模块。Tile 静态内存通常由 16、32 或 64 个 bank 组成,每个 bank 为 32 位宽。这是特定于特定 GPU 硬件的,将来可能会发生变化。平铺静态存储器在这些存储体中交错。这意味着对于使用 32 个 bank 实现的 tile 静态内存的 GPU,如果 arr 是一个数组 <float, 1>,那么 arr[1] 和 arr[33] 在同一个 bank 中,因为每个 float 占用一个 32 位 bank地点。这是处理银行冲突时要理解的关键点。
每个银行每个周期可以服务一个地址。为了获得最佳性能,warp 中的线程应该访问不同 bank 中的数据,或者全部读取单个 bank 中的相同数据,这种模式通常由硬件优化。当遵循这些访问模式时,您的应用程序可以最大化可用的切片静态内存带宽。在最坏的情况下,同一个 warp 中的多个线程从同一个 bank 访问数据。这会导致这些访问被序列化,这可能会导致性能显着下降。
我认为混淆的关键点可能是(基于您的其他一些问题)是内存库是 32 位宽,但负责访问该库中的所有内存,这将是 1/16、1/32或总平铺静态内存的 1/64。
您可以在此处阅读有关银行冲突的更多信息。什么是银行冲突?(做 Cuda/OpenCL 编程)