Unterschied zwischen Abschnitt und Aufgabe openmp

Lesezeit: 11 Minuten

Benutzeravatar von Arkerone
Arkerone

Was ist der Unterschied in OpenMP zwischen:

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

und :

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

Ich bin mir nicht sicher, ob der zweite Code richtig ist …

  • Außer vermisst ; Am Ende beider Anweisungen ist der zweite Code korrekt.

    – Christo Iljew

    9. Dezember 2012 um 16:09 Uhr

Benutzeravatar von Hristo Iliev
Christo Iljew

Der Unterschied zwischen Aufgaben und Abschnitten liegt im Zeitrahmen, in dem der Code ausgeführt wird. Abschnitte sind innerhalb der eingeschlossen sections konstruieren und (es sei denn, die nowait -Klausel angegeben wurde) werden Threads sie nicht verlassen, bis alle Abschnitte ausgeführt wurden:

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

Hier N Threads begegnen a sections Konstruieren Sie mit zwei Abschnitten, wobei der zweite mehr Zeit in Anspruch nimmt als der erste. Die ersten beiden Threads führen jeweils einen Abschnitt aus. Das andere N-2 Threads warten einfach an der impliziten Barriere am Ende des Abschnittskonstrukts (hier als *).

Aufgaben werden wann immer möglich an den sogenannten Aufgabenplanungspunkten in die Warteschlange gestellt und ausgeführt. Unter bestimmten Bedingungen kann es der Laufzeit erlaubt sein, Tasks zwischen Threads zu verschieben, sogar mitten in ihrer Lebensdauer. Solche Aufgaben werden als ungebunden bezeichnet, und eine ungebundene Aufgabe kann mit der Ausführung in einem Thread beginnen und dann an einem Planungspunkt von der Laufzeit zu einem anderen Thread migriert werden.

Dennoch sind Aufgaben und Abschnitte in vielerlei Hinsicht ähnlich. Beispielsweise erzielen die folgenden beiden Codefragmente im Wesentlichen dasselbe Ergebnis:

// 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 funktioniert sehr gerne barrier aber für Aufgaben – es stellt sicher, dass der aktuelle Ausführungsfluss angehalten wird, bis alle Aufgaben in der Warteschlange ausgeführt wurden. Es ist ein Scheduling Point, dh es ermöglicht Threads, Aufgaben zu bearbeiten. Das single construct wird benötigt, damit Tasks nur von einem Thread erstellt werden. Wenn es keine gäbe single konstruieren, würde jede Aufgabe erstellt werden num_threads Zeiten, die vielleicht nicht das sind, was man will. Das nowait Klausel in der single Konstrukt weist die anderen Threads an, nicht bis zum zu warten single Konstrukt ausgeführt wurde (dh entfernt die implizite Barriere am Ende der single konstruieren). Also schlugen sie zu taskwait sofort und beginnen Sie mit der Bearbeitung von Aufgaben.

taskwait ist ein expliziter Planungspunkt, der hier zur Verdeutlichung gezeigt wird. Es gibt auch implizite Planungspunkte, insbesondere innerhalb der Barrierensynchronisation, egal ob explizit oder implizit. Daher könnte der obige Code auch einfach geschrieben werden als:

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

Hier ist ein mögliches Szenario, was passieren könnte, wenn es drei Threads gibt:

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

Zeigen Sie hier innerhalb der | ... | ist die Aktion des Planungspunkts (entweder die taskwait Richtlinie oder das implizite Hindernis). Grundsätzlich Gewinde 1 und 2 Unterbrechen Sie, was sie zu diesem Zeitpunkt tun, und beginnen Sie mit der Verarbeitung von Aufgaben aus der Warteschlange. Sobald alle Aufgaben verarbeitet wurden, nehmen Threads ihren normalen Ausführungsfluss wieder auf. Beachten Sie, dass Fäden 1 und 2 könnte den Scheduling-Punkt vor dem Thread erreichen 0 hat die verlassen single konstruieren, also links |s müssen nicht unbedingt ausgerichtet sein (dies ist im Diagramm oben dargestellt).

Es könnte auch passieren, dass Thread 1 ist in der Lage, die Verarbeitung abzuschließen foo() Aufgabe und fordern eine andere an, noch bevor die anderen Threads Aufgaben anfordern können. Also beides foo() und bar() könnte von demselben Thread ausgeführt werden:

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

Es ist auch möglich, dass der ausgewählte Thread die zweite Aufgabe ausführt, wenn Thread 2 zu spät kommt:

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

In einigen Fällen kann der Compiler oder die OpenMP-Laufzeitumgebung die Aufgabenwarteschlange sogar vollständig umgehen und die Aufgaben seriell ausführen:

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

Wenn im Code der Region keine Aufgabenplanungspunkte vorhanden sind, kann die OpenMP-Laufzeit die Aufgaben starten, wann immer sie dies für angemessen hält. Zum Beispiel ist es möglich, dass alle Aufgaben bis zur Sperre am Ende des zurückgestellt werden parallel Region erreicht ist.

  • +1, @Arkerone ja, es ist eine gute Erklärung, du solltest auch eine positive Stimme abgeben 🙂

    – Traumkrach

    9. Dezember 2012 um 22:12 Uhr

  • Gibt es einen großen Unterschied zwischen 3 aufeinanderfolgenden Singles und Abschnitten?

    – Traumkrach

    13. Februar 2013 um 22:32 Uhr

  • @HristoIliev Haben Sie eine Quelle für eine Aufgabe, die num_threads Mal erstellt wird, wenn sich ein Aufgabenpragma nicht in einem einzelnen Pragma befindet? Ich sehe in der OpenMP-Dokumentation von IBM nichts, was darauf hindeutet.

    – Chris

    26. Februar 2013 um 18:27 Uhr

  • @Chris, OpenMP 3.1-Spezifikation §2.7.1: “Wenn ein Thread auf ein Aufgabenkonstrukt trifft, wird eine Aufgabe aus dem Code für den zugehörigen strukturierten Block generiert.” Es sei denn, es gibt eine single/master’ oder ein Worksharing-Konstrukt oder Bedingungen vorhanden sind, führt jeder Thread genau denselben Code aus und daher begegnen alle Threads dem task Richtlinie.

    – Christo Iljew

    27. Februar 2013 um 8:29 Uhr

  • @JoeC, sections ist ein Konstrukt zur Arbeitsteilung, was bedeutet, dass alle Threads im Team, die einer bestimmten parallelen Region zugeordnet sind, darauf stoßen müssen, damit das Konstrukt erfolgreich ist. Wenn es nicht erwünscht ist, dass untätige Threads an der impliziten Barriere warten, wendet man die an nowait Klausel, die die implizite Barriere beseitigt.

    – Christo Iljew

    14. September 2015 um 18:11 Uhr

Benutzeravatar von Yiling Liu
Yiling Liu

Ich bin kein Experte für OpenMP, habe aber versucht, die Fib-Sequenz auf meinem Computer mit beiden zu testen task und sections

Abschnitte

int fib(int n)
{
    int i, j;
    if (n < 2)
        return n;
    else
    {
#pragma omp parallel sections       
{
#pragma omp section             
{
                i = fib(n - 1);
            }
#pragma omp section             
{
                j = fib(n - 2);
            }
        }
        printf("Current int %d is on thread %d \n", i + j, omp_get_thread_num());
        return i + j;
    }
}

int main()
{
    int n = 10;

#pragma omp parallel shared(n)  {
#pragma omp single      {
            printf("%d\n", omp_get_num_threads());
            printf("fib(%d) = %d\n", n, fib(n));
        }
    }
}

Aufgabe

#include <stdio.h>
#include <omp.h>
int fib(int n)
{
  int i, j;
  if (n<2)
    return n;
  else
    {
       #pragma omp task shared(i) firstprivate(n)
       i=fib(n-1);

       #pragma omp task shared(j) firstprivate(n)
       j=fib(n-2);

       #pragma omp taskwait
    printf("Current int %d is on thread %d \n", i + j, omp_get_thread_num());
       return i+j;
    }
}

int main()
{
  int n = 10;

  #pragma omp parallel shared(n)
  {
    #pragma omp single
    {
    printf("%d\n", omp_get_num_threads());
        printf ("fib(%d) = %d\n", n, fib(n));
    }
  }
}

Ergebnis für Abschnitte:

12
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 8 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 13 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 8 is on thread 0
Current int 21 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 8 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 13 is on thread 0
Current int 34 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 8 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 13 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 5 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 1 is on thread 0
Current int 3 is on thread 0
Current int 8 is on thread 0
Current int 21 is on thread 0
Current int 55 is on thread 4
fib(10) = 55

Ergebnis für Aufgabe:

12
Current int 1 is on thread 3
Current int 2 is on thread 3
Current int 1 is on thread 8
Current int 2 is on thread 8
Current int 1 is on thread 8
Current int 1 is on thread 4
Current int 1 is on thread 11
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 3 is on thread 11
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 1 is on thread 11
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 3 is on thread 11
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 1 is on thread 11
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 3 is on thread 11
Current int 5 is on thread 11
Current int 8 is on thread 11
Current int 1 is on thread 8
Current int 2 is on thread 8
Current int 3 is on thread 8
Current int 5 is on thread 8
Current int 13 is on thread 8
Current int 1 is on thread 7
Current int 2 is on thread 7
Current int 1 is on thread 7
Current int 1 is on thread 7
Current int 1 is on thread 0
Current int 1 is on thread 0
Current int 2 is on thread 0
Current int 3 is on thread 0
Current int 1 is on thread 1
Current int 1 is on thread 6
Current int 2 is on thread 6
Current int 1 is on thread 9
Current int 2 is on thread 9
Current int 1 is on thread 2
Current int 2 is on thread 7
Current int 3 is on thread 7
Current int 5 is on thread 7
Current int 2 is on thread 5
Current int 5 is on thread 5
Current int 1 is on thread 5
Current int 2 is on thread 5
Current int 1 is on thread 5
Current int 1 is on thread 5
Current int 2 is on thread 5
Current int 3 is on thread 5
Current int 1 is on thread 5
Current int 2 is on thread 5
Current int 1 is on thread 5
Current int 1 is on thread 5
Current int 2 is on thread 5
Current int 3 is on thread 5
Current int 5 is on thread 5
Current int 1 is on thread 5
Current int 2 is on thread 5
Current int 1 is on thread 11
Current int 2 is on thread 11
Current int 1 is on thread 8
Current int 2 is on thread 8
Current int 5 is on thread 8
Current int 3 is on thread 1
Current int 8 is on thread 1
Current int 21 is on thread 1
Current int 1 is on thread 10
Current int 3 is on thread 10
Current int 8 is on thread 0
Current int 1 is on thread 4
Current int 3 is on thread 4
Current int 1 is on thread 9
Current int 3 is on thread 9
Current int 8 is on thread 9
Current int 3 is on thread 2
Current int 5 is on thread 3
Current int 13 is on thread 3
Current int 5 is on thread 6
Current int 13 is on thread 7
Current int 8 is on thread 10
Current int 21 is on thread 10
Current int 34 is on thread 3
Current int 55 is on thread 1
fib(10) = 55

Es scheint, dass Aufgaben viel klüger sind als Abschnitte, während Rechenressourcen verteilt werden

—————————–BEARBEITEN——————– ———

Für Leute, die nach Antworten auf diese Frage suchen, lesen Sie bitte den Kommentar unter diesem Beitrag.

  • Die beiden Codebeispiele sind nicht gleichwertig. Der mit Abschnitten verwendet verschachtelte Parallelität, dh bei jedem rekursiven Aufruf wird eine neue parallele Region erstellt. Die verschachtelte Parallelität ist standardmäßig deaktiviert, sodass alles außer der obersten Rekursionsebene mit Teams aus einem Thread ausgeführt wird, weshalb Sie so viele Thread-IDs gleich 0 sehen. Selbst wenn die verschachtelte Parallelität aktiviert war, können Sie mit Tausenden von Threads enden , was wirklich ineffizient sein wird.

    – Christo Iljew

    19. Juli 2020 um 7:31 Uhr


  • @Hristo Iliev Also können wir Fibonacci berechnen, indem wir verwenden sections? Ich meine, aktivieren Sie die Parallelität während der Verwendung sections

    – Yiling Liu

    19. Juli 2020 um 9:19 Uhr


  • Nur sehr eingeschränkt. Abschnitte sind nicht dazu gedacht, rekursive Probleme zu lösen. Sie sollen den Fall unabhängiger Blöcke in der linearen Ausführung Ihres Programms lösen.

    – Christo Iljew

    19. Juli 2020 um 11:23 Uhr

  • @Hristo Iliev Verstanden

    – Yiling Liu

    19. Juli 2020 um 14:28 Uhr

1415350cookie-checkUnterschied zwischen Abschnitt und Aufgabe openmp

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy