[我正在尝试使用OpenMP实现nqueens求解器,我的串行代码工作正常,但是当我尝试对此执行任务并行处理时,会出现分段错误或行/列为空。
这是我的实现:
#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
因为使用private(col)
,所以存在分段错误。因此,col
不会从您的函数中复制,甚至不会初始化。使用firstprivate(col)
正确复制col
。
omp taskgroup
将使您的代码按顺序运行,因为作用域末尾存在隐式障碍。最好避免这种情况(例如,在循环结束时使用omp taskwait
并在其余代码中稍加更改)。如果要更改此设置,请注意,必须使用i
而不是firstprivate
复制shared
。
此外,请避免在并行代码中使用诸如SOLUTION_EXISTS
之类的全局变量。通常,这会导致从恶性错误到速度慢的代码的问题。并且,如果您仍然需要/想要这样做,则必须使用例如omp atomic
或omp critical
指令对多线程中使用的变量进行保护。