【问题标题】:OpenMP segmentation fault when parallelising a for loop with nested while loop将 for 循环与嵌套的 while 循环并行化时出现 OpenMP 分段错误
【发布时间】:2018-05-10 12:17:37
【问题描述】:

我有一个 for 循环,它将总结两个变量,“时间”和“成功运行”,但循环运行的次数在循环内随机更改。 (我认为代码在这个问题上是不言自明的)

问题是我不断收到分段错误错误。不使用 openmp 时不会发生这种情况。

这是我尝试并行运行的循环。

rnd() 是一个函数,它返回一个介于 0 和 1 之间的随机数。

    #pragma omp parallel for
    for(w=1; w<=200000; w++){
        tau=0;
        for(i=0; i<N; i++) g[i]=1;
        g[0] = 2;
        N_a=N-1;
        N_b=1;
        b=false;
        while(b== false){
            tau++;
            R = rnd() * (N_a + N_b*r_b);    
            prev=0; next=0;
            chosenB = N;
            for(i=0; i<N; i++){
                if(g[i]==1) next = prev + 1.0;
                    else next = prev + r_b;
                if(R>prev && R<next){
                    chosenB = i; break;
                }
                prev = next;
            }
            R = rnd() * N;
            while(int(R)==chosenB)
                R = rnd() * N;      
            if(g[int(R)]==1) N_a--;
                else N_b--;
            g[int(R)] = g[chosenB];     
            if(g[chosenB] == 1) N_a++;
                else N_b++;
            if(N_b == N){
                b = true; break;
            }
            if(N_b == 0){
                b = false; break;
            }
        }
        if(g[0]==2 && b==true){     
            Time += tau;
            successRuns++;
        }
        if(b==false) w--;
        runs++;
    }
    //end of parallel
    cout<<Time/successRuns<<endl;
    cout<<successRuns/runs<<endl;

【问题讨论】:

    标签: c++ parallel-processing openmp


    【解决方案1】:

    查看您的代码,似乎所有变量在线程之间都是共享/可见的。

    因此,不幸的是,由于并行竞争条件,无法预测代码执行过程中发生的情况。

    竞争条件是当执行线程位于代码的不同部分时,当你不想要它时更改变量值。造成不可预知的结果。

    例如:

    int main(){
        int var=0;    //shared variable, visible to all threads
    
        #pragma omp parallel
        {
            int myOnly;    //private variable, each thread have it's own
            if ( var <= 0)
                var++;
            else
                var--;
    
            myOnly = var;
            printf("private variable: %d\n",myOnly);
        }
        printf("value : %d", var);
    }
    

    假设我们这里有2个正在运行的线程,如果第一个线程执行if()检查并在第二个线程执行if()检查之前到达var++,那么第二个线程将进入else代码(而不是 if )。

    但如果第二个线程在第一个线程更改var 的值之前检查if() 语句,它将执行var++;,而不是var--;

    这样,myOnly 的值可以是 -1 或 1,仅在一个线程上,这取决于发生了什么。

    我们怎么知道其中一个会发生?我们没有。 每个线程都是独立运行的,无法预测会发生什么。

    为此,有#pragma omp barrier 和其他并行同步工具,但它们非常昂贵。

    尝试组织变量并为线程创建本地(私有)变量,这样一个线程就没有机会覆盖它不应该覆盖的东西。

    【讨论】:

    • pages.tacc.utexas.edu/~eijkhout/pcse/html/omp-data.html 在本指南中指出,在每次迭代中每次设置和使用变量时,都会将它们设为私有。这是错的吗?我应该使用 private(i,fixed,g,...) 并列出我的所有变量吗?
    • 好吧,本指南说如果变量在#pragma omp 并行范围之外声明,它是共享的,而内部是私有的。我将编辑我的答案解释得更好。
    • @Alireza,你运行了多少线程?你是怎么计算时间的?
    • 尝试更好地在线程之间划分步骤。也许你多次做同样的工作。还有一个提示:当您在 openMP 中使用 clock() 时,它会汇总所有正在运行的线程的总时钟,因此如果您有 4 个线程,它将显示总时钟的 4 倍。
    • 如果你说它就做,就像在#pragma omp parallel for 中,步骤在线程之间划分。但是如果你只使用#pragma omp parallel,完全相同的代码将在所有线程中运行。有很多工具(例如 pragma omp parallel )可以以更具体的方式划分代码/工作。尝试在谷歌上搜索它。
    猜你喜欢
    • 1970-01-01
    • 2016-07-23
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多