递归任务创建导致 OpenMP 中的分段错误
Recursive task creation results in segmentation fault in OpenMP
我正在尝试使用 OpenMP 实现 nqueens 求解器,我的串行代码工作正常,但是当我尝试对其执行任务并行时,出现分段错误或空 rows/cols。
这是我的实现:
#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
并稍微更改其余代码)。
如果您想更改它,请注意必须使用 firstprivate
而不是 shared
.
复制 i
此外,避免在并行代码中使用像 SOLUTION_EXISTS
这样的全局变量。这通常会导致 lot 从恶性错误到缓慢代码的问题。如果您仍然 need/want 这样做,则 多线程 中使用的变量必须 受保护 使用例如 omp atomic
或 omp critical
指令。
我正在尝试使用 OpenMP 实现 nqueens 求解器,我的串行代码工作正常,但是当我尝试对其执行任务并行时,出现分段错误或空 rows/cols。
这是我的实现:
#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
并稍微更改其余代码)。
如果您想更改它,请注意必须使用 firstprivate
而不是 shared
.
i
此外,避免在并行代码中使用像 SOLUTION_EXISTS
这样的全局变量。这通常会导致 lot 从恶性错误到缓慢代码的问题。如果您仍然 need/want 这样做,则 多线程 中使用的变量必须 受保护 使用例如 omp atomic
或 omp critical
指令。