我需要通过偏移移动1-D数组的每个前k个元素, 其中偏移是单调增加的,即,如果元素i的偏移是offset1 那么元素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;
}
}
然而,当测试k = 3时,偏移确实是单调增加的,即 0,1,1。 元素0按预期保持其位置。 但是,元素1不仅会复制到元素2(根据元素1的偏移量),还会复制到元素3中。
也就是说,只有在线程1完成元素1到元素2的复制之后,线程2才会读取元素2并将其存储到temp的副本中。
我做错了什么以及如何解决?
谢谢!
答案 0 :(得分:3)
您正在做的事情推广到分散操作:
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]
其中out
未指向与in
相同的内存。