Создание рекурсивной задачи приводит к ошибке сегментации в OpenMP - PullRequest
0 голосов
/ 03 марта 2020

Я пытаюсь реализовать решатель nqueens с OpenMP, мой последовательный код работает нормально, но когда я пытаюсь выполнить параллелизм задач, я получаю ошибку сегментации или пустые строки / столбцы.

Вот моя реализация :

#define N 8
bool SOLUTION_EXISTS = false; // THIS IS GLOBAL

bool solve_NQueens(int board[N][N], int col) 
{ 

    if (col == N) 
    { 
        #pragma omp critical
            print_solution(board); 
        SOLUTION_EXISTS = true;
        return true; 
    } 

    for (int i = 0; i < N; i++) 
    {  
        if (can_be_placed(board, i, col) ) 
        { 
            #pragma omp taskgroup
            {   
                #pragma omp task private(col) shared(i) firstprivate(board)
                {
                    board[i][col] = 1; 
                    SOLUTION_EXISTS = solve_NQueens(board, col + 1) || SOLUTION_EXISTS; 
                    board[i][col] = 0; 
                }
            }    
        } 
    } 
    return SOLUTION_EXISTS; 
}

И первый вызов этой функции:

#pragma omp parallel
{
    #pragma omp single
    {
        solve_NQueens(board, 0);
    }
}

Когда я делаю col частным, это вызывает ошибку сегментации. Если я не ставлю переменную область видимости, печатаются неоднозначные и неправильные решения.

И я использую gcc 4.8.5

1 Ответ

1 голос
/ 04 марта 2020

Решение

Ошибка сегментации, так как вы используете private(col). Таким образом, col не копируется из вашей функции и даже не инициализируется. Используйте firstprivate(col), чтобы сделать правильную копию col.

Advise

omp taskgroup заставит ваш код работать последовательно, так как в конце области видимости существует неявный барьер. Вероятно, лучше этого избежать (например, используя omp taskwait в конце l oop и немного изменив остальную часть кода). Если вы хотите изменить это, обратите внимание, что i необходимо копировать, используя firstprivate вместо shared.

Более того, избегайте использования глобальных переменных, таких как SOLUTION_EXISTS, в параллельном коде. Это обычно вызывает много проблем от порочных ошибок до медленных кодов. И если вам все еще нужно / нужно сделать это, переменные, используемые в нескольких потоках , должны быть защищены с использованием, например, директив omp atomic или omp critical.

...