atomicMax + AtomicCAS(atomicExch)

时间:2016-08-16 19:42:02

标签: cuda atomic

我想问你们,如果有更好的方法来结合2个原子。

我的目标是在J参数值列表(非常类似于双向输入)下找到一组K个等式(大于32)的最高结果,并保存值和j索引。

if (atomicMax(&max_k[id], t_max) < t_max) atomicExch(&indexMax[id],t_pos);

最初我们使用上述方法,但是,由于我们确实期望每个线程具有更高的值,因此可以在相同的线程中使线程B> C> A(线程B具有最高值,线程C具有高于A的值)。 我不确定,但是atomicExch可以在另一个线程顺序中执行而不是atomicMax(是正确的吗?),所以我们尝试了一个关键部分,但它导致了死锁。毕竟所有的解决方案似乎都有效。

以下代码中是否有更好的方法或存在任何问题?

__device__ int atomicMaxCAS(int* addressMax, int valMax, int* addressCAS, int valCas) {
        int oldCas = *addressCAS, assumedCas;
        int oldMax = *addressMax, assumedMax;
        do {
            assumedCas = oldCas;
            assumedMax = oldMax;
            oldMax = atomicMax(addressMax, valMax);
            if (oldMax < valMax) oldCas = atomicCAS(addressCAS, assumedCas, valCas);
        } while (assumedCas != oldCas || assumedMax != oldMax);
        return (oldMax);
    }

提前致谢!由于所有这些帖子,我能够开始写CUDA!

1 个答案:

答案 0 :(得分:3)

  

以下代码中有任何问题吗?

是的,你不能使用这样的两个原子并期望连贯的结果。您已经设置了可能的竞争条件。

假设线程A执行atomicMax并用100替换旧值。然后线程B执行atomicMax并用100替换100值。然后假设线程B执行atomicCAS ,并替换其索引。然后线程A执行atomicCAS,并用线程A索引替换线程B索引。现在,最大值为110,索引对应于线程A.

即使在单个warp中,也没有规定的原子操作执行顺序。

  

有更好的方法吗?

  1. 由于您的值都是32位数量,因此您可能有兴趣使用自定义的64位原子操作(如this)来同时更新值和索引。 / p>

  2. 对于大规模使用(大量线程),您可能想要探索classical paraellel reduction。这里有关于CUDA标记的问题,例如this onethis one,它们讨论了如何进行索引+值减少。

  3. Kepler上的全局原子很快,所以取决于你的确切代码和减少密度&#34;全局原子还原在性能方面可能不是一个大问题。