如何解决open mp中for循环中的“return 0或return 1”?

时间:2012-09-13 21:57:20

标签: c openmp

这是我到目前为止解决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;

1 个答案:

答案 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毫秒,为什么要使它并行?