簡體   English   中英

OpenMP並行代碼變慢

[英]OpenMP parallel code slower

我有兩個要並行化的循環

#pragma omp parallel for
  for (i = 0; i < ni; i++)
    for (j = 0; j < nj; j++) {
      C[i][j] = 0;
      for (k = 0; k < nk; ++k)
        C[i][j] += A[i][k] * B[k][j];
    }
#pragma omp parallel for
  for (i = 0; i < ni; i++)
    for (j = 0; j < nl; j++) {
      E[i][j] = 0;
      for (k = 0; k < nj; ++k)
        E[i][j] += C[i][k] * D[k][j];
    }

奇怪的是,即使使用大量線程,順序執行也比並行版本要快得多。 難道我做錯了什么? 請注意,所有數組都是全局的。 這有什么區別嗎?

並行外部循環的迭代共享其內部循環的索引變量( jk )。 這肯定會使您的代碼比您預期的要慢一些,即,您的循環不會“尷尬” (或“令人愉快”)並行和並行循環迭代需要以某種方式從共享內存訪問這些變量。

更糟糕的是,因此,您的代碼包含競爭條件 結果,它將無法確定地運行。 換句話說:您的並行矩陣乘法實現現在不正確! (繼續檢查計算結果。))

您要做的是確保外部循環的所有迭代都具有索引變量jk的專用副本。 您可以通過在並行循環范圍內聲明以下變量來實現此目的:

int i;

#pragma omp parallel for
  for (i = 0; i < ni; i++) {
    int j1, k1;  /* explicit local copies */
    for (j1 = 0; j1 < nj; j1++) {
      C[i][j1] = 0;
      for (k1 = 0; k1 < nk; ++k1)
        C[i][j1] += A[i][k1] * B[k1][j1];
    }
  }        
#pragma omp parallel for
  for (i = 0; i < ni; i++) {
    int j2, k2;  /* explicit local copies */
    for (j2 = 0; j2 < nl; j2++) {
      E[i][j2] = 0;
      for (k2 = 0; k2 < nj; ++k2)
        E[i][j2] += C[i][k2] * D[k2][j2];
    }
  }

或在循環編譯中將它們聲明為private

int i, j, k;

#pragma omp parallel for private(j, k)
  for (i = 0; i < ni; i++)
    for (j = 0; j < nj; j++) {
      C[i][j] = 0;
      for (k = 0; k < nk; ++k)
        C[i][j] += A[i][k] * B[k][j];
    }
#pragma omp parallel for private(j, k)
  for (i = 0; i < ni; i++)
    for (j = 0; j < nl; j++) {
      E[i][j] = 0;
      for (k = 0; k < nj; ++k)
        E[i][j] += C[i][k] * D[k][j];
    }

這些更改會使並行實現比順序實現更快嗎? 很難說。 這取決於您的問題大小。 並行化(特別是通過OpenMP進行並行化)會帶來一些開銷。 僅當產生足夠的並行工作時,在並行線程上分配工作的收益才會超過產生的間接費用。

為了找出足以滿足您的代碼和軟件/硬件平台需求的工作量,建議您以不同的矩陣大小運行代碼以進行實驗。 然后,如果您還期望矩陣尺寸太小而無法作為計算的輸入,則可能需要使並行處理成為條件處理(例如,使用if -clauses修飾循環編譯):

#pragma omp parallel for private (j, k) if(ni * nj * nk > THRESHOLD)
  for (i = 0; i < ni; i++) {
     ...
  }
#pragma omp parallel for private (j, k) if(ni * nl * nj > THRESHOLD)
  for (i = 0; i < ni; i++) {
    ...
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM