C++ OpenMP和CUDA进行并行计算时的浮点“误差”

本文讨论了在C++中使用OpenMP和CUDA进行并行计算时遇到的浮点数计算差异问题。主要表现为CUDA在Debug和Release模式下计算结果不同,以及多线程二分求和与单线程计算结果的差异。这两种差异源于浮点数的32位数据结构限制和Rounding操作。文中还提到了Kahan summation algorithm作为解决浮点精度问题的一种算法。
摘要由CSDN通过智能技术生成

前话


前些时间考虑了下VS要不要顺便也讲下Linux的开发。最后还是决定算了:1.现在主流开发Linux的团队,比较排斥使用Windows来对Linux进行开发,虽然他们自己也承认VS开发很方便;2.Linux在VS和C++工程上和Android的基本没啥区别,唯一需要注意的要在VS的配置里面加上远程调试目标也就是Linux的IP和用户名之类的,具体参考微软官方文档:https://docs.microsoft.com/en-us/cpp/linux/connect-to-your-remote-linux-computer?view=vs-2019。总之VS可以远程调试,部署Linux服务器,还有像RaspberryPi这样的Linux设备,很方便。最后还是写了:VS2019 C++的跨平台开发——Linux开发

 

正题


最近在对神经网络进行CUDA并行计算的时候碰到了两次计算结果有偏差的情况:1. CUDA10.1在Debug和Release下计算出的结果并不一样;2. 通过CUDA使用多线程对数组二分求和的结果和单线程计算结果不一样。

这两种如标题写的那样都是假的误差,更像是一种差异,由于float 32bits的数据结构所限定的有效数据位数带来的显示差异。这两种不同的显示结果无法区分哪种更优。

第一种,具体来说是由于Release配置打开了-fmad造成的。fmad是一种基于硬件的加速技术,这里需要提到的一点就是数字电路里面的逻辑电路和组合电路。fmad的意思是将浮点小数的乘法和加法合并在一起,即通常情况下是a*b+c=d。那么需要先进行乘法计算,把结果按照浮点有效位数保存后再根据保存结果进行一次加法计算。这个操作在硬件级别上就是两个时钟完成的操作,两层时序逻辑。而fmad是把这两个操作转换成了一个时钟的组合逻辑电路,这个不单是时间上的减少,而且还减少了一次有效位数的保存操作。这里把计算结果按照有效位数保存的操作叫做Rounding。正是少了的这次Rounding导致计算结果的差异。这里先不解释怎么导致的,因为第二种也是由于这个导致的。

fmad的Wiki百科:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值