2016-02-16 87 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循環中聲明變量。