共用方式為


D。 使用排程子句

在平行區域到此為止,有一個以上的防護機制,而且有額外的障礙,在其中。 在每個障盾,其他小組成員必須等待最後一個執行緒,才會送達。 這個等待時間減到最少,共用的工作應該分散,讓所有的執行緒分時抵達障盾在大約相同的時間。 如果共用的部份工作包含在建構, schedule子句可用於此用途。

有重複的參考到同一個物件,也就是選擇的排程時, 建構可由主要的記憶體系統中,例如目前狀態與和大小的快取記憶體存取的時間是否為統一或位於特性。 這類考量可能會造成讓一組相同的一系列的迴圈,在陣列的元素一致地參考每個執行緒,即使有些執行緒會被指派相對較少的工作,在某些迴圈。 這可透過使用靜態與相同範圍中的所有迴圈的排程。 在下列範例中,請注意,即使使用在第二個迴圈中,而下限為零 k 會更為自然,如果排程的會議不重要。

#pragma omp parallel
{
#pragma omp for schedule(static)
  for(i=0; i<n; i++)
    a[i] = work1(i);
#pragma omp for schedule(static)
  for(i=0; i<n; i++)
    if(i>=k) a[i] += work2(i);
}

在剩餘的範例中,則會假設該記憶體存取不是主控項的考量,除非有不同的敘述,所有執行緒會都收到類似的運算資源。 在這些情況下,選擇的排程建構取決於要執行最靠近的前導之間的所有共用工作障盾和隱含的結尾屏障或最接近的後續的屏障,如果沒有nowait子句。 排程每一種,簡短範例顯示如何排程這樣可能會是最佳的選擇。 簡短討論以下每個範例。

靜態 排程也是適用於最簡單的情況下,包含一個平行區域 建構,每次反覆運算時需要相同數量的工作。

#pragma omp parallel for schedule(static)
for(i=0; i<n; i++) {
  invariant_amount_of_work(i);
}

靜態排程由下列算式描述屬性的每一個執行緒取得數目相近的反覆項目與任何其他的執行緒,以及每個執行緒可以獨立地決定指派給它的反覆項目。 因此沒有同步處理,才能發佈的工作,並假設每個反覆項目需要相同數量的工作,所有的執行緒應該在完成大約相同的時間。

為一群p的執行緒,讓 ceiling(n/p) 是整數 q,可滿足 n = p * q-r0 < = r < p. 一個實作靜態 排程這個範例會將指定的 q 與第一個反覆項目 p–1 執行緒,以及 q-r 反覆項目到最後一個執行緒。 另一個可接受的實作可能會指派 q 與第一個反覆項目 p-r 執行緒,以及 q-1 反覆項目給剩餘的 r 執行緒。 這說明了為什麼程式不應依賴特定實作的詳細資料。

動態 排程適合的大小寫的 建構包含要求工作的不同,或甚至無法預測,大量的反覆項目。

#pragma omp parallel for schedule(dynamic)
  for(i=0; i<n; i++) {
    unpredictable_amount_of_work(i);
}

動態排程的特點在於沒有執行緒等待障盾的長度超過它所需的另一個執行緒,以執行其最終的反覆項目屬性。 這需要將反覆項目分派一次一個執行緒正在使用時,每個工作分派的同步處理。 同步處理負荷可以減少指定最小的區塊大小 k 大於 1,以便指派執行緒 k 一次最多能 k 會保留。 這可以保證沒有執行緒會等候較長的時間比所需另一個執行緒 (最多) 執行其最後一個區塊的防護機制在 k 反覆項目。

動態排程時相當有用的執行緒會收到不同的運算資源,其中包含針對每個反覆項目工作的資訊量很多相同的效果。 同樣地,動態排程也可以是很有用,如果執行緒分時抵達 建構在不同的時候,即使在這些案例 指引排程可能比較好的做法。

指引 排程適合的大小寫的執行緒可能會到達不同的時間,在 建構包含每個反覆項目需要大約相同數量的工作。 如果這可能會發生,例如, 建構一或多個區段的開頭或建構nowait子句。

#pragma omp parallel
{
  #pragma omp sections nowait
  {
    // ...
  }
  #pragma omp for schedule(guided)
  for(i=0; i<n; i++) {
    invariant_amount_of_work(i);
  }
}

就像動態指引 排程保證沒有執行緒等待時間超過所需另一個執行緒,以執行其最終反覆項目] 或 [完稿障盾 k 反覆項目,如果區塊大小為 k 所指定。 在這類的排程之間指引排程由下列算式描述屬性它需要最少同步處理。 區塊大小的 k,典型的實作將會指派 q = ceiling(n/p) 反覆項目到第一個可用的執行緒,設定 n 較大的 n-qp * k,重覆,直到所有反覆項目會被指派。

當選擇最佳的排程不清楚這些範例中,所顯示的原狀執行階段排程很方便,而不必修改並重新編譯程式實驗不同的排程和區塊大小。 它也相當有用的最佳的排程 (以某種可預測的方式) 定程式所套用的輸入資料時。

若要查看不同的排程之間的取捨的範例,請考慮共用 1000年 8 執行緒之間的反覆項目。 假設沒有在每個反覆項目,工時不變量使用其做為時間單位。

如果所有的執行緒啟動一次, 靜態排程將會造成執行 125 單位,有沒有同步處理建構。 但是,假設一個執行緒會在到達 100 個單位。 然後其餘的七個執行緒等待障盾,在 100 個單位,整個建構執行時間會增加至 225。

因為同時動態指引排程確保沒有執行緒等候障盾在一個以上的單位,延遲的執行緒會使 138 單位時,可能是增加從同步處理的延遲,才能增加建構其執行時間。 不可以忽略這種延遲時,便愈來愈重要的同步處理的數目是 1000年動態 ,但只有 41 的 指引,假設某個預設區塊大小。 區塊大小的 25, 動態指引兩者分別完成 150 單位,加上必要的同步處理哪些現在的數字只有 40 到 20,從任何延遲。