OpenMP for循环导致错误结果
我想通过部分简单代码比较循环性能与openmp。但结果是错误的。OpenMP for循环导致错误结果
我已经使用减少来避免竞争条件,但从来没有工作。
这里是我的代码:感谢您的任何建议
void TestMP_1(){
float afValueTmp[MP_TEST_NUM] = { 0 }; // MP_TEST_NUM = 10000
float sum = 0, sumNoMP = 0;
float fDiff = 0;
double eTDiff = 0;
double t0 = 0;
double t1 = 0;
for (int i = 0; i < MP_TEST_NUM; i++)
{
afValueTmp[i] = i;
}
t0 = (double)getTickCount();
for (int i = 0; i < MP_TEST_NUM; i++)
{
for (int k = 0; k < MP_TEST_NUM; k++); // just for delay
sumNoMP += afValueTmp[i]; // equation 4
}
t0 = ((double)getTickCount() - t0)/getTickFrequency();
t1 = (double)getTickCount();
#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < MP_TEST_NUM; i++)
{
for (int k = 0; k < MP_TEST_NUM; k++); // just for delay
sum += afValueTmp[i];
}
t1 = ((double)getTickCount() - t1)/getTickFrequency();
eTDiff = t0 - t1; // time improve
fDiff = sum - sumNoMP; // check result
printf("%.3f\n", eTDiff);
}
您正面临着浮点精度问题。请允许我来阐述:
#include <stdio.h>
int main(void)
{
float myOrigNumber = 49995000;
float myNumber = myOrigNumber + 1.;
printf ("orig: %f new: %f diff: %f\n",
myOrigNumber, myNumber, myNumber-myOrigNumber);
return 0;
}
结果将是:
orig: 49995000.000000 new: 49995000.000000 diff: 0.000000
所以,哪里是+1
去了?
float
类型只有7到8位有效数字。它们在哪里并不重要,因为浮点数在内部始终以Scientific notation表示为x.xxE + yy表示法,其中x.xx有24位,yy有8位。 数49995001大于2^24(16777216)放大,所以它会被舍入到可以被精确表示的最近数,这显然是49995000.
这就是为什么使用double
为sum
将缓解你的疼痛。不过,这不是一个真正的解决方案。减少操作要求操作必须是交换。 但是,这不一定是浮点加法的情况:如果您将百分之一,然后49995000添加到sum
,则结果将与您第一次添加1和49995000并接着九十九次1:在第二种情况下不同,每个稍后的+1将如上所示向下舍入。
您的结果可能会根据你所写的内容和预期四舍五入是正确的。
afValueTmp [i]中的数字都是整数,49995000不超过浮点类型范围。为什么有舍入问题,使结果不同? 我发现一旦我使用double和sumNoMP类型,所有结果都是正确的。 –
'for(int k = 0; k
@ Johnny Mopp感谢您的通知。但添加“;”后为延迟循环。结果仍然错过匹配。 –
我手工计算的结果是49995000 和sumNoMP = 49992896 sum = 49994736 ..... –