![](/img/trans.png)
[英]openMP lastprivate and firstprivate to the same variable
[英]OpenMP calls and directives allowed in firstprivate variable construction?
我有以下代碼可用於我可用的編譯器(xlC和gcc),但我不知道它是否完全兼容(我沒有在OpenMP 3.0規范中找到明確禁止它的任何內容):
#include <iostream>
#include <vector>
#include <omp.h>
struct A {
int tid;
A() : tid(-1) { }
A(const A&) { tid = omp_get_thread_num(); }
};
int main() {
A a;
std::vector<int> v(10);
std::vector<int>::iterator it;
#pragma omp parallel for firstprivate(a)
for (it=v.begin(); it<v.end(); ++it)
*it += a.tid;
for (it=v.begin(); it<v.end(); ++it)
std::cout << *it << ' ';
std::cout << std::endl;
return 0;
}
我的動機是弄清楚omp並行部分中有多少個線程和每個線程的id(我不希望為每個正在處理的元素調用它)。 我有沒有機會導致未定義的行為?
我只是從循環中解耦(開始)並行區域,並使用私有變量來保持tid:
std::vector<int>::iterator it;
int tid;
#pragma omp parallel private(tid)
{
tid = omp_get_thread_num();
#pragma omp for
for (it=v.begin(); it<v.end(); ++it)
*it += tid;
}
補充:以下是OpenMP規范 (第2.9.3.4節)中的引用,這些引號使我認為您的代碼符合要求,因此不會產生UB (但請參見下面的其他添加內容):
...新的列表項是從構造之前存在的原始列表項初始化的。 對於引用構造中任何語句中的列表項的每個任務,都會對新列表項的初始化執行一次。 初始化在構造執行之前完成。
對於
parallel
或task
構造的firstprivate
子句,新列表項的初始值是在遇到構造的任務區域中緊接構造之前存在的原始列表項的值。C / C ++:...對於類類型的變量,調用復制構造函數來執行初始化。 調用類型的不同變量的復制構造函數的順序是未指定的。
C / C ++:出現在
firstprivate
子句中的類類型(或其數組)的變量需要類類型的可訪問的,明確的復制構造函數。
Added-2:但是,沒有指定哪個線程執行firstprivate
變量的復制構造函數。 所以從理論上講,它可以由區域的主線程完成變量的所有副本。 在這種情況下, omp_get_thread_num()
的值在所有副本中都相等,0或者在嵌套的並行區域的情況下,外部區域中的線程號。 因此,作為OpenMP立場的定義行為,它可能會導致程序中的數據競爭。
當你遍歷向量時,你應該使用它!= v.end(),而不是<v.end()。 但是,在這種情況下,並行for循環不再有效。 我將按以下方式重構代碼的這一部分:
#pragma omp parallel for firstprivate(a)
for (int i = 0 ; i < v.size() ; i++ )
v[i] += a.tid;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.