2016-02-16 53 views
0

也许我的问题的解决方案是非常明显的。我想用openMP(英特尔至强融核)加速下面的代码,但我不能。如何使用openMP并行化内部循环?

int c=0, d=0, e=0, i; 
#pragma opm parallel for private(c, d, e) 
for(i=0; i < columns; i++) 
{ 
    if((left_side[rule*columns + i] > 0) || (right_side[rule*columns + i] > 0)) 
    { 
    for(c=0; c < rows; c++) 
    { 
     if(left_side[i + c * columns] > 0) 
     { 
     if(flag[c] == 0) 
     { 
      r_prob[c] = c_vect[c]; 
      flag[c] = 1; 
      for(d=0; d < columns; d++) 
      { 
      switch(left_side[c * columns + d]) 
      { 
       case 0: 
       break; 
       case 1: 
       r_prob[c] *= M_in[d] * 1.0; 
       break; 
       case 2: 
       r_prob[c] *= (M_in[d] * (M_in[d] - 1)) * .5; 
       break; 
       default: 
       for(e=1; e <= left_side[c * columns + d]; e++) 
        r_prob[c] *= M_in[d] * 1.0/(e * 1.0); 
       break; 
      } 
      } 
     } 
     } 
    } 
    } 
} 
//where r_prob, M_in, left_side, right_side, c_vect and flag are array that are in input. 

此代码无法正确运行,r_prob中的值错误。 我如何可以并行化这段代码?

+2

为什么'c','d','e'和最重要的'i'没有在并行循环中声明的具体原因是什么? – Haatschii

+0

我想是因为它是用纯C语言编程的。在C++中,您可以在每个FOR中声明变量 –

回答

1

你的代码有错误,因为第一个FOR创建多个线程,并且这些同时写入数组r_prob,flag。该解决方案是:

int c=0, d=0, e=0, i; 
#pragma opm parallel for private(c, d, e) 
for(i=0; i < columns; i++) 
{ 

if((left_side[rule*columns + i] > 0) || (right_side[rule*columns + i] > 0)) 
{ 
    for(c=0; c < rows; c++) 
    { 
    if(left_side[i + c * columns] > 0) 
    { 
    if(flag[c] == 0) 
    { 
     #pragma omp critical //Only one thread at a time can enter 
     { 
     r_prob[c] = c_vect[c]; 
     flag[c] = 1; 
     } 

     for(d=0; d < columns; d++) 
     { 
     switch(left_side[c * columns + d]) 
     { 
      case 0: 
      break; 
      case 1: 
      #pragma omp critical //Only one thread at a time can enter 
      { 
      r_prob[c] *= M_in[d] * 1.0; 
       } 
      break; 
      case 2: 
      #pragma omp critical //Only one thread at a time can enter 
      { 
      r_prob[c] *= (M_in[d] * (M_in[d] - 1)) * .5; 
      } 
      break; 
      default: 
      for(e=1; e <= left_side[c * columns + d]; e++) 
       #pragma omp critical //Only one thread at a time can enter 
       { 
       r_prob[c] *= M_in[d] * 1.0/(e * 1.0); 
       } 
      break; 
      } 
      } 
     } 
    } 
    } 
} 
}//where r_prob, M_in, left_side, right_side, c_vect and flag are array that are in input. 
1

的问题是,不同的线程写入和同一r_prob[c]可变的读取。使用此算法,您可以仅通过c并行化循环。即写:

for(int i=0; i < columns; i++) 
{ 
    if((left_side[rule*columns + i] > 0) || (right_side[rule*columns + i] > 0)) 
    { 
    #pragma omp parallel for 
    for(int c=0; c < rows; c++){ 
     //.... 

或者你可以使用语法:

#pragma omp critical 
{ 
    r_prob[c] *= ... 
} 

语法,只允许一个线程一次访问阵列。

哪一个更快取决于数组的大小和线程数。

正如Haatschii所述,最好在for循环中声明变量。