Cuda atomicMax+;AtomicCAS(atomicExch)
我想问你们,是否有更好的方法将两个原子组合起来 我的目标是在J参数值列表(非常类似于双向输入)下找到一组K方程(超过32个)的最高结果,并保存该值和J索引Cuda atomicMax+;AtomicCAS(atomicExch),cuda,atomic,Cuda,Atomic,我想问你们,是否有更好的方法将两个原子组合起来 我的目标是在J参数值列表(非常类似于双向输入)下找到一组K方程(超过32个)的最高结果,并保存该值和J索引 if (atomicMax(&max_k[id], t_max) < t_max) atomicExch(&indexMax[id],t_pos); if(atomicMax(&max_k[id],t_max)C>A是可能的(线程B的值最高,线程C的值高于A)我不确定,但是atomicExch可以以比atomicMax
if (atomicMax(&max_k[id], t_max) < t_max) atomicExch(&indexMax[id],t_pos);
if(atomicMax(&max_k[id],t_max)
最初我们使用了上述方法,但是,由于我们确实希望每个线程都有更高的值,因此在同一个扭曲中,线程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);
}
\uuuuu设备\uuuuuu原子最大值(int*addressMax,int-valMax,int*addressCAS,int-valCas){
int oldCas=*地址cas,假定为;
int oldMax=*地址最大值,假设最大值;
做{
假设值=旧值;
假设最大值=最大值;
oldMax=atomicMax(addressMax,valMax);
如果(oldMax
提前谢谢!我之所以能够开始写CUDA,是因为这些帖子都是关于
以下代码中是否存在任何问题
__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);
}
是的,你不能像那样使用两个原子来期望一致的结果。您已经设置了可能的比赛条件
假设线程A执行atomicMax
,并将旧值替换为100。然后线程B执行atomicMax
,并将100值替换为110。然后假设线程B执行了atomicCAS
,并替换了它的索引。然后线程A执行atomicCAS
,并用线程A索引替换线程B索引。现在,最大值为110,索引对应于线程a
即使在单个扭曲中,也没有规定的原子操作执行顺序
有更好的办法吗
__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);
}
是的,你不能像那样使用两个原子来期望一致的结果。您已经设置了可能的比赛条件
假设线程A执行atomicMax
,并将旧值替换为100。然后线程B执行atomicMax
,并将100值替换为110。然后假设线程B执行了atomicCAS
,并替换了它的索引。然后线程A执行atomicCAS
,并用线程A索引替换线程B索引。现在,最大值为110,索引对应于线程a
即使在单个扭曲中,也没有规定的原子操作执行顺序
有更好的办法吗
开普勒上的全局原子学速度非常快,因此根据您的精确代码和缩减“密度”,全局原子缩减在性能方面可能不是一个大问题 你不能像那样使用两个原子并期望得到一致的结果。您已经设置了可能的比赛条件。假设线程A执行
atomicMax
,并将旧值替换为100。然后线程B执行atomicMax
,并将100值替换为110。然后假设线程B执行了atomicCAS
,并替换了它的索引。然后线程A执行atomicCAS
,并用线程A索引替换线程B索引。现在,最大值为110,索引对应于线程a。即使在单个扭曲中,也没有规定原子操作的执行顺序。由于您的值都是32位量,您可能有兴趣使用自定义64位原子操作同时更新值和索引,原子操作。在这些正确性问题之上,减少速度可能更快,因为原子操作完全序列化了所有线程。@RobertCrovella:非常感谢!我相信它会解决的!你不能像那样使用两个原子并期望得到一致的结果。您已经设置了可能的比赛条件。假设线程A执行atomicMax
,并将旧值替换为100。然后线程B执行atomicMax
,并将100值替换为110。然后假设线程B执行了atomicCAS
,并替换了它的索引。然后线程A执行atomicCAS
,并用线程A索引替换线程B索引。现在,最大值为110,索引对应于线程a。即使在单个扭曲中,也没有规定原子操作的执行顺序。由于您的值都是32位量,您可能有兴趣使用自定义64位原子操作同时更新值和索引,原子性。在这些正确性问题之上,减少可能更快,因为原子操作是完全独立的