【问题标题】:How do I start two thread teams with different thread functions at the same time?如何同时启动两个具有不同线程功能的线程组?
【发布时间】:2017-10-19 21:25:54
【问题描述】:

我有两组线程,一组由n个线程执行,另一组由m个线程执行。我想同时启动它们,但我得到的是,第 1 组首先启动,然后是第 2 组。

//group 1   
#pragma omp parallel num_threads(n)
{
    #pragma omp for
    for (int i = 0; i < n; i++) {
        function1(i);
    }
}
//group 2   
#pragma omp parallel num_threads(m)
{
    #pragma omp for
    for (int i = 0; i < m; i++) {
        function2(i);
    }
}

我得到的输出是:

function1 is called
function1 is called
function1 is called
...
n
function2 is called
...
m

我期望的输出(只是一个随机的例子):

function2 is called
function2 is called
function1 is called
function2 is called
function1 is called
...

【问题讨论】:

  • 如果有某种结构可以让您指定要执行的许多事情并且同时完成所有这些事情,那么您可以使用某种并行循环。
  • 这将在很大程度上取决于您的操作系统正在使用的调度程序的时间片,以及您是否使用多个内核以及许多您可能不想处理的事情。你应该问这个问题,你为什么要它这样做?

标签: c++ multithreading openmp


【解决方案1】:

在您的示例中,您遇到的行为正是人们所期望的,因为 2 个parallel 区域是一个接一个地按顺序创建的。

如果您想坚持使用parallel for 构造的方法,则需要将它们封装到另一个parallel 构造中,并允许嵌套并行。例如:

#include <stdio.h>
#include <omp.h>
#include <unistd.h>

void function1( int i ) {
    printf( "Function1( %d )\n", i );
    usleep( ( i * 1237 + 8765 ) % 9797 );
}

void function2( int i ) {
    printf( "Function2( %d )\n", i );
    usleep( ( i * 7321 + 5678 ) % 10903 );
}

int main() {

    int n = 10, m = 5;
    omp_set_nested( 1 );

    #pragma omp parallel sections num_threads( 2 )
    {
        #pragma omp section
        #pragma omp parallel for num_threads( n )
        for ( int i = 0; i < n; i++ )
            function1( i );
        #pragma omp section
        #pragma omp parallel for num_threads( m )
        for ( int i = 0; i < m; i++ )
            function2( i );
    }

    return 0;
}

注意:我在函数调用中添加了一些伪随机等待,以允许延迟返回,否则,看到损坏输出的可能性非常小。

在我的四核机器上,这给了我(例如):

~/tmp$ gcc -fopenmp pools.c
~/tmp$ ./a.out 
Function2( 2 )
Function1( 5 )
Function1( 1 )
Function2( 1 )
Function2( 0 )
Function1( 0 )
Function1( 3 )
Function1( 4 )
Function1( 6 )
Function1( 9 )
Function1( 7 )
Function2( 4 )
Function1( 2 )
Function1( 8 )
Function2( 3 )

所以这回答了您的直接问题,但我觉得最初的方法可能不是最合适的方法。您应该明确考虑查看 task 构造,因为它可能更适合您想要实现的目标。

【讨论】:

    【解决方案2】:

    Gilles 的回答很好,但我想提出一些额外的想法:

    由于您有从线程到函数的 1 对 1 映射,因此有一个非常简短的解决方案:

    #pragma omp parallel number_threads(n + m)
    {
      assert(omp_get_num_threads() == n + m);
      auto me = omp_get_thread_num();
      if (me < n) function1(me);
      else function2(me - n);
    }
    

    但是 - 无论如何我建议谨慎。线程数多于内核数(超额订阅)在性能方面可能非常危险,并且宁愿将线程数的选择留给 OpenMP,并且仍然有一个简单的解决方案,无需嵌套:

    #pragma omp parallel for
    for (int nm = 0; nm < n + m; nm++) {
      if (nm < n) function1(nm);
      else function2(nm - n);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-03-23
      • 2017-01-02
      • 2023-03-06
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 2018-03-10
      • 2017-08-27
      • 1970-01-01
      相关资源
      最近更新 更多