[英]OpenMP parallelization
我正在編寫一個具有科學目的的 C++ 程序。 該程序運行良好並且返回了良好的結果,因此我決定使用 OpenMP 提高其性能。 我要優化的循環如下:
//== #pragma omp parallel for private(i,j)
for (k=0; k < number; k++)
{
for (i=0; i < L; i++)
{
for (j=0; j < L; j++)
{
red[i][j] = UNDEFINED;
}
}
Point inicial = {L/2, L/2, OCCUPIED};
red[L/2][L/2] = OCCUPIED;
addToList(inicial, red, list, L,f);
oc.push_back(inicial);
while (list.size() > 0 && L > 0)
{
punto = selectPoint(red, list, generator, prob, p);
if (punto.state == OCCUPIED)
{
addToList(punto, red, list, L,f);
oc.push_back(punto);
}
else
{
out.push_back(punto);
}
}
L = auxL;
oc.clear();
out.clear();
list.clear();
}
f = f*1.0/(number*1.0);
if (f > 0.5)
{
inta = inta;
intb = p;
p = (inta + intb) / 2.0;
}
else if (f < 0.5)
{
intb = intb;
inta = p;
p = (inta + intb) / 2.0;
}
cout << p << endl;
}
上面評論了我對 OpenMP 的嘗試。 如您所見,我已將i
和j
聲明為私有,因為它們是在並行部分之前聲明的。 我也嘗試將L
設為私有,但沒有結果。 只有分段錯誤和壞指針無處不在。 我認為問題在於 while 循環嵌套在里面。 我的問題是:在這種情況下, omp parallel for
正確? 或者我應該嘗試只優化那個 while 循環? std::vector
是否會干擾 OpenMP?
注意: list
、 oc
和out
是std::vector<Point>
,而Point
是一個具有三個 int 屬性的簡單結構。 addToList
是一個內部沒有循環的函數。
您可能想閱讀 OpenMP 教程。 當您查看 OpenMP 代碼時,您需要想象並行發生的事情。 拿
oc.push_back(inicial);
兩個線程可以嘗試同時執行此操作嗎? 是的。 std::vector
是否支持並行性? 不。
上面的代碼充滿了這些東西。
如果要在 OpenMP ode 中使用數據結構,則需要使用 locks 。 根據我的個人經驗,當發生這種情況時,重構算法比實際使用它們要好得多。 雖然 OpenMP + 鎖定是可能的,但通常表明該想法存在問題(= 可能的主觀觀點)。
當前的答案指出了代碼中的並發性,但請注意,並非所有數據結構都必須使用鎖來實現以實現線程安全。 還有無lock-free
數據結構。 對於這種特殊情況,我們可以使用 Harris 無鎖鏈表: https : //timharris.uk/papers/2001-disc.pdf
雖然我知道在這一點上向 OP 指出並發問題有很大幫助,但我想確保我們不會通過說鎖對於實現線程安全是絕對必要的來傳達錯誤信息。
#pragma omp parallel 指令定義了一段可以由多個線程同時執行的代碼。 在您的情況下,由於您沒有指定任何進一步的指令,您的並行區域將被每個線程執行一次。 為了實現並行行為,您可以嘗試將循環分解為更小的任務(taskloop 指令將完成這項工作)。 這些任務將保留在任務池中,直到線程開始執行它們。 這樣,您的循環將被分割並由您的線程執行,而不是讓每個線程執行整個循環。
https://www.openmp.org/spec-html/5.0/openmpsu47.html這里是 taskloop 指令的官方 openMP 文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.