这是我到目前为止解决return 1;
,return 0;
所做的事情,它实际上是一个使用回溯算法的数独求解器,所以我试图将它并行化,但我无法完成结果。 (如果我的实施错误,请纠正我)
实际发生了什么?
任何人都可以帮忙吗?!
这是我所指的网站,我曾经按照他们的方式:http://www.thinkingparallel.com/2007/06/29/breaking-out-of-loops-in-openmp/#reply
int solver (int row, int col)
{
int i;
boolean flag = FALSE;
if (outBoard[row][col] == 0)
{
#pragma omp parallel num_threads(2)
#pragma omp parallel for //it works if i remove this line
for (i = 1; i < 10; i++)
{
if (checkExist(row, col, i)) //if not, assign number i to the empty cell
outBoard[row][col] = i;
#pragma omp flush (flag)
if (!flag)
{
if (row == 8 && col == 8)
{
//return 1;
flag = TRUE;
#pragma omp flush (flag)
}
else if (row == 8)
{
if (solver(0, col+1))
{
//return 1;
flag = TRUE;
#pragma omp flush (flag)
}
}
else if (solver(row+1, col))
{
//return 1;
flag = TRUE;
#pragma omp flush (flag)
}
}
}
if (flag) { return 1; }
if (i == 10)
{
if (outBoard[row][col] != inBoardA[row][col])
outBoard[row][col] = 0;
return 0;
}
}
else
{
if (row == 8 && col == 8)
{
return 1;
}
else if (row == 8)
{
if (solver(0,col+1)) return 1;
}
else
{
if (solver(row+1,col)) return 1;
}
return 0;
}
}
5 0 0 0 0 3 7 0 0
7 4 6 1 0 2 3 0 0
0 3 8 0 9 7 5 0 2
9 7 0 4 0 0 2 0 0
0 0 2 0 0 0 4 0 0
0 0 4 0 0 5 0 1 9
4 0 3 2 7 0 9 8 0
0 0 5 3 0 9 6 7 4
0 0 7 5 0 0 0 0 3
Sudoku solved :
5 2 9 8 0 3 7 4 1
7 4 6 1 5 2 3 9 0
1 3 8 0 9 7 5 6 2
9 7 0 4 1 0 2 3 6
0 1 2 9 6 0 4 5 8
3 6 4 7 8 5 0 1 9
4 0 3 2 7 6 9 8 5
2 8 5 3 0 9 6 7 4
6 9 7 5 4 8 1 2 3
//return 1;
是原始的序列号,因为return
中不允许parallel for
,因此我使用#pragma opm flush
来消除它,但结果并不完整,它仍然在数独中留下了几个空格子。
感谢您的回答:&gt;
答案 0 :(得分:0)
首先,由于solver
是递归调用的,因此它会使每个递归级别的线程数加倍。我不认为这是你打算做的。
修改:仅当使用omp_set_nested()
启用嵌套并行时才会出现这种情况,默认情况下不是。{因此,只有solver
的第一次调用才会分叉。
#pragma omp parallel num_threads(2)
#pragma omp parallel for
代码中的尝试在另一个内部创建一个并行区域,并且它将导致后面的循环执行两次,因为外部parallel
已经创建了两个线程。这应该替换为
#pragma omp parallel num_threads(2)
#pragma omp for
或同等的#pragma omp parallel for num_threads(2)
。
其次,这段代码:
if (checkExist(row,col,i))//if not, assign number i to the empty cell
outBoard[row][col] = i;
创建竞争条件,两个线程并行地向同一个单元写入不同的值。您可能希望为每个要使用的线程创建一个单独的电路板副本。
另一个代码部分,
if (outBoard[row][col] != inBoardA[row][col])
outBoard[row][col] = 0;
似乎在并行区域之外,但在对solver
的嵌套调用中,它也在由最外层solver
创建的不同线程中并行执行。
最终(e)(18.09)无论如何,即使您设法调试/更改您的代码以便并行正确运行(因为我自己也只是为了它 - i如果有人感兴趣,我会尝试提供代码,我怀疑),结果将是并行执行此代码并没有给你带来太多好处。我的理由如下:
想象一下,当solver
迭代9个可能的单元格值时,它会创建9个执行分支。如果使用OpenMP创建2个线程,它将以某种方式在线程之间分配顶级分支,比如说一个线程执行5个分支,另一个线程执行4个分支,并且在每个线程中,分支将逐个连续执行。如果初始数据状态有效,则只有一个分支将导致正确的解决方案。当其他分支机构在解决方案中遇到差异时会被缩短,因此有些分支机构需要更长的时间,有些分支机构需要更短的时间才能运行,而导致正确解决方案的分支机构运行时间最长。您无法预测哪些分支将花费多长时间执行,因此无法合理平衡线程之间的工作负载。即使你使用OpenMP动态调度,很可能当一个线程执行最长的分支时,其他线程已经完成所有其他分支并将等待最后一个分支,因为分支太少(因此动态调度将是一点帮助)。
由于创建线程并在它们之间同步数据会产生一些实质性开销(与0.01-10 ms的连续solver
运行时间相比),您会发现并行执行时间比顺序更长或更短,具体取决于输入
在任何情况下,如果顺序解算器的运行时间小于10毫秒,为什么要使它并行?