omp 并行运算,float计算误差那么大,怎么办

GKatHere 2023-07-28 15:16:03
//  开启omp并行,float计算误差累积到了0.2.
	//		服了呀....
	{
		std::cout.precision(14);

		std::array<float, 100000> da;
		for (size_t i = 0; i < da.size(); i++)
			da[i] = 1.0f * i / da.size();

		long cnt = 0;
		float cf = 0;
		double cdb = 0;
#pragma omp parallel for         
		for (int i = 0; i < 100000; i++)
		{
#pragma omp critical
			{
				cnt++;
				cf += da[i];
				cdb += da[i];
			}
		}
		// x86 debug 输出:		100000	49999.6953125	49999.5	(49999.6953125这个值,还每次都不一样)
		// x86 release 输出:	100000	49999.54296875	49999.5	(49999.54296875这个值,还每次同样不一样)
		std::cout << cnt << " " << cf << " " << cdb << std::endl;	

		cnt = 0;
		cf = 0;
		cdb = 0;
		for (int i = 0; i < 100000; i++)
		{
			cnt++;
			cf += da[i];
			cdb += da[i];
		}

		// x86 debug 输出:		100000	49999.51171875	49999.5
		// x86 release 输出:	100000	49999.51171875	49999.5
		std::cout << cnt << " " << cf << " " << cdb << std::endl;
	}

 

...全文
285 5 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
CSDN-Ada助手 2023-07-28
精选
  • 打赏
  • 举报
回复
您的问题已经帮您同步至问答, 链接: https://ask.csdn.net/questions/7983093, 请您保持关注, 如果回答有帮助解决此问题, 麻烦您动动小手给相关的回答点赞, Ada会在评论区为您更新结题状态
Williamtym 2023-07-28
  • 打赏
  • 举报
回复

浮点数计算误差是一个常见的问题。这是因为浮点数在计算机中以二进制形式表示,而大多数实数(例如十进制中的小数)无法精确地用二进制表示,因此存在舍入误差。

有几种方法可以减少浮点数计算误差:

使用更高精度的数据类型:如果需要更高的精度,可以使用更长的或更高精度的浮点数类型,如double或long double。
使用对称数:对称数是一种表示方式,使得计算机在进行浮点数计算时没有舍入误差。例如,可以将浮点数表示为(sign, exponent, mantissa)的形式,其中sign为正负号,exponent为指数,mantissa为尾数。这样,正数和负数的指数就可以用相同的表示方式,从而避免了舍入误差。
使用数值稳定的算法:数值稳定的算法是指在计算过程中保持舍入误差较小或可控的算法。这些算法通常会在计算过程中减少舍入误差的影响,以确保计算结果的准确性。
使用并行计算库:一些并行计算库提供了数值稳定的的高精度计算函数,可以在并行计算中减少浮点数计算误差。
调整计算精度:如果可能的话,可以调整计算精度,以减少舍入误差的影响。例如,可以设置计算精度为某个容忍度,以接受一定的计算误差。
总之,在并行计算中,浮点数计算误差是无法完全避免的,但可以通过上述方法减少其影响,以确保计算结果的准确性。

GKatHere 2023-07-29
  • 举报
回复
@Williamtym 我现在采用的是,一边用少量的double, 一边拉大数值空间,减少误差的影响...
A11000100A 2023-07-28
  • 打赏
  • 举报
回复

在这个代码中,浮点数计算误差累积到了0.2,可能是由于多个线程同时对cf和cdb进行累加操作时导致的。为了解决这个问题,可以尝试以下方法:

使用OpenMP的reduction指令:将累加操作放在reduction指令中,让OpenMP自动处理并行计算中的累加操作。这样可以避免多个线程同时对同一个变量进行累加操作,从而减小误差。修改代码如下:

cpp
Copy code
#pragma omp parallel for reduction(+:cf,cdb)
for (int i = 0; i < 100000; i++)
{
cnt++;
cf += da[i];
cdb += da[i];
}

使用更高精度的数据类型:可以尝试使用double类型来存储浮点数,以提高计算的精度。修改代码如下:

cpp
Copy code
std::array<double, 100000> da;

减少并行度:减少并行计算的线程数量,使得每个线程负责的计算量更大,从而减小误差。可以通过设置OMP_NUM_THREADS环境变量来控制线程数量。
需要注意的是,浮点数计算误差是由于浮点数的存储方式和运算规则所导致的,这是一个普遍存在的问题。在进行浮点数计算时,需要始终注意并处理可能的误差。

GKatHere 2023-07-28
  • 举报
回复
@A11000100A 谢了..想用double,不过太耗空间了

65,194

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧