CUDA: 使用shared memory

CUDA 的thread本身是有层次结构的。 thread 被grouped成多个thread blocks。 同一个block 的threads 在同一时间, 运行在同一个SM上。

每一个block都有一个shared memory, 是被这个block内的所有的thread所共享的。 一个SM一次最多只能运行8个blocks。

我们知道, global memory, texture memory, constant memory 并没有在chip上面, 所以存取速度慢。 而shared memory 是on chip 上的, 故而速度很快。

并且我们的shared memory 是block级别的, 所以我们要充分利用shared memory存取速度快的特点, 可以将数据对象一次就load到shared memory 上面, 然后直接在shared memory 上进行数据的存取相关的操作。


但是使用shared memory 容易造成bank conflicts。 所谓的bank 就是shared memory arrays 被细分成多个小的subarrays, 这些小的subarray就被称为bank。

在计算能力为2.X(1.X)的GPU上, 每个block的shared memory 有32(16)个banks。 连续的32位的words被设置为连续的banks上。 不同的banks 能够同时被访问。 如果有两个或者更多的内存地址被同一个bank request(要求), 那么内存地址的访问就变成串行的了(serilized)。

在2.x 中, 如果memory request和32字相同, 就没有bank conflict。


另外, 我们有的时候需要等待一个block中的所有线程都完成工作之后, 才能进行下一步的操作。 否则就会出现race conditions.  所谓的race condition

就是, 例如当global memory中存有一个数字3. 当有两个线程都需要去访问这个位置, 将相关的值加一。 此时, 如果不进行synchronization, 就是出现数据竞赛的情况。 具体的, 有两种情况:

(1)线程1读取值为3, 加1变成4, 然后在存进去。 线程2读取数据4, 加1变成5, 将5 写进这个地址中。

(2) 线程1读取3, 线程2读取3, 都加1, 变成4, 写进去。 位置处存的值此时为4.
所以,根据具体的运行情况, 这个位置的值是无法确定的。

为了解决这类问题, 我们需要调用__syncthread() 去同步。

你可能感兴趣的:(DeepLearning)