Ошибка сегментации OpenMP при распараллеливании цикла for с вложенным циклом while - PullRequest
0 голосов
/ 10 мая 2018

У меня есть цикл for, который будет суммировать две переменные, 'Time' и 'successRuns', но количество раз, которое цикл будет выполняться, изменяется внутри цикла случайным образом.(Я думаю, что код самообъясним по этому вопросу)

Проблема в том, что я продолжаю получать ошибку ошибки сегментации.Это не происходит, когда не используется 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;

1 Ответ

0 голосов
/ 10 мая 2018

Глядя на ваш код, кажется, что все переменные являются общими / видимыми между потоками.

Из-за этого, к сожалению, невозможно предсказать, что происходит при выполнении вашего кода, из-за условия параллельной гонки.

Состояние гонки - это когда выполняющиеся потоки находятся в разных частях кода, изменяя значения переменных, когда вы этого не хотите. Причинение непредсказуемого результата.

например:

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() и достигает var++ до того, как второй поток выполняет проверку if(), второй поток введет код else ( вместо if).

Но если второй поток проверяет оператор if() перед тем, как первый изменит значение var, он выполнит var++;, а не var--;.

Таким образом, значение myOnly может быть равно -1 или 1 для обоих только в одном потоке, в зависимости от того, что произошло.

И как мы узнаем, какой из них случится? Мы не Каждый поток работает независимо, нет способа предсказать, что произойдет.

Для этого есть #pragma omp barrier и другие инструменты параллельной синхронизации, но они очень дорогостоящие.

Попытайтесь упорядочить переменные и создать локальные (частные) потоки, чтобы у одного потока не было возможности перезаписать что-либо, чего не должно быть.

...