[英]Why is parallel execution slower than sequential for this code?
#pragma omp parallel
{
for (i=1; i<1024; i++)
#pragma omp for
for (j=1; j<1024; j++)
A[i][j] = 2*A[i-1][j];
}
我正在使用12個線程來執行此代碼。 有什么建議我必須加快速度嗎?
假設A的類型小於64Byte,嘗試以這種方式並行化內部循環很可能會導致您在緩存行中共享錯誤。
假設A是4字節整數的對齊數組,則在同一緩存行中將具有A [i] [0]至A [i] [15]。 這意味着所有12個線程都將嘗試同時讀取該行,每個線程都需要讀取該行,如果您將其留在那,則可能導致該行在多個內核之間共享,但是您還嘗試寫回去,導致每個核心嘗試擁有所有權以進行修改。
CPU緩存通常基於基於MESI的協議,使存儲嘗試發出所有權的讀取,這將使除請求者之外的每個其他內核中的行無效。 發出12個並行信號(如果您有6個核心* 2個線程,則發出6個並行信號)將導致比賽,其中第一個贏得該線路的人很可能在沒有機會對其進行修改之前就搶先一步搶走了他(雖然不太可能)。 結果是非常混亂的,並且可能需要一段時間才能將生產線依次轉到每個核心,然后進行修改,然后被另一個核心偵聽。 下一個連續的16個元素組中的每個重復出現一次(同樣,假定為int)。
您可能會做的是:
但是,這將使您無法充分利用CPU的潛力,因為您會丟失代碼的空間局部性和流屬性。 相反,您可以:
這里仍然有一個缺點,因為如果線程遇到太多的流,可能會失去對它們的跟蹤。 因此,第三種方法是-
1)您擁有幾個核心? 您無法獲得比這更多的並行化速度,而且正如其他人所說的那樣,可能要少得多。
2)看起來內部索引j
應該從0開始,而不是1。
3)內循環正在為指針和展開吶喊,就像
double* pa = &A[i][0];
double* pa1 = &A[i-1][0];
for (j = 0; j < 1024; j += 8){
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
*pa++ = 2 * *pa1++;
}
要么...
double* pa = &A[i][0];
double* paEnd = &A[i][1024];
double* pa1 = &A[i-1][0];
for (; pa < paEnd; pa += 8, pa1 += 8){
pa[0] = 2 * pa1[0];
pa[1] = 2 * pa1[1];
pa[2] = 2 * pa1[2];
pa[3] = 2 * pa1[3];
pa[4] = 2 * pa1[4];
pa[5] = 2 * pa1[5];
pa[6] = 2 * pa1[6];
pa[7] = 2 * pa1[7];
}
以較快者為准。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.