【发布时间】:2018-05-04 16:55:03
【问题描述】:
我编写了一个 CUDA 内核,它执行两个数组 arr1 和 arr2 的数组加法。 arr1的哪个索引应该加上arr2的哪个索引存储在数组idx中的信息。
这是一个代码示例:
__global__ add(float* arr1, float* arr2, int* idx, int length)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
// each thread performs (length) additions,
// arr2 is (lenght) times larger than arr1
for (int j=threadIdx.x; j<length*blockDim.x; j+=blockDim.x)
{
arr1[i] += arr2[ idx[blockIdx.x*blockDim.x + j] ]; // edited here
}
}
该代码产生正确的输出,但几乎不比具有 8 个线程的 CPU 上的 openmp 并行代码快。我尝试了不同的块大小。
我怀疑对arr2 的访问模式效率低下,因为arr2 在全局内存中并且是准随机访问的——数组idx 包含唯一的、已排序但不连续的索引(可能是2, 3, 57, 103, ...)。因此,没有利用 L1 缓存。
此外,数组非常大,无法完全放入共享内存中。
有没有办法绕过这个障碍?
你知道如何优化arr2的访问模式吗?
【问题讨论】:
-
是什么让您认为访问
arr2是瓶颈?对idx的完全未合并的访问呢? -
好点。尽管如此,一个线程至少访问
idx的length连续元素,而arr2的访问模式中没有任何顺序。 -
我认为您需要阅读有关内存合并的内容
-
是的,谢谢,我做了一些研究并更新了问题。现在应该合并对
idx的访问,并且我的代码运行速度是原来的两倍。现在我很确定访问arr2是瓶颈。 -
编辑后的代码不可能产生与您问题中的原始代码相同的结果