我竭尽全力尝试将经常访问的数据存储在tile_static
内存中,以利用随之而来的无限性能必杀技。
但是,我刚刚读到只有某些硬件/驱动程序可以实际动态索引tile_static数组,并且操作可能只会溢出到全局内存。
在一个理想的世界里,我只是去做和描述,但这是一个重大的操作,我想知道我是否在浪费我的时间在这里:
tile_static int staticArray[128];
int resultFast = staticArray[0]; // this is super fast
// but what about this:
i = // dynamically derived value!
int resultNotSoFast = staticArray[i]; // is this faster than getting it from global memory?
如何判断我的GPU /驱动程序是否支持静态数组的动态索引?
答案 0 :(得分:2)
本地内存的动态索引
所以我做了一些挖掘,因为我也想了解这一点。
如果您指的是本地内存的动态索引,不是 tile_static
(或者用CUDA说法,“共享内存”)。在上面的示例中,staticArray
应声明为:
int staticArray[128]; // not tile_static
这不能动态索引,因为int staticArray[128]
数组实际上存储为128个寄存器,而这些寄存器无法动态访问。像这样分配大型数组无论如何都是有问题的,因为它耗尽了大量的寄存器,这些寄存器是GPU上的有限资源。每个线程使用太多寄存器,您的应用程序将无法使用所有可用的并行性,因为某些可用线程将停止等待寄存器变为可用。
在C ++ AMP的情况下,我甚至不确定DX11提供的抽象级别可能会使这有点无关紧要。我不熟悉DX11的专家。
这里有一个很好的解释,In a CUDA kernel, how do I store an array in "local thread memory"?
银行冲突
Tile静态内存分为多个模块,简称为 银行。平铺静态存储器通常由16,32或64个存储体组成, 每个都是32位宽。这是特定于特定GPU的 硬件并可能在未来发生变化。平铺静态内存 横跨这些银行。这意味着对于带有磁贴的GPU 如果arr是一个数组,那么用32个存储体实现的静态存储器< float,1>,然后arr [1]和arr [33]在同一个bank中,因为每个float占用一个32位的bank位置。这是关键点 了解何时处理银行冲突。
每家银行都可以 每个周期服务一个地址。为获得最佳性能,经线中的线程 应该访问不同库中的数据或者都读取相同的数据 在单个库中,通常由硬件优化的模式。什么时候 遵循这些访问模式,您的应用程序可以最大化 可用磁贴静态内存带宽。在最坏的情况下,多个 同一个warp中的线程访问来自同一个bank的数据。这导致 这些访问要序列化,这可能导致a 性能显着下降。
我认为混淆的关键点可能是(基于你的一些其他问题)存储库是32位宽,但是负责访问存储区内的所有内存,这将是1/16,总瓦片静态内存的1/32或1/64。
您可以在此处详细了解银行冲突What is a bank conflict? (Doing Cuda/OpenCL programming)