我有两组线程,一组由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
...
答案 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);
}