2012-11-04 13 views
11
vector<int> v; 

#pragma omp parallel for ordered schedule(dynamic, anyChunkSizeGreaterThan1) 
    for (int i = 0; i < n; ++i){ 
      ... 
      ... 
      ... 
#pragma omp ordered 
      v.push_back(i); 
    } 

這填充vn大小的有序列表。omp命令子句是如何工作的?

當達到omp ordered塊時,所有線程都需要等待最低可能的迭代線程完成,但如果沒有任何線程被指定爲特定迭代,會怎麼樣呢?還是OpenMP運行時庫總是確保最低的迭代由某個線程處理?

此外,爲什麼建議ordered子句與dynamic schedule一起使用? static schedule會影響性能嗎?

回答

31

ordered子句的工作原理是這樣的:不同的線程同時執行,直到遇到ordered區域,然後按順序執行,順序與在串行循環中執行的順序相同。這仍然允許某種程度的併發性,特別是如果ordered區域以外的代碼部分有相當長的運行時間。

沒有特別的理由使用dynamic時間表而不是static時間表與小塊大小。這完全取決於代碼的結構。由於ordered引入了線程之間的依賴關係(如果與schedule(static)一起使用且缺省塊大小),第二個線程將不得不等待第一個線程完成所有迭代,那麼第三個線程必須等待第二個線程完成其迭代(因此也是第一個),等等。

tid List of  Timeline 
    iterations 
0 0,1,2  ==o==o==o 
1 3,4,5  ==.......o==o==o 
2 6,7,8  ==..............o==o==o 

=表明線程並行執行的代碼:一個可以很容易地用3個線程和9次迭代(3每線程)進行可視化。 o是線程執行ordered區域時。 .是處於空閒狀態的線程,正在等待輪到執行ordered區域。隨着schedule(static,1)下面會發生:

tid List of  Timeline 
    iterations 
0 0,3,6  ==o==o==o 
1 1,4,7  ==.o==o==o 
2 2,5,8  ==..o==o==o 

我相信,在這兩種情況下的差異大於更爲明顯。隨着schedule(dynamic)上面的圖片將變得或多或少是隨機的,因爲分配給每個線程的迭代列表是非確定性的。它也會增加額外的開銷。只有在每次迭代的計算量不同時,計算量需要比使用動態調度的額外開銷時間多得多。

不要擔心編號最小的迭代。它通常被處理爲團隊中的第一個線程,以準備執行代碼。

+0

優秀的答案Hristo!現在都清楚了,謝謝! –

+2

@ Cookie503,請注意,如果塊大小太小,則由於數據局部性丟失,緩存可能會變得不那麼有用。這可能會傷害你的表現比隱含的序列化更糟糕。試驗不同的塊大小,直到達到最佳加速。明智地使用'ordered'循環,如果可能的話避開它們,即使它導致增加的內存佔用 - 例如(根據你的具體例子),應該使用一個簡單的預分配數組(或其他線程安全的隨機訪問容器),而不是一個向量:'arr [i] = i;' –