我目前正在平铺我的 c++ AMP 代码。对于每个图块,我有 4096 字节的数据经常被读取,所以我想将其声明为 tile_static。将其分成多个图块是不切实际的,因为每个线程都需要访问所有数据。我的瓦片由 128 个线程组成,因此它们应该在 Nvidia/AMD GPU 上占用 2-4 个扭曲。
我刚刚阅读了以下文章,这似乎表明我只能在每个 warp 的 tile_static 中使用 1024 位:http: //blogs.msdn.com/b/nativeconcurrency/archive/2012/08/14/avoid-bank-conflicts -on-tile-static-memory-with-c-amp.aspx
在一些现代 GPU 上,tile_static 内存由可以同时访问的“n”个大小相等的内存条组成,并且连续的“m”位字被映射到连续的内存条。tile_static 内存(即 n 和 m)的确切组织取决于硬件。例如,在 Nvidia GTX 580 卡或 ATI HD 5870 卡上,tile_static 内存具有32 个存储库 (n = 32),这些存储库的组织方式使得连续的 32 位字 (m = 32) 映射到连续的存储库。请注意,n 可能因硬件而异,m 通常为 32。在本文的其余部分,我将假设 m 为 32。
这是否意味着我可以为每个扭曲或每个线程声明多达 1024 位?所有 tile_static 变量是否在 warp 之间共享,或者每个 warp 都有自己的副本?
这些问题中有多少是依赖于硬件的,如果是,我怎样才能在运行时找出限制?
我已经阅读了一本 c++ AMP 书籍封面,虽然我很感谢作者向我介绍了这个主题,但它似乎没有解决这个问题(或者如果它解决了,我不明白它)。
网上有很多关于如何使用 tile_static 内存的信息(这是一个好的开始:http ://www.danielmoth.com/Blog/tilestatic-Tilebarrier-And-Tiled-Matrix-Multiplication-With-C-AMP .aspx),但似乎没有人谈论我们可以声明多少,因此不可能真正实现这些东西!最后一个链接给出了以下示例:
01: void MatrixMultiplyTiled(vector<float>& vC,
const vector<float>& vA,
const vector<float>& vB, int M, int N, int W)
02: {
03: static const int TS = 16;
04: array_view<const float,2> a(M, W, vA);
05: array_view<const float,2> b(W, N, vB);
06: array_view<float,2> c(M,N,vC); c.discard_data();
07: parallel_for_each(c.extent.tile< TS, TS >(),
08: [=] (tiled_index< TS, TS> t_idx) restrict(amp)
09: {
10: int row = t_idx.local[0]; int col = t_idx.local[1];
11: float sum = 0.0f;
12: for (int i = 0; i < W; i += TS) {
13: tile_static float locA[TS][TS], locB[TS][TS];
14: locA[row][col] = a(t_idx.global[0], col + i);
15: locB[row][col] = b(row + i, t_idx.global[1]);
16: t_idx.barrier.wait();
17: for (int k = 0; k < TS; k++)
18: sum += locA[row][k] * locB[k][col];
19: t_idx.barrier.wait();
20: }
21: c[t_idx.global] = sum;
22: });
23: }
请注意,第 13 行声明了 2x 1024 位,这让我希望我的 4096 位不会要求太多...... - 我想这些问题更多地依赖于硬件/实现,而不是 AMP 语言扩展本身......