OpenMP - 在每次循环迭代中启动一个新线程
OpenMP - Starting a new thread in each loop iteration
我很难调整自己的思维以适应OpenMP的做事方式。
粗略地说,我想要的是:
for(int i=0; i<50; i++)
{
doStuff();
thread t;
t.start(callback(i)); //each time around the loop create a thread to execute callback
}
我想我知道如何在 c++11 中做到这一点,但我需要能够使用 OpenMP 完成类似的事情。
最接近您想要的是 OpenMP 任务,可在 OpenMP v3.0 和更高版本的兼容编译器中使用。它就像:
#pragma omp parallel
{
#pragma omp single
for (int i = 0; i < 50; i++)
{
doStuff();
#pragma omp task
callback(i);
}
}
此代码将使循环仅在一个线程中执行,并将创建 50 个 OpenMP 任务,这些任务将使用不同的参数调用callback()
。然后,它将等待所有任务完成,然后再退出并行区域。任务将由要执行的空闲线程选取(可能是随机的)。OpenMP 在每个并行区域的末尾施加了一个隐式屏障,因为其分叉连接执行模型要求只有主线程在并行区域之外运行。
这是一个示例程序(ompt.cpp
):
#include <stdio.h>
#include <unistd.h>
#include <omp.h>
void callback (int i)
{
printf("[%02d] Task stated with thread %dn", i, omp_get_thread_num());
sleep(1);
printf("[%02d] Task finishedn", i);
}
int main (void)
{
#pragma omp parallel
{
#pragma omp single
for (int i = 0; i < 10; i++)
{
#pragma omp task
callback(i);
printf("Task %d createdn", i);
}
}
printf("Parallel region endedn");
return 0;
}
编译和执行:
$ g++ -fopenmp -o ompt.x ompt.cpp
$ OMP_NUM_THREADS=4 ./ompt.x
Task 0 created
Task 1 created
Task 2 created
[01] Task stated with thread 3
[02] Task stated with thread 2
Task 3 created
Task 4 created
Task 5 created
Task 6 created
Task 7 created
[00] Task stated with thread 1
Task 8 created
Task 9 created
[03] Task stated with thread 0
[01] Task finished
[02] Task finished
[05] Task stated with thread 2
[04] Task stated with thread 3
[00] Task finished
[06] Task stated with thread 1
[03] Task finished
[07] Task stated with thread 0
[05] Task finished
[08] Task stated with thread 2
[04] Task finished
[09] Task stated with thread 3
[06] Task finished
[07] Task finished
[08] Task finished
[09] Task finished
Parallel region ended
请注意,任务的执行顺序与创建顺序不同。
GCC 不支持低于 4.4 的版本中的 OpenMP 3.0。无法识别的 OpenMP 指令将被静默忽略,生成的可执行文件将以串行方式将该代码部分:
$ g++-4.3 -fopenmp -o ompt.x ompt.cpp
$ OMP_NUM_THREADS=4 ./ompt.x
[00] Task stated with thread 3
[00] Task finished
Task 0 created
[01] Task stated with thread 3
[01] Task finished
Task 1 created
[02] Task stated with thread 3
[02] Task finished
Task 2 created
[03] Task stated with thread 3
[03] Task finished
Task 3 created
[04] Task stated with thread 3
[04] Task finished
Task 4 created
[05] Task stated with thread 3
[05] Task finished
Task 5 created
[06] Task stated with thread 3
[06] Task finished
Task 6 created
[07] Task stated with thread 3
[07] Task finished
Task 7 created
[08] Task stated with thread 3
[08] Task finished
Task 8 created
[09] Task stated with thread 3
[09] Task finished
Task 9 created
Parallel region ended
看看 http://en.wikipedia.org/wiki/OpenMP。
#pragma omp for
是你的朋友。OpenMP 不需要您考虑线程。您只需声明(!)您想要并行运行的内容,OpenMP 兼容编译器就会在编译时在代码中执行所需的转换。
OpenMP的规范也非常完善。他们很好地解释了可以做什么以及如何做:http://openmp.org/wp/openmp-specifications/
您的示例可能如下所示:
#pragma omp parallel for
for(int i=0; i<50; i++)
{
doStuff();
thread t;
t.start(callback(i)); //each time around the loop create a thread to execute callback
}
for 循环中的所有内容都是并行运行的。您必须注意数据依赖性。'doStuff()' 函数在您的伪代码中按顺序运行,但在我的示例中将并行运行。您还需要指定哪些变量是线程私有的,以及类似的东西也会进入 #pragma 语句。
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 多线程:线程或进程.h - C++
- BOOST线程:线程还是进程
- 如何在线程线程内部制作内存?
- C++ - 多线程 - 线程之间的通信
- C++多线程:线程安全的内存分配
- 如何在 Linux 上强制 g++ 在协程切换线程时更新线程指针(对于 TLS)
- 如何确定流程的"经理"和"工作线程"线程的优先级(或为其设置调度策略)?
- 一旦另一个线程完成,就会生成一个新线程
- 是boost::线程线程安全的
- c++多线程-线程安全的代码
- 依靠额外的线程-线程安全
- Linux多线程——线程不会产生任何预期的输出
- 线程-线程创建问题
- 只在前一个线程完成时创建一个新线程
- 创建新线程时在lambda内部使用unique_ptr的线程安全性