请理解我,但我不懂英语。
我的计算环境
我已经在CUDA C编程指南上阅读了有关“合并内存访问”的文档。 但我不能在我的案子中应用它们。
我有32x32块/网格和16x16线程/块。 这意味着如下代码。
dim3 grid(32, 32);
dim3 block(16,16);
kernel<<<grid, block>>>(...);
然后,我如何使用合并的内存访问?
我在下面的内核中使用了代码。
int i = blockIdx.x*16 + threadIdx.x;
int j = blockIdx.y*16 + threadIdx.y;
...
global_memory[i*512+j] = ...;
我使用常量512,因为线程总数是512x512个线程:它是grid_size x block_size。
但是,我从Visual Profiler中看到“全局内存存储效率低[平均9.7%,内核占计算量的100%]”。
Helper说使用合并的内存访问。 但是,我不知道应该使用内存的索引上下文。
有关详细代码的详细信息,请The result of an experiment different from CUDA Occupancy Calculator
答案 0 :(得分:2)
在CUDA中合并内存加载和存储是一个非常简单的概念 - 同一warp 中的线程需要从内存中加载或存储适当对齐的连续单词。
CUDA中的warp大小为32,warp由同一块中的线程组成,排序使得threadIdx.{xyz}
的x维度变化最快,y表示下一个最快,z表示最慢(在功能上,这与数组中的列主要排序相同)。
您发布的代码未实现合并内存存储,因为同一warp中的线程以512个字的间距存储,而不是在所需的32个连续字中。
改进合并的简单方法是按列主要顺序处理内存,所以:
int i = blockIdx.x*16 + threadIdx.x;
int j = blockIdx.y*16 + threadIdx.y;
...
global_memory[i+512*j] = ...;
在2D块和网格上采用更一般的方法,以你在问题中展示的精神实现合并将是这样的:
tid_in_block = threadIdx.x + threadIdx.y * blockDim.x;
bid_in_grid = blockIdx.x + blockIdx.y * gridDim.x;
threads_per_block = blockDim.x * blockDim.y;
tid_in_grid = tid_in_block + thread_per_block * bid_in_grid;
global_memory[tid_in_grid] = ...;
最合适的解决方案将取决于您未描述的代码和数据的其他详细信息。