0

我正在阅读有关 OpenMP 的信息,这听起来很棒。我来到了作者声明 #pragma omp parallel可用于创建新线程团队的地方。所以我想知道 #pragma omp parallel这里的区别是什么意思。我读到 #pragma omp for使用当前的线程团队来处理 for 循环。所以我有两个例子

第一个简单的例子:

 #pragma omp for
 for(int n=0; n<10; ++n)
 {
   printf(" %d", n);
 }
 printf(".\n");

第二个例子

 #pragma omp parallel
 {
  #pragma omp for
  for(int n=0; n<10; ++n) printf(" %d", n);
 }
 printf(".\n");

我的问题是那些线程是每次或一次在应用程序启动时动态创建的,以及我何时或为什么要创建更多线程团队?

4

3 回答 3

4

你的第一个例子不会这样编译。“#pragma omp for”建议编译器在您必须首先创建的线程组内分配以下循环的工作负载。当您在第二个示例中使用它时,使用“#pragma omp parallel”语句创建了一组线程。您可以使用“#pragma omp parallel for”组合“omp parallel”和“omp for”指令。线程组在并行语句之后创建,并且在此块内有效。

于 2013-06-28T08:11:17.493 回答
1

TL;DR:唯一的区别是第一个代码调用了两个隐式障碍,而第二个代码只调用了一个。


使用现代官方 OpenMP 5.1 标准作为参考的更详细的答案。

#pragma omp parallel

将创建一个parallel region包含 的团队threads,其中每个线程将执行包含的整个代码块parallel region

OpenMP 5.1可以阅读更正式的描述:

当线程遇到并行构造时,会创建一组线程来执行并行区域 (..)。遇到并行构造的线程成为新团队的主线程,在新并行区域的持续时间内线程数为零。新团队中的所有线程,包括主线程,都执行该区域。创建团队后,团队中的线程数在该并行区域的持续时间内保持不变。

这:

#pragma omp parallel for

将创建一个parallel region(如前所述),并且threads该区域的 将使用 分配它所包含的循环的迭代default chunk size,并且通常default schedule是。但是请记住,标准的不同具体实施可能会有所不同。 staticdefault scheduleOpenMP

OpenMP 5.1您可以阅读更正式的描述:

工作共享循环结构指定一个或多个相关循环的迭代将由团队中的线程在其隐式任务的上下文中并行执行。迭代分布在执行工作共享循环区域绑定到的并行区域的团队中已经存在的线程中

此外

并行循环构造是指定并行构造的快捷方式,该并行构造包含具有一个或多个关联循环且没有其他语句的循环构造。

或非正式地,#pragma omp parallel for是构造函数#pragma omp parallel#pragma omp for.

您使用 achunk_size=1static schedule的两个版本都会产生类似的结果:

在此处输入图像描述

在代码方面,循环将被转换为逻辑上类似于:

for(int i=omp_get_thread_num(); i < n; i+=omp_get_num_threads())
{  
    //...
}

其中omp_get_thread_num()

omp_get_thread_num 例程返回当前团队中调用线程的线程号。

omp_get_num_threads()

返回当前团队中的线程数。在程序的连续部分中,omp_get_num_threads 返回 1。

或者换句话说,for(int i = THREAD_ID; i < n; i += TOTAL_THREADS)THREAD_ID范围从0TOTAL_THREADS - 1,表示在TOTAL_THREADS并行区域上创建的团队的线程总数。

于 2021-07-05T12:27:11.577 回答
0

À“并行”区域可以包含多个简单的“for”循环。在您的程序第一次遇到“并行”时,将创建开放式 MP 线程团队,之后,每个开放式 mp 构造都会将这些线程重用于循环、部分、任务等......

于 2013-06-24T07:02:07.183 回答