CUDA在多个数据上合并了一个扭曲
CUDA coalesced one warp on multiple data
我有一个关于联合cuda访问的基本问题。
例如,我有一个由32个元素和32个线程组成的数组,每个线程访问一个元素。
__global__ void co_acc ( int A[32], int B[32] ) {
int inx = threadIdx.x + (gridDim.x * blockDim.x);
B[inx] = A[inx]
}
现在,我想知道的是:如果我有32个线程,但有一个64个元素的数组,那么每个线程必须复制2个元素。为了保持联合访问,我应该转换我拥有的线程数的数组访问索引。例如:ID为0的线程将访问A[0]
和A[0+32]
。我的假设是对的吗?
__global__ void co_acc ( int A[64], int B[64] ) {
int inx = threadIdx.x + (gridDim.x * blockDim.x);
int actions = 64/blockDim.x;
for ( int i = 0; i < actions; ++i )
B[inx+(i*blockDim.x)] = A[inx+(i*blockDim.x)]
}
为了保持联合访问,我应该将数组访问的索引移动我所拥有的线程数。例如:ID为0的线程将访问A[0]和A[0+32]。我的假设是对的吗?
是的,这是一个正确的方法。
严格来说,这不是应该,而是可以:只要warp请求中的所有线程都位于同一(对齐)128字节行内,任何内存访问都将合并。这意味着你可以排列线程索引,你的访问仍然会被合并(但既然你可以做简单的事情,为什么要做复杂的事情呢)。
另一种解决方案是让每个线程加载一个int2
:
__global__ void co_acc ( int A[64], int B[64] ) {
int inx = threadIdx.x + (gridDim.x * blockDim.x);
reinterpret_cast<int2*>(B)[inx] = reinterpret_cast<int2*>(A)[inx];
}
这是(在我看来)更简单、更清晰的代码,可能会提供更好的性能,因为这可能会减少编译器发出的指令数量和内存请求之间的延迟(免责声明:我没有尝试过)。
注意:正如Robert Crovella在评论中提到的那样,如果你真的在使用32个线程的线程块,那么你很可能严重不足了GPU的容量。
相关文章:
- 如何将一个数组值合并为一个整数c++
- 如何将不同的可执行文件合并到一个窗口框架中进行编码?像浏览器一样
- 为什么在排序链表上的这种合并实现总是将两个列表都设置为 NULL,而只有一个应该设置一个列表?
- 将两个 cpp 文件合并为一个 cpp 文件
- 将所有 *.txt 文件合并到一个文本文件中,其名称由用户使用 C++ 提供
- C++ 如何将两个 makefile 对象目标规则(位于另一个文件夹中)合并到一个目标/规则中?
- 将两个列表合并为一个蛇形列表
- 使用迭代器进行合并排序中的一个缓冲区
- 如何通过通用引用或std::forward将这三个c++模板函数合并为一个
- C将链接库合并为一个库
- 是否可以将前向声明和常规声明合并到一个文件中,然后像分开一样使用它?
- 我正在编写一个拆分为 3 的合并排序,我不知道为什么它不起作用
- 两个 cin / cout 语句合并为一个
- 我想将四个字节合并为一个数字以进行串行传输
- 将两个 1D 直方图合并为一个
- 如何合并两个双重链接列表(访问下一个链接)
- 将 3 个列表合并到一个大列表中
- C++全局常量数组:是否保证合并(优化)到一个副本中
- 将多个 stl 文件合并为一个
- 我写了一个合并排序,但它有一些错误