2012-09-19 65 views
5

我正在使用openMP并行地运行我的模拟实例。如何强制openMP按特定顺序运行迭代

#pragma omp parallel for private(part) shared(P,lfcc,temp) 
for (part = 0; part < P->Parts; part++) 

部分循环检查如果与索引号“份”已经存在(这样我就可以运行该仿真“份”的某一值,后来增加它不覆盖现有结果)输出文件。但是,这需要迭代按顺序运行。也就是说,对于n个线程,它应该首先同时运行部分(1) - (n),然后是部分(n + 1) - (2n),依此类推。运行第一部分(0),(N/3),(2N/3),然后是(1),((1),(2)), N/3 + 1),(2N/3 + 1)等。

现在假设我想要30个零件都已完成。然后,我决定我需要更多的零件,并将“零件”更改为45.然后第一个线程获取零件(1) - (15),第二个(16) - (30)和第三个(31-45)。前两个线程很快就会发现所有已分配的部分已经完成,并且会让最后一个线程独立工作(如果我在程序终止前放置了一个障碍子句)。

一个简单的解决方案是让“零件”变量不以0开始,而是以m + 1开始,其中m是先前完成零件的数量。但是我想知道是否有可能强制openMP以上面粗体显示的顺序运行迭代。

+1

有可能不是除了抛出外环在该遍历所有连续块并行区域更好的办法。 – Mysticial

+0

所以你想要块分区?就像我想用4个线程处理40个项目一样,它们将分别工作在0..9,10..19,20..29和30..39之间? – Tudor

+0

都铎王朝,我需要另一种方式。用4线程做1-4,5-8,9-12 ... –

回答

7

您可以将每个线程的迭代块的大小更改为schedule子句中的1,例如, schedule(static,1)。有了3个线程,第一个线程将处理迭代0,3,6,9等,第二个线程将处理迭代1,4,7,10等,第三个线程将处理迭代2,5,8, 11等。您仍然需要在循环中的某处进行同步,因为不能保证线程将同时以相同的速度执行所有步骤(您可以在每次迭代结束时将屏障放到下一个迭代块开始之前同步)。

另一种解决方案是使用OpenMP任务构造。有了它,你可以在一个线程中运行一个大循环,生成计算任务。你可以把检查此循环中的输出文件的存在,并创建仅在需要新的任务(例如输出文件不存在):

#pragma omp parallel 
{ 
    ... 
    #pragma omp single 
    for (part = 0; part < P->Parts; part++) 
    { 
     if (!output_file_exists(part)) 
      #pragma omp task 
      { 
       ... computation for that part ... 
      } 
    } 
    #pragma omp taskwait 
    ... 
} 

希望我理解正确的问题。

+0

这是一个很好的解决方案。我会尝试,或尝试尝试:) –

0

如果我们想要OpenMP线程执行,我们必须使用ordered子句。但是,我们必须小心。下面将打印i的(和线程ID的)(从0i19,从0omp_get_num_threads() - 1 TID)依次为:

#pragma omp parallel 
    #pragma omp for ordered 
     for (i = 0; i < 20; i++) 
      #pragma omp ordered 
       printf("i=%d - tid=%d\n", i, omp_get_thread_num()); 

输出(在我的8核心英特尔x86_64的机器):

i=0 - tid=0 
i=1 - tid=0 
i=2 - tid=0 
i=3 - tid=1 
i=4 - tid=1 
i=5 - tid=1 
i=6 - tid=2 
i=7 - tid=2 
i=8 - tid=2 
i=9 - tid=3 
i=10 - tid=3 
i=11 - tid=3 
i=12 - tid=4 
i=13 - tid=4 
i=14 - tid=5 
i=15 - tid=5 
i=16 - tid=6 
i=17 - tid=6 
i=18 - tid=7 
i=19 - tid=7 

但注意:

#pragma omp parallel 
    #pragma omp for ordered 
     for (i = 0; i < 20; i++) 
     { 
      // the threads enter this for() section in order but won't 
      // print this statement in order! 
      printf("other i=%d - tid=%d\n", i, omp_get_thread_num()); 
      #pragma omp ordered 
       // these are printed in order 
       printf("i=%d - tid=%d\n", i, omp_get_thread_num()); 
     } 

输出:

other i=16 - tid=6 
other i=18 - tid=7 
other i=12 - tid=4 
other i=0 - tid=0 
i=0 - tid=0 
other i=1 - tid=0 
i=1 - tid=0 
other i=2 - tid=0 
i=2 - tid=0 
other i=3 - tid=1 
other i=6 - tid=2 
other i=14 - tid=5 
i=3 - tid=1 
other i=4 - tid=1 
i=4 - tid=1 
other i=5 - tid=1 
i=5 - tid=1 
i=6 - tid=2 
other i=7 - tid=2 
i=7 - tid=2 
other i=8 - tid=2 
i=8 - tid=2 
other i=9 - tid=3 
i=9 - tid=3 
other i=10 - tid=3 
i=10 - tid=3 
other i=11 - tid=3 
i=11 - tid=3 
i=12 - tid=4 
other i=13 - tid=4 
i=13 - tid=4 
i=14 - tid=5 
other i=15 - tid=5 
i=15 - tid=5 
i=16 - tid=6 
other i=17 - tid=6 
i=17 - tid=6 
i=18 - tid=7 
other i=19 - tid=7 
i=19 - tid=7 

最后要注意的是这个数组是按顺序填充的(我之后在从主线程串行打印以确认它时检查它)。

// threads filling up array 
    int Arr[20] = {0}; 
#pragma omp parallel for ordered 
    for (i = 0; i < 20; i++) 
     Arr[i] = i; 

    printf("\n\n"); 
    // lets check to see if threads have put values to the array in order 
    for (i = 0; i < 20; i++) 
     printf("Arr[%d]=%d\n", i, Arr[i]); 

输出:

A[0]=0 
A[1]=1 
A[2]=2 
A[3]=3 
A[4]=4 
A[5]=5 
A[6]=6 
A[7]=7 
A[8]=8 
A[9]=9 
A[10]=10 
A[11]=11 
A[12]=12 
A[13]=13 
A[14]=14 
A[15]=15 
A[16]=16 
A[17]=17 
A[18]=18 
A[19]=19 
相关问题