程序输出错误

程序执行一段时间后,输出结果显示1.#QNAN0,之前的数据输出都是正常的,请问这是神马情况?

超出数值表示范围

请仔细检查程序逻辑

LZ您好,这个是NAN,表示not a number。
在浮点数规范中,一些错误的计算(如分子分母都为零)会生成这样的结果,但并不直接报错,从而可以使结果保留下来供人分析。

因此,请LZ检查自己的程序。

大致如上,祝您好运~

修正了一处不严格的举例。

根据版主指导,我对程序进行了仔细的检查,问题仍未能解决。同样的程序在CPU中可以正常计算的,我也看了编程手册中的浮点标准,还是不太明白在CUDA中浮点数运算有什么不同的地方呢?:handshake

LZ您好,并无其他进一步的建议了。以及我也无法凭空猜得您的问题所在。

唯一的建议是4#给出的检查程序的建议。

大致如此,祝您好运~

谢谢斑竹的建议,为难斑竹了。试问一下,一样的单精度浮点数,同样的算法,在CPU下可以实现,那在GPU下计算精度会有什么区别吗?

LZ您好:

1:单精度浮点数的格式和有效位数是统一的。

2:CUDA的数学函数的精度请参考手册,一般来说是可以的(fermi及kepler核心)。

3:不同的中间过程的截断情况会轻微影响浮点计算结果,比如CPU上X87的浮点计算,中间过程的精度就很高,比CPU上的SIMD的浮点运算要高。再比如fermi开始使用的FMA的中间过程的精度就要比GT200的MAD的高。

4:不同的编译参数会影响浮点计算精度。

5:GPU上运行的某算法的并行版本,如果和CPU上的串行版本相比,运算顺序上有差异(如CPU上循环实现的串行累加和GPU上的并行规约相加),那么由于浮点数的自身的性质(不可结合性),运算结果会有差异。

大致有如上几点,供您参考。

祝您编码顺利~

多谢,不过在CPU上可以正常 执行的话,程序逻辑应该是没问题的吧?

LZ您好,这个至多说明您CPU上的实现是没有问题的。(以及实际上也可能有没爆发的隐藏问题)

而您GPU的实现是和CPU实现不同的另外一个实现。所以无法判断您GPU实现是否有问题。

大致如此,供您参考。

祝您好运~

如果贴出代码,大家可以试试看

[

谢谢版主每次耐心的指导!我的问题应该是误差积累所致,这两天看了一些cuda浮点方面的资料,有些疑问:对于普通的加减乘除 运算可以直接移植还是应使用相应的cuda函数?不知如何才能减小误差积累?

LZ您好,不客气的。

普通的加减乘除可以直接使用运算符,其他的诸如指数函数,对数函数,三角函数等可以使用对应的函数。您可以在 CUDA C Programming Guide Appendix C里面找到相关的内容。

减少积累误差这个话题有点大,比如浮点数累加,这个有专门的方法避免大数吃掉小数。您也可以尝试使用双精度数据来改善精度情况。

值得指出的是,浮点数自身其实是不具备结合性的,其结果依赖于实际的运算顺序。比如100个浮点数相加,直接从第一个循环加到第100个和并行规约的结果,一般来说是不一样的。以及此时您不能以CPU循环相加的结果作为“准确值”来衡量GPU的结果。因为该CPU的结果只是一种顺序下的浮点数运算的结果,或着还是CPU实现,但是您反过来从第100个数据往回加,结果都有可能不一样。

此外,当前主流的GPU都具备FMA的操作,这个和CPU上直接运行乘法再运行加法相比,如果CPU使用了X87浮点运算,中间过程都是80bit精度的,那么CPU的运算精度高;但CPU如果使用了SSE等SIMD的指令,并且没有使用FMA(这个只有AMD 的推土机和较新的APU以及intel的haswell 才支持),那么CPU上实际上是先算乘法,得到数据,再算加法的。此时中间过程精度不如GPU。

大致如此,祝您编码顺利~

再一次感谢版主多次的指导!我的问题解决了,是误差积累导致,改成双精度的可以了!

恭喜LZ解决问题,并感谢您反馈结果。

欢迎您经常来论坛转转,祝您编码顺利~