0

这是我到目前为止解决return 1;,所做的return 0;,它实际上是一个使用回溯算法的数独求解器,所以我试图并行化它,但我无法得到完整的结果。(如果我的实施有误,请纠正我)实际发生了什么?有人可以帮忙吗?!

这是我指的网站,我曾经按照他们的方式行事:http ://www.thinkingparallel.com/2007/06/29/break-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以前把它去掉了,但是结果不完整,还是在数独中留下了几个空格。

感谢您的回答:>

4

1 回答 1

0

首先,由于solver是递归调用的,它使每个递归级别的线程数加倍。我不认为这是你打算做的。 编辑:仅当使用 启用嵌套并行性时才适用omp_set_nested(),默认情况下不是。所以只有第一次调用solverwill fork。

#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)无论如何,即使您设法调试/更改代码以正确并行运行(正如我自己所做的那样 -如果有人感兴趣,我会尝试提供代码,哪个我怀疑),结果将是此代码的并行执行不会给您带来太多优势。我心中的原因如下:

想象一下什么时候solver迭代超过 9 个可能的单元格值,它会创建 9 个执行分支。如果您使用 OpenMP 创建 2 个线程,它将以某种方式在线程之间分配顶级分支,例如一个线程执行 5 个分支,另一个线程执行 4 个分支,并且每个线程中的分支将一个接一个地连续执行。如果初始数独状态有效,则只有一个分支会导致正确的解决方案。其他分支在遇到解决方案差异时会被缩短,因此有些运行时间较长,有些运行时间较短,而导致正确解决方案的分支运行时间最长。您无法预测执行哪些分支需要什么时间,因此无法合理地平衡线程之间的工作负载。即使您使用 OpenMP 动态调度,也有可能当一个线程执行最长的分支时,

由于创建线程并在它们之间同步数据会产生一些重大开销(与solver0.01-10 毫秒的顺序运行时间相比),您会看到并行执行时间比顺序执行时间稍长或稍短,具体取决于输入。

无论如何,如果顺序求解器的运行时间低于 10 毫秒,为什么要让它并行呢?

于 2012-09-14T09:36:02.470 回答