节和任务 openmp 的区别 [英] Difference between section and task openmp

查看:19
本文介绍了节和任务 openmp 的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

OpenMP 之间有什么区别:

What is the difference in OpenMP between :

#pragma omp parallel sections
{
    #pragma omp section
    {
       fct1();
    }
    #pragma omp section
    {
       fct2();
    }
}

和:

#pragma omp parallel 
{
    #pragma omp single
    {
       #pragma omp task
       fct1();
       #pragma omp task
       fct2();
    }
}

我不确定第二个代码是否正确...

I'm not sure that the second code is correct...

推荐答案

任务和节之间的区别在于代码将执行的时间范围.节被包含在 sections 结构中,并且(除非指定了 nowait 子句)线程在所有节都执行完之前不会离开它:

The difference between tasks and sections is in the time frame in which the code will execute. Sections are enclosed within the sections construct and (unless the nowait clause was specified) threads will not leave it until all sections have been executed:

                 [    sections     ]
Thread 0: -------< section 1 >---->*------
Thread 1: -------< section 2      >*------
Thread 2: ------------------------>*------
...                                *
Thread N-1: ---------------------->*------

这里N 个线程遇到一个sections 结构,它有两个部分,第二个比第一个花费更多的时间.前两个线程各执行一个部分.其他 N-2 线程只是在部分构造末尾的隐式屏障处等待(此处显示为 *).

Here N threads encounter a sections construct with two sections, the second taking more time than the first. The first two threads execute one section each. The other N-2 threads simply wait at the implicit barrier at the end of the sections construct (show here as *).

只要有可能,任务就会在所谓的任务调度点排队并执行.在某些情况下,可以允许运行时在线程之间移动任务,即使是在它们生命周期的中期.此类任务称为解绑任务,解绑任务可能会在一个线程中开始执行,然后在某个调度点可能会被运行时迁移到另一个线程.

Tasks are queued and executed whenever possible at the so-called task scheduling points. Under some conditions, the runtime could be allowed to move task between threads, even in the mid of their lifetime. Such tasks are called untied and an untied task might start executing in one thread, then at some scheduling point it might be migrated by the runtime to another thread.

不过,任务和部分在很多方面都相似.例如,以下两个代码片段实现了基本相同的结果:

Still, tasks and sections are in many ways similar. For example, the following two code fragments achieve essentially the same result:

// sections
...
#pragma omp sections
{
   #pragma omp section
   foo();
   #pragma omp section
   bar();
}
...

// tasks
...
#pragma omp single nowait
{
   #pragma omp task
   foo();
   #pragma omp task
   bar();
}
#pragma omp taskwait
...

taskwait 的工作方式与 barrier 非常相似,但对于任务 - 它确保当前的执行流程将暂停,直到所有排队的任务都执行完毕.它是一个调度点,即它允许线程处理任务.single 结构是必需的,这样任务将只由一个线程创建.如果没有 single 构造,每个任务将被创建 num_threads 次,这可能不是人们想要的.single 构造中的 nowait 子句指示其他线程不要等到 single 构造被执行(即移除末尾的隐式障碍)single 结构).所以他们立即点击taskwait并开始处理任务.

taskwait works very like barrier but for tasks - it ensures that current execution flow will get paused until all queued tasks have been executed. It is a scheduling point, i.e. it allows threads to process tasks. The single construct is needed so that tasks will be created by one thread only. If there was no single construct, each task would get created num_threads times, which might not be what one wants. The nowait clause in the single construct instructs the other threads to not wait until the single construct was executed (i.e. removes the implicit barrier at the end of the single construct). So they hit the taskwait immediately and start processing tasks.

taskwait 是一个显式的调度点,此处显示为清晰起见.还有隐式调度点,最显着的是在屏障同步内部,无论是显式还是隐式.因此,上面的代码也可以简单地写成:

taskwait is an explicit scheduling point shown here for clarity. There are also implicit scheduling points, most notably inside the barrier synchronisation, no matter if explicit or implicit. Therefore, the above code could also be written simply as:

// tasks
...
#pragma omp single
{
   #pragma omp task
   foo();
   #pragma omp task
   bar();
}
...

如果存在三个线程,可能会发生以下情况的一种可能情况:

Here is one possible scenario of what might happen if there are three threads:

               +--+-->[ task queue ]--+
               |  |                   |
               |  |       +-----------+
               |  |       |
Thread 0: --< single >-|  v  |-----
Thread 1: -------->|< foo() >|-----
Thread 2: -------->|< bar() >|-----

在<代码>中显示在这里|... | 是调度点的动作(taskwait 指令或隐式屏障).基本上线程 12 暂停他们正在做的事情并开始处理队列中的任务.处理完所有任务后,线程将恢复其正常执行流程.请注意,线程 12 可能会在线程 0 退出 single 构造之前到达调度点,因此左 | 不需要对齐(这在上图中表示).

Show here within the | ... | is the action of the scheduling point (either the taskwait directive or the implicit barrier). Basically thread 1 and 2 suspend what they are doing at that point and start processing tasks from the queue. Once all tasks have been processed, threads resume their normal execution flow. Note that threads 1 and 2 might reach the scheduling point before thread 0 has exited the single construct, so the left |s need not necessary be aligned (this is represented on the diagram above).

也可能发生线程 1 能够完成处理 foo() 任务并在其他线程能够请求任务之前请求另一个任务.所以 foo()bar() 可能会被同一个线程执行:

It might also happen that thread 1 is able to finish processing the foo() task and request another one even before the other threads are able to request tasks. So both foo() and bar() might get executed by the same thread:

               +--+-->[ task queue ]--+
               |  |                   |
               |  |      +------------+
               |  |      |
Thread 0: --< single >-| v             |---
Thread 1: --------->|< foo() >< bar() >|---
Thread 2: --------------------->|      |---

如果线程 2 来得太晚,被挑出的线程也有可能执行第二个任务:

It is also possible that the singled out thread might execute the second task if thread 2 comes too late:

               +--+-->[ task queue ]--+
               |  |                   |
               |  |      +------------+
               |  |      |
Thread 0: --< single >-| v < bar() >|---
Thread 1: --------->|< foo() >      |---
Thread 2: ----------------->|       |---

在某些情况下,编译器或 OpenMP 运行时甚至可能完全绕过任务队列并串行执行任务:

In some cases the compiler or the OpenMP runtime might even bypass the task queue completely and execute the tasks serially:

Thread 0: --< single: foo(); bar() >*---
Thread 1: ------------------------->*---
Thread 2: ------------------------->*---

如果区域代码中不存在任务调度点,OpenMP 运行时可能会在它认为合适的时候启动任务.例如,所有任务都可能被推迟,直到到达 parallel 区域末尾的障碍.

If no task scheduling points are present inside the region's code, the OpenMP runtime might start the tasks whenever it deems appropriate. For example it is possible that all tasks are deferred until the barrier at the end of the parallel region is reached.

这篇关于节和任务 openmp 的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆