2013-08-06 24 views
0

我学习OpenMP的,现在,我有一个问题。尽管所有线程都访问该函数,但以下代码的工作时间和没有并行部分的相同代码在统计上是相等的。我试图看看互联网上的一些指南,但它没有帮助。所以问题是,这个平行部分有什么问题?打开熔点为平行不工作

int sumArrayParallel() 
{ 

    int i = 0; 
    int sum = 0; 
    #pragma omp parallel for 
    for (i = 0; i < arraySize; ++i) 
    { 
     cout << omp_get_thread_num() << " "; 
     sum += testArray[i]; 
    } 
    return sum; 
} 

回答

4

还有的OpenMP的代码没有对他们的串口对应表现出改善的性能两个非常常见的原因:

  1. 正在做的工作是不足以超过并行计算的开销。想想有一段时间,建立一个线程团队,分配工作给他们,从他们那里收集结果的成本。除非这个成本低于并行化计算所节省的时间,否则OpenMP代码即使正确,也不会显示任何加速并可能显示相反的结果。你没有向我们显示数字,所以你自己的计算。

  2. 程序员强加给并行程序串行操作,或者通过包装的内部存储器围栏的数据访问,可能通过访问平台资源,这是固有的串行。我怀疑(但我对C的知识很糟糕),你对cout的写作可能会无意中使你的计算部分串行化。

当然,你可以混合使用这两个问题,太多的序列化和没有足够的工作,导致性能令人失望。

进一步的阅读this page on Intel's website是有用的,而不是只为初学者。

我认为,虽然,你有你的代码比它差的并行性能更严重的问题。 OpenMP版本是否产生正确的sum?既然你没有做出具体规定sum被所有线程共享,他们将比赛访问它。在学习OpenMP的同时,将条款default(none)附加到并行区域并负责定义每个区域中每个变量的共享/私有状态是一个非常好的主意。然后,一旦你流利地使用OpenMP,你就会知道为什么继续使用default(none)条款是有意义的。

即使您回复是的,代码确实会产生正确的结果数据竞争存在,您的程序不能被信任。数据竞赛非常有趣,它们并没有出现在你运行的所有测试中,一旦你将代码推广到生产中,轰炸!和蛋全在你的脸上。

但是,你似乎是滚动自己reduction和OpenMP提供的工具这样做。调查OpenMP引用中的reduction子句。如果我正确地读你的代码,并考虑到以上的建议,你可以重写环路

#pragma omp parallel for default(none) shared(sum, arraySize, testArray) private(i) reduction(+:sum) 
for (i = 0; i < arraySize; ++i) 
{ 
    sum += testArray[i]; 
} 

简而言之,使用还原子句告诉OpenMP的梳理总结,从工作单个值的问题跨线程分布,避免竞争条件

由于OpenMP使循环迭代变量默认为私有,因此您可以从指令中省略子句private(i),而没有太多风险。更妙的是,虽然可能会宣布它里面的语句:并行区域内声明的(撇开一些特殊情况下)总是私人

#pragma omp parallel for default(none) shared(sum, arraySize, testArray) reduction(+:sum) 
for (int i = 0; i < arraySize; ++i) 

变量。