我最近在学习CUDA。我对内存事务有疑问。 据我所知,在每个事务中,32个连续的线程(在同一个块中)可以同时访问连续的128个字节(32个单精度字)的内存,这称为warp。 但在该示例中,每个线程始终将(4个字节)字作为1个整个变量访问。所以我的问题是,如果我的数组在全局内存中的类型为char定义,那么所有32个线程是否可以访问这段内存,并分别同时读取4个连续的char?
因此,对于eaxmple,如果我编写代码:
__global__
void kernel(char *d_mask)
{
extern __shared__ char s_tmp[];
const unsigned int thId = threadIdx.x;
const unsigned int elementId = 4 * (threadIdx.x + blockDim.x * blockIdx.x);
s_tmp[thId_x] = d_mask[elementId];
s_tmp[1 + thId_x] = d_mask[elementId + 1];
s_tmp[2 + thId_x] = d_mask[elementId + 2];
s_tmp[3 + thId_x] = d_mask[elementId + 3];
__syncthreads();
/* calculation */
}
那么,每个线程会同时读取4个字节吗?如果没有,我怎么能设法做到这一点?我应该使用像memcpy这样的API吗?
答案 0 :(得分:2)
为了获得适当有效的读取,必须将读取的字节组合到单个事务中;我们通常不能通过跨越几行代码来解决问题。
要将事物组合到单个事务中,有矢量类型,它们将多个元素组合成一个类型。只要我们pay attention to proper alignment,我们就可以将char
或unsigned char
数组视为例如uchar4
或vector_types.h
数组。 vector_functions.h
这是一种将四个字符组合成一个(32位)类型的矢量类型。您可以在cuda标题文件__global__
void kernel(char *d_mask)
{
extern __shared__ char s_tmp[];
const unsigned int thId = threadIdx.x;
const unsigned int elementId = threadIdx.x + blockDim.x * blockIdx.x;
uchar4 *s_tmp_v = reinterpret_cast<uchar4 *>(s_tmp);
uchar4 *d_mask_v = reinterpret_cast<uchar4 *>(d_mask);
s_tmp_v[thId] = d_mask_v[elementId];
__syncthreads();
/* calculation */
}
和{{1}}中找到更多好东西。
无论如何,我们可以像这样重写你的样本,以利用&#34;向量加载&#34;:
{{1}}