CUDA:如何移动数组元素

CUDA:如何移动数组元素,cuda,Cuda,我需要将一维数组的前k个元素移动一个偏移量, 其中,偏移量单调增加,即,如果元素i的偏移量为偏移量1 然后元素i+1有偏移量offset2,它满足:offset2>=offset1 我编写了一个内核,在前k个元素中的每个元素上执行: if (thread_id < k) { // compute offset if (offset) { int temp = a[thread_id]; __synchthreads(); a[thread_id +

我需要将一维数组的前k个元素移动一个偏移量, 其中,偏移量单调增加,即,如果元素i的偏移量为偏移量1 然后元素i+1有偏移量offset2,它满足:offset2>=offset1

我编写了一个内核,在前k个元素中的每个元素上执行:

if (thread_id < k) {

  // compute offset

  if (offset) {
    int temp = a[thread_id];

    __synchthreads();

    a[thread_id + offset] = temp;
  }
}
if(线程id
然而,当测试k=3时,偏移量确实是单调增加的,即 0, 1, 1. 元素0保持在预期的位置。 但是,元素1不仅会复制到元素2(根据元素1的偏移量),还会复制到元素3

也就是说,只有在线程1完成了元素1到元素2的复制之后,线程2才会读取元素2并将其存储到temp的副本中

我做错了什么?如何修复


谢谢大家!

您正在执行的操作概括为分散操作:

thread   0  1  2  3  4
in  =  { 1, 4, 3, 2, 5}
idx =  { 1, 2, 3, 4, 0}

out[idx] = in[i]
一般来说,分散不能并行进行,因为线程从其他线程写入的位置读取数据。在我们的示例中,如果线程2在线程1写入其输出位置后读取其输入位置,则会得到错误的结果。这是一种竞争条件,需要同步或异地存储

由于在这种情况下,大型阵列的同步是全局同步,CUDA编程模型不支持全局同步,因此必须使用异地分散

换句话说,您不能这样做:

temp = in[thread_idx]
global-sync
in[thread_idx + offset] = temp
out[i + offset] = in[thread_idx]
您必须这样做:

temp = in[thread_idx]
global-sync
in[thread_idx + offset] = temp
out[i + offset] = in[thread_idx]

其中,
out
不指向与
中的
相同的内存

请注意,
\u syncthreads()
仅为块内的线程提供了一个屏障。因此,当您转到网格中的多个块时,此方法将立即中断。此外,如果您正在做一些愚蠢的事情,比如启动一个由线程块组成的网格,每个线程块只有一个线程,那么代码将到处中断。也许您应该展示内核的完整表示以及内核调用和启动参数的计算。你可以简单地用这些信息编辑你的问题,不要试图把它塞进评论中。是的,我错误地运行了3个块,每个块1个线程。它适用于1块3线程。但是,在特斯拉K20上,每个块的线程数限制为1024个。如何移动超过1024个元素?通过一次移动一个1024块,在执行另一个1024块之前完成工作,依此类推?同样,在这样的条件块中,
\uu syncthreads()
也不能保证工作。阅读条件代码中的同步线程。关于如何使它跨多个线程块工作,您需要一个不同的可并行化算法。我还没有详细考虑过,但在我看来,如果输出向量与输入向量不同,则完全可以避免这种危险。那么uu threadfence()呢?这可以用在条件代码中吗?描述的_syncthreads()和_threadfence()之间的区别在哪里?@user1760748:
__threadfence()
是一个内存围栏,可以有条件地使用,但在这里没有帮助。您可以在中看到所有这些函数的描述。