如何在同一时间启动具有不同线程功能的两个线程组?
问题描述:
我有两组线程,一组由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个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映射,有一个很短的解决方案:
#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);
}
只要有是一些让你指定许多事情的结构,并且它们在同一时间完成了它们,你可以使用某种并行循环。 –
这将严重依赖于您的操作系统正在使用的调度程序的时间片等事情,以及您是否正在使用多个内核以及许多您可能不想处理的内容。你应该问这个问题,你为什么要这样做? –