c++ - 为函数创建 openmp 线程

标签 c++ c++11 pthreads openmp

我看到的所有 openmp 教程示例都是为 for 循环创建线程。但是我需要为可能聚集到函数中的普通语句组创建线程。例如,类似于以下内容:

#include <stdio.h>
#include <omp.h>
int A() { printf("in A:%d\n", omp_get_thread_num()); }
int B() { printf("in B:%d\n", omp_get_thread_num()); }
int D() { printf("in D:%d\n", omp_get_thread_num()); }
int E() { printf("in E:%d\n", omp_get_thread_num()); }
int F() { printf("in F:%d\n", omp_get_thread_num()); }
int G() { printf("in G:%d\n", omp_get_thread_num()); }
int H() { printf("in H:%d\n", omp_get_thread_num()); }
int C() {
    printf("in C:%d\n", omp_get_thread_num());
    #pragma omp parallel num_threads(2)
    {
        D(); // want to execute D,E in separate threads
        E();
    }
    F();
}
main() {
    omp_set_nested(1);
    printf("in main:%d\n", omp_get_thread_num());
    G();
    #pragma omp parallel num_threads(3)
    {
        A(); // want to execute A,B,C in separate threads
        B();
        C();
    }
    H();
}

在上面的代码中,我希望每个函数只执行一次,但在不同的线程中。 (所以我在上面的代码中使用指令可能是错误的,请根据需要进行更正。)

如何使用 openmp 编写这种函数的嵌套并行性?这些函数是否会共享所有可用的全局变量,或者是否有一种方法可以指定哪些变量将由哪些函数共享?

编辑: 在阅读了 Jorge Bellon 的回答后,我编写了以下代码,其输出显示在代码之后。看起来 thread-0 被用于许多功能,这不是我想要的 - 我希望这些功能并行执行。另外,我只想为 G 执行一次,所以看起来我必须删除“num_threads(3)”行。让我知道这个问题的解决方法是什么。

// compile this with: g++ -fopenmp
int A() { printf("in H:%d\n", omp_get_thread_num()); sleep(1); }
// similarly for B, D, E, F, G, H
int C() {
    printf("in C:%d\n", omp_get_thread_num()); sleep(1);
    #pragma omp task
    D();
    #pragma omp task
    E();
    #pragma omp taskwait
    F(); sleep(1);
}
main() {
    omp_set_nested(1);
    printf("in main:%d\n", omp_get_thread_num());
    #pragma omp parallel num_threads(3)
    G();
    #pragma omp task
    A();
    #pragma omp task
    B();
    #pragma omp task
    C();
    #pragma omp taskwait
    H();
}
// outputs:
in main:0
in G:1
in G:0
in G:2
in A:0
in B:0
in C:0
in D:0
in E:0
in F:0
in H:0

最佳答案

并行化此类代码的最佳方法是使用 OpenMP task 结构。您的并行区域将创建一个线程池,一个主线程将创建外部任务,其余线程将在这些任务可用时立即处理它们。

// [...]

int C() {
  // You can create tasks within tasks
  // In this example is better to place {D,E} and {E} in tasks
  // and omit the task construct of C function call
  #pragma omp task
  {
    D();
    E();
  }
  // if F() needs D and E to finish, a taskwait is necessary
  F();
}

main() {
  // omp_set_nested no longer necessary
  printf("in main:%d\n", omp_get_thread_num());
  G();
  #pragma omp parallel num_threads(3)
  #pragma omp single
  {
    // a single thread creates the tasks
    // other threads in the team will be able to execute them
    // want to execute A,B,C in separate threads
    #pragma omp task
    A();
    #pragma omp task
    B();
    #pragma omp task
    C();
    // wait until all the tasks have been finished
    #pragma omp taskwait
  }
  H();
}

每个函数是否在不同的线程中执行,完全取决于程序在运行时的状态。这意味着如果所有其他线程都忙,一些任务可能会在同一个线程中执行,这并不是什么大问题。

您可以使用 task dependences (从 OpenMP 4 开始)控制是否允许任务在创建时继续执行。

关于c++ - 为函数创建 openmp 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46069034/

相关文章:

c++ - 如何读取=从文件中分离数据

c++ - 自旋锁是否保证获取顺序?

c++ - c++11 中指针的 'auto' 类型赋值是否需要 '*' ?

c++ - 在 GDB 中调试多线程服务器 - 查找每个线程的状态。执行时计数并停止

c - 将 argc 和 argv 传递给 c 中的线程

c++ - Autotools 提示使用不同上下文编译的文件

c++ - 优化 Microsoft Visual Studio 编译器生成的程序集

c++ - for 循环需要运行 LLONG_MAX 次,但计数器变量也需要表示有符号数。你用什么类型的柜台?

C++11 unordered_set with std::owner_less-like hashing

c++ - 非等待 cond_t 变量上的 pthread_cond_signal