簡體   English   中英

OpenMP迭代for循環並行區域

[英]OpenMP iteration for loop in parallel region

對不起,如果標題是一個很大的不清楚。 我不太清楚怎么說這個。

我想知道我是否有辦法做到以下幾點:

#pragma omp parallel
{
    for (int i = 0; i < iterations; i++) {
        #pragma omp for
        for (int j = 0; j < N; j++)
            // Do something
    }
}

忽略諸如在for循環中省略私有說明符之類的東西,有什么方法可以在我的外部循環之外分叉線程,這樣我就可以並行化內部循環? 從我的理解(如果我錯了請糾正我),所有線程將執行外部循環。 我不確定內循環的行為,但我認為for會將塊分配給遇到它的每個線程。

我想要做的是不需要fork / join iterations次數,而只需在外部循環中執行一次。 這是正確的策略嗎?

如果有另一個外環不應該並行化怎么辦? 那是...

#pragma omp parallel
{

    for (int i = 0; i < iterations; i++) {
        for(int k = 0; k < innerIterations; k++) {
            #pragma omp for
            for (int j = 0; j < N; j++)
                // Do something

            // Do something else
        }
    }
}

如果有人向我指出使用OpenMP並行化的大型應用程序的示例,那將是很好的,這樣我就可以更好地理解使用OpenMP時要采用的策略。 我似乎找不到任何東西。

澄清:我正在尋找不會改變循環排序或涉及阻塞,緩存和一般性能考慮因素的解決方案。 我想了解如何在OpenMP上對指定的循環結構進行此操作。 // Do something可能有也可能沒有依賴,假設他們這樣做,你不能移動東西。

處理這兩個for循環的方式對我來說是正確的,因為它實現了你想要的行為:外部循環不是並行化的,而內部循環是。

為了更好地說明會發生什么,我會嘗試在代碼中添加一些注釋:

#pragma omp parallel
{
  // Here you have a certain number of threads, let's say M
  for (int i = 0; i < iterations; i++) {
        // Each thread enters this region and executes all the iterations 
        // from i = 0 to i < iterations. Note that i is a private variable.
        #pragma omp for
        for (int j = 0; j < N; j++) {
            // What happens here is shared among threads so,
            // according to the scheduling you choose, each thread
            // will execute a particular portion of your N iterations
        } // IMPLICIT BARRIER             
  }
}

隱式屏障是線程彼此等待的同步點。 因此,作為拇指的一般規則,因此優選並行化外部循環而不是內部循環 ,因為這將為iterations*N次迭代(而不是您在上面創建的iterations點)創建單個同步點。

我不確定我能回答你的問題。 我現在只使用OpenMP幾個月,但是當我嘗試回答這樣的問題時,我會做一些你好的世界printf測試,如下所示。 我認為這可能有助於回答您的問題。 也可以嘗試#pragma omp for nowait ,看看會發生什么。

只要確保當你“//做某事並做其他事情”而你沒有寫入同一個內存地址並創建競爭條件時。 此外,如果您正在進行大量的閱讀和寫作,則需要考慮如何有效地使用緩存。

#include "stdio.h"
#include <omp.h>
void loop(const int iterations, const int N) {
    #pragma omp parallel
    {
        int start_thread = omp_get_thread_num();
        printf("start thread %d\n", start_thread);
        for (int i = 0; i < iterations; i++) {
            printf("\titeration %d, thread num %d\n", i, omp_get_thread_num());
            #pragma omp for
            for (int j = 0; j < N; j++) {
                printf("\t\t inner loop %d, thread num %d\n", j, omp_get_thread_num());
            }
        }
    }
}

int main() {
    loop(2,30);
}

在性能方面,您可能需要考慮融合您的循環。

#pragma omp for
for(int n=0; n<iterations*N; n++) {
    int i = n/N;
    int j = n%N;    
    //do something as function of index i and j
}

很難回答,因為它實際上取決於代碼中的依賴關系。 但解決這個問題的一般方法是反轉循環的嵌套,如下所示:

#pragma omp parallel
{
    #pragma omp for
    for (int j = 0; j < N; j++) {
        for (int i = 0; i < iterations; i++) {
            // Do something
        }
    }
}

當然,這可能是也可能是不可能的,這取決於你在循環中的代碼是什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM