如何同时启动具有不同线程功能的两个线程组?

时间:2017-10-19 21:25:54

标签: c++ multithreading openmp

我有两组线程,一组由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
...

2 个答案:

答案 0 :(得分:2)

在您的示例中,您遇到的行为正是人们所期望的,因为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构造,因为它可能更适合您想要实现的目标。

答案 1 :(得分:1)

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

由于您有从线程到函数的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);
}