首页
学习
活动
专区
圈层
工具
发布

OpenMP:
EN

Stack Overflow用户
提问于 2016-11-13 07:32:02
回答 2查看 789关注 0票数 0

我对代码进行了如下编辑:

代码语言:javascript
复制
#pragma omp parallel for private(i, piold, err) shared(threshold_err) reduction(+:pi) schedule (static)
{
  for (i = 0; i < 10000000000; i++){ //1000000000//705035067
        piold = pi;
        pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
        err = fabs(pi-piold);
        if ( err < threshold_err){
#pragma omp cancel for
        }

  }
}
  pi = 4*pi;

我用LLVM3.9/Clang4.0编译它。当我使用一个线程运行它时,我就会使用杂注取消操作获得预期的结果(与非语用取消版本进行检查,会导致更快的运行)。

但是当我使用线程>=2运行它时,程序会进入循环。我正在NUMA机器上运行代码。这是怎么回事?也许取消的条件是不满意的!但是,代码比单线程非实用化取消版本花费的时间更长!!FYI,它运行文件时,OMP_CANCELLATION=false。

我有以下OpenMP代码。我正在使用LLVM-3.9/Clang-4.0编译这段代码。

代码语言:javascript
复制
#pragma omp parallel private(i, piold, err) shared(pi, threshold_err)
{
#pragma omp for reduction(+:pi) schedule (static)
  for (i = 0; i < 10000000 ; i++){
        piold = pi;
        pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
        #pragma omp critical
        {
        err = fabs(pi-piold);// printf("Err: %0.11f\n", err);
        }
        if ( err < threshold_err){
                printf("Cancelling!\n");
                #pragma omp cancel for
        }

  }
}

不幸的是,我认为#pragma omp cancel for并没有终止整个for循环。最后,我打印出了err值,但同样由于并行性,打印哪个值令人困惑。err的最终值小于threshold_err。打印取消是打印,但在一开始的程序,这是令人惊讶的。在那之后,程序一直在运行!

如何确保这是正确的实现?顺便说一下,OMP_CANCELLATION设置为true,一个小测试程序返回相应函数omp_get_cancellation()的'1‘。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-13 17:01:48

据我所知,omp取消只是一个中断信号,它会发出通知,以便以后不会创建线程。仍在运行的线程将一直持续到结束。见http://bisqwit.iki.fi/story/howto/openmp/http://jakascorner.com/blog/2016/08/omp-cancel.html

事实上,在我看来,我认为你的程序产品是可以接受的。但是,一些变量可以保持在较小的范围内。这是我的建议

代码语言:javascript
复制
#include <iostream>
#include <cmath>
#include <iomanip>

int main() {

    long double pi = 0.0;
    long double threshold_err = 1e-7;
    int cancelFre = 0;

#pragma omp parallel shared(pi, threshold_err, cancelFre)
    {
#pragma omp for reduction(+:pi) schedule (static)
        for (int i = 0; i < 100000000; i++){
            long double piold = pi;
            pi += (((i&1) == false) ? 1.0 : -1.0)/(2*i+1);
            long double err = std::fabs(pi-piold);
            if ( err < threshold_err){

#pragma omp cancel for
               cancelFre++;
            }

        }
    }

    std::cout << std::setprecision(10) << pi * 4 << " " << cancelFre;

    return 0;
}
票数 1
EN

Stack Overflow用户

发布于 2016-11-16 02:21:41

好吧,所以我解决了。在我上面的代码中,问题就在这里:

err = fabs(pi-piold);

在上面的行中,如果条件发生更改,则在以下条件之前更改pi。同时,多个线程也会这样做。据我所知,这使得程序陷入僵局。

我解决了这个问题,只强制一个线程,主人,做这个检查:

代码语言:javascript
复制
if(omp_get_thread_num()==0){
err = fabs(pi-piold);
if ( err < threshold_err){
#pragma omp cancel for
        }
}

我本可以使用#pragma omp single,但它给嵌套的语用带来了错误。

在这里,线程数量少(1-4个线程比正常的顺序代码差),性能就会受到影响。在那之后,性能提高了。这不是最好的解决办法,而且肯定有人可以改进这一解决办法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40571582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档