2016-11-26 49 views
2

我已經寫了這個代碼讀取矩陣,它基本上總結了矩陣的值...但是我的問題是,因爲我嘗試以不同的方式執行雜注,我發現reduction (+:sum)不會是必要的,但是,我只是不知道爲什麼,在這種情況下,我可能錯過了減排系統的實際意義。這將是替代:#pragma omp parallel for private(i, j) reduction (+:sum)什麼時候需要減少?

,這將是代碼:

#include <stdio.h> 
#include <math.h> 
#include <omp.h> 
#include <unistd.h> 


int main() 
{ 

    printf("===MATRIX SUM===\n"); 
    printf("N ROWS: "); 
    int i1; scanf("%d",&i1); 
    printf("M COLUMNS: "); 
    int j1; scanf("%d",&j1); 
    int matrixA[i1][j1]; 

    int i, j; 

    for(i = 0; i < i1; i++){ 
     for (j = 0; j < j1; j++){ 
      scanf("%d",&matriuA[i][j]); 
     } 
    } 

    printf("\nMATRIX A: \n"); 
    for (i = 0; i < i1; i++){ 
     for (j = 0; j < j1; j++){ 
      printf("%d ", matrixA[i][j]); 
     } 
     printf("\n"); 
    } 
    int sum = 0; 
    #pragma omp parallel for private(i, j) 
     for (i = 0; i < i1; i++) 
      for (j = 0; j < j1; j++){ 
       sum += matrixA[i][j]; 
      } 


    printf("\nTHE RESULT IS: %d", sum); 

    return 0; 
} 

而且,我想問一下,是否會有像,有關編譯還原一個更好的解決方案,因爲我讀的是最有效的方法。

+0

您應該同時放置縮減和'sum + = ..',因爲您希望單個OpenMP線程執行'sum + = ...',並減少每個OpenMP thead的總和變量。 – yakoudbz

+0

如果我理解你的效率是什麼意思,那麼即使需要單獨命名的內部和外部還原變量,也希望在每個線程內減少simd以及外部循環縮減。 – tim18

回答

5

您發佈的代碼是不減少條款不正確。當通過並聯多個線程執行

sum += matrixA[i][j]; 

會導致經典競爭狀態。總和是一個共享變量,但sum += ...不是原子操作。

(sum is initially 0, all matrix elements 1) 
Thread 1      | Thread 2 
----------------------------------------------------------- 
tmp = sum + matrix[0][0] = 1 | 
          | tmp = sum + matrix[1][0] = 1 
sum = tmp = 1    | 
          | sum = tmp = 1 (instead of 2) 

這個縮減修正了這一點。在減少的情況下,循環將在sum變量的隱式線程本地副本上工作。在區域末尾,原始sum變量將被設置爲所有線程本地副本的總和(以正確的方式沒有競態條件)。

另一種解決方案是將sum += ...標記爲原子操作或臨界區。然而,這具有顯着的性能損失。

相關問題