GPU世界论坛

GPU开发园地(Developers) => CUDA => 主题发帖人为: 娃娃脸 于 七月 25, 2019, 09:17:36 am

标题: GPU每次运行结果不一样是什么原因
作者: 娃娃脸七月 25, 2019, 09:17:36 am
代码是一样的但是每次运行结果都不一样,相差很大。感觉有点像是数值结果是一样的,但数值排列顺序每次运行出来都不一样。
想问问[名词2]们到底是什么原因?
标题: Re: GPU每次运行结果不一样是什么原因
作者: 屠戮人神七月 25, 2019, 01:29:20 pm
代码是一样的但是每次运行结果都不一样,相差很大。感觉有点像是数值结果是一样的,但数值排列顺序每次运行出来都不一样。
想问问[名词2]们到底是什么原因?

要么是你的代码有问题,要么是某些GPU算法本身就是结果不问题的,于是产生了你说的“数值结果是一样的,但排列顺序不同”。

不妨考虑一下CPU上的一些不稳定算法,是不是有类似现象?
标题: Re: GPU每次运行结果不一样是什么原因
作者: 娃娃脸七月 26, 2019, 10:29:18 am
要么是你的代码有问题,要么是某些GPU算法本身就是结果不问题的,于是产生了你说的“数值结果是一样的,但排列顺序不同”。

不妨考虑一下CPU上的一些不稳定算法,是不是有类似现象?

找到原因了,是我在核函数内给三个全局变量相互赋值出了问题,例如初始化是p1=1,p2=2,p3=3。然后后面相互赋值p3=p2;p2=p1;但最后输p3结果不是2而是1。为什么会这样的?而且我加一个中间变量来赋值也还是不行,例如swap=p2,p3=swap;swap=p1,p2=swap;结果还是和上面的一样
标题: Re: GPU每次运行结果不一样是什么原因
作者: 屠戮人神七月 26, 2019, 05:40:51 pm
找到原因了,是我在核函数内给三个全局变量相互赋值出了问题,例如初始化是p1=1,p2=2,p3=3。然后后面相互赋值p3=p2;p2=p1;但最后输p3结果不是2而是1。为什么会这样的?而且我加一个中间变量来赋值也还是不行,例如swap=p2,p3=swap;swap=p1,p2=swap;结果还是和上面的一样

不妨发一下代码,例如考虑如下三个变量:
__device__ int a;
__device__ int b;
当同时有多个线程在进行tmp = a; a = b; b = tmp;的时候,因为多个GPU上的线程的执行在时间上可能是错开的,此时则会发生竞态,使得a,b并没有完成交换。这就是一种例子。

楼主不妨发一下代码,没啥可以保密的。
标题: Re: GPU每次运行结果不一样是什么原因
作者: 娃娃脸七月 26, 2019, 10:34:38 pm
不妨发一下代码,例如考虑如下三个变量:
__device__ int a;
__device__ int b;
当同时有多个线程在进行tmp = a; a = b; b = tmp;的时候,因为多个GPU上的线程的执行在时间上可能是错开的,此时则会发生竞态,使得a,b并没有完成交换。这就是一种例子。

楼主不妨发一下代码,没啥可以保密的。

谢谢啦!问题已解决了,应该就是你说的那样,我限制了执行这几条命令的线程数,只有blockIdx.x==0的线程执行该命令就能实现了。
修改前:p2[tid] = p1[tid];
     p1[tid] = 1.0f;
修改后:if (blockIdx.y == 0)
   {
      p2[tid] = p1[tid];
     p1[tid] = 1.0f;
   }
标题: Re: GPU每次运行结果不一样是什么原因
作者: 屠戮人神七月 28, 2019, 02:54:26 pm
谢谢啦!问题已解决了,应该就是你说的那样,我限制了执行这几条命令的线程数,只有blockIdx.x==0的线程执行该命令就能实现了。
修改前:p2[tid] = p1[tid];
     p1[tid] = 1.0f;
修改后:if (blockIdx.y == 0)
   {
      p2[tid] = p1[tid];
     p1[tid] = 1.0f;
   }

嗯嗯。以及,考虑到这问题这么普遍的存在,你也许应当额外看一下手册的“原子操作”和相关章节。很多问题可以变通的用其他方式解决的。
标题: Re: GPU每次运行结果不一样是什么原因
作者: 娃娃脸七月 30, 2019, 10:48:45 pm
嗯嗯。以及,考虑到这问题这么普遍的存在,你也许应当额外看一下手册的“原子操作”和相关章节。很多问题可以变通的用其他方式解决的。
嗯嗯,看过了。我了解的原子操作只是用那几个函数,而且只对共享内存和全局内存的数据起到作用,好像不适合我用。不知道为什么  在我的工程里atomicAdd()和atomicExch()函数都能用而atomicSub()这个函数却用不了。