簡體   English   中英

在 openMP 中增加數組索引

[英]Increasing array index in openMP

我剛開始使用 OpenMP。 我正在嘗試並行化一個嵌套循環,到目前為止我有這種形式的東西......

#pragma omp parallel for
for (j=0;j <m; j++) {
    some work;
    for (i= 0; i < n ; i++) {
        p =b[i];
        if (P< 0 && k < m) {
            a[k] = c[i]; k++ ;
        } else {
            x=c[i];
        }
    }
    some work
}

外循環是並行的,內循環更新k 其他線程需要k的當前值才能正確更新a[k] 問題是所有線程都在更新a[k] ,但是 k 的正確順序沒有保持。

有些線程會更新ka[k] ,有些則不會。 我如何在線程之間傳遞最新的k以正確更新a[k] ,因為c[i]對每個線程都有不同的值?

例如,當它串行運行時,程序可能會將a的前七個值設置為{1,3,5,7,3,9,13}並以k等於 7 終止,但是當並行運行時,會產生不同的結果,或導致不同的(因此是錯誤的)順序。

如何保持相同的順序並同時確保並行性?

注意:根據 OP 的說明,此答案已完全重寫。 原答案在文末。

如何保持相同的順序並同時確保並行性?

順序依賴與並行是對立的,因為並行運行操作本質上需要放寬執行它們的相對順序。 並非所有計算都可以有效地並行化。

你的情況也不例外。 外循環的第二次和每次后續迭代需要使用上一次迭代計算的k的最終值(除其他外)。 它怎么能得到那個? 只有先執行前一次迭代。 這為並發操作留下了什么空間? 沒有任何。 並發性與並行性不同,但它是並行性的主要動機之一,因為這就是並行性在運行時間上產生改進的方式。

由於沒有 scope 用於並發,並行性對您來說會適得其反。 假設您將外部循環的整個主體設為關鍵部分,因此實際上沒有並發性(正如您當前的代碼所要求的那樣)並且沒有涉及k的數據競爭。 那么你仍然會為並行性付出開銷,得不到加速作為回報,並且可能仍然會因為以錯誤的順序執行外循環體的評估而得到錯誤的結果。

可能整個事情都可以重寫以減少或刪除阻止計算有效並行化的數據依賴性,也可能不會。 我們沒有足夠的信息來確定,因為它部分取決於“ some work ”的細節和數據的重要性。 可能您需要一種完全不同的算法來產生所需的結果。

> 而不是給 a[n]={0,1,2,3,.......n},當我使用 reduction 子句時,它給我 a 的垃圾值。 我需要 K 的總和,因此需要減少條款。

連續整數之和有一個封閉式方程,當列表中的第一個 integer 為 0 或 1 時,它具有特別簡單的形式。特別地,從 0 到n的整數之和為n * (n + 1) / 2 你不需要為此減少。

如果您無論如何都想使用縮減,那么您需要了解它並不像您認為的那樣工作。 您得到的是每個執行並行構造的線程的縮減變量的單獨私有副本,這些獨立變量的每個線程(而不是每次迭代)最終值根據縮減運算符組合。 因此,如果您真的想通過 OpenMP 歸約來進行計算,那么您需要像這樣重構循環:

 #pragma omp parallel for reduction (+:k) for (i = 0; i < 10; i++) { a[i] = i; k += i; }

這假設k的值在循環之前立即為 0,正如您確實在做的那樣。 如果那不是一個安全的假設,那么您將需要類似

type_of_k k0 = k; k = 0; #pragma omp parallel for reduction (+:k) for (i = 0; i < 10; i++) { a[k0 + i] = i; k += k0 + i; }

請注意,在任何一種情況下,這不僅正確地設置了縮減,而且還打破了先前由表達式k++攜帶的循環迭代之間的數據依賴性。

聽起來您實際上是在使用來自c的條目過濾器來填充a ,並希望保留它們的順序。 如果這是k的唯一用途,請記住其他一些方法 spring:

  1. 總是寫a[i] ,但使用一個標記來指示不滿足 P 謂詞的未使用值。 這保留了順序,但需要更大a您可以在第二遍中進行壓縮。

  2. 寫一個a_i數組存儲每個條目屬於哪個索引。 這仍然需要#pragma omp atomic k_local = k++訪問k ,並進行第二次排序以恢復順序。 而且您需要aa_i再次成為完整大小,否則您可能會錯過條目,因此這是一個糟糕的解決方法。

即使有一些順序依賴關系,您也可以進行優化,例如scan計算每個ik可以在 O(log n) 而不是 O(n) 中完成。 例如並行前綴和關於堆棧溢出的 openmp 討論 我相信,這種事情就是 OpenMP 的ordered depend 無論如何,這導致了第三種解決方案:

  1. 生成一個k數組,保存k每次迭代將具有的值,以便那些將寫入的線程寫入正確的位置。 這需要掃描謂詞。

在規划算法時,擁有更高級別的構造(如 map、掃描和減少)很有用。

暫無
暫無

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

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