Freigeben über


Gewusst wie: Konvertieren einer OpenMP-Schleife, in der die Ausnahmebehandlung verwendet wird, zur Verwendung der Concurrency Runtime

In diesem Beispiel wird veranschaulicht, wie Eine OpenMP-Parallele für Schleife konvertiert wird, die eine Ausnahmebehandlung durchführt, um den Ausnahmebehandlungsmechanismus für Parallelitäts-Runtime zu verwenden.

In OpenMP müssen Ausnahmen in einem parallelen Bereich im gleichen Bereich und vom gleichen Thread abgefangen und behandelt werden. Eine Ausnahme, die den parallelen Bereich umgeht, wird vom Handler für nicht behandelte Ausnahmen abgefangen, der den Prozess standardmäßig beendet.

Wenn Sie in der Parallelitätslaufzeit eine Ausnahme im Textkörper einer Arbeitsfunktion auslösen, die Sie an eine Aufgabengruppe übergeben, z. B. eine Parallelität::task_group oder ein Parallelitätsobjekt::structured_task_group-Objekt oder einen parallelen Algorithmus wie "concurrency::p arallel_for", speichert die Laufzeit diese Ausnahme und marshallt sie in den Kontext, der auf den Abschluss der Aufgabengruppe oder des Algorithmus wartet. Für Aufgabengruppen ist der Wartekontext der Kontext, in dem "concurrency::task_group::wait", "concurrency::structured_task_group::wait", "concurrency::task_group::run_and_wait" oder "concurrency::structured_task_group::run_and_wait" aufgerufen werden. Der Wartekontext eines parallelen Algorithmus ist der Kontext, von dem dieser Algorithmus aufgerufen wurde. Darüber hinaus werden von der Runtime auch alle aktiven Aufgaben in der Aufgabengruppe (sowie alle aktiven Aufgaben in untergeordneten Aufgabengruppen) beendet sowie alle noch nicht gestarteten Aufgaben verworfen.

Beispiel

In diesem Beispiel wird veranschaulicht, wie Ausnahmen in einem OpenMP parallel-Bereich und in einem Aufruf von parallel_for behandelt werden. Die do_work Funktion führt eine Speicherzuweisungsanforderung aus, die nicht erfolgreich ist, und löst daher eine Ausnahme vom Typ "std::bad_alloc" aus. In der Version, die OpenMP verwendet, muss diese vom Thread, der diese Ausnahme auslöst, ebenfalls abgefangen werden. Mit anderen Worten muss die Ausnahme von jeder Iteration einer parallelen OpenMP-Schleife behandelt werden. In der Version mit der Concurrency Runtime wird eine Ausnahme, die von einem anderen Thread ausgelöst wird, vom Hauptthread abgefangen.

// concrt-omp-exceptions.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <new>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

// Demonstrates a function that performs a memory allocation request 
// that does not succeed.
void do_work(int)
{
   // The following memory allocation causes this function to 
   // throw std::bad_alloc.
   char* ptr = new char[(~unsigned int((int)0)/2) - 1];

   // TODO: Assuming that the allocation succeeds, perform some work 
   // and free the allocated memory.

   delete[] ptr;
}

// Demonstrates an OpenMP parallel loop that performs exception handling.
void omp_exception_handling()
{
   #pragma omp parallel for 
      for(int i = 0; i < 10; i++) 
      {
         try {
            // Perform a unit of work.
            do_work(i);
         }
         catch (exception const& e) {
            // Print the error to the console.
            wstringstream ss;
            ss << L"An error of type '" << typeid(e).name() 
               << L"' occurred." << endl;
            wcout << ss.str();
         }
      }
}

// Demonstrates an Concurrency Runtime parallel loop that performs exception handling.
void concrt_exception_handling()
{
   try {
      parallel_for(0, 10, [](int i) 
      {
         // Perform a unit of work.
         do_work(i);
      });
   }
   catch (exception const& e) {
      // Print the error to the console.
      wcout << L"An error of type '" << typeid(e).name() 
            << L"' occurred." << endl;
   }
}

int wmain()
{
   wcout << L"Using OpenMP..." << endl;
   omp_exception_handling();

   wcout << L"Using the Concurrency Runtime..." << endl;
   concrt_exception_handling();
}

Folgende Ergebnisse werden zurückgegeben:

Using OpenMP...
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
An error of type 'class std::bad_alloc' occurred.
Using the Concurrency Runtime...
An error of type 'class std::bad_alloc' occurred.

In der Version in diesem Beispiel mit OpenMP tritt die Ausnahme in der jeweiligen Schleifeniteration auf und wird dort auch behandelt. In der Version mit der Concurrency Runtime wird die Ausnahme von der Laufzeit gespeichert, alle aktiven Aufgaben werden beendet, noch nicht gestartete Aufgaben werden verworfen, und die Ausnahme, die parallel_for aufruft, wird an den Kontext gemarshallt.

Wenn Sie möchten, dass die Version mit OpenMP nach dem Auftreten der Ausnahme beendet wird, können Sie ein boolesche Flag verwenden, um den Fehler gegenüber anderen Schleifeniterationen anzuzeigen. Wie im Beispiel im Thema How to: Convert an OpenMP Loop that Uses Cancellation to Use the Concurrency Runtime, subsequent loop iterations would nothing if the flag is set. Umgekehrt können Sie die Ausnahme, wenn die Schleife mit der Concurrency Runtime nach dem Auftreten der Ausnahme fortgesetzt werden soll, im Text der parallelen Schleife selbst behandeln.

Andere Komponenten der Concurrency Runtime, wie asynchrone Agents und einfache Aufgaben, transportieren keine Ausnahmen. Stattdessen werden unbehandelte Ausnahmen vom Handler für nicht behandelte Ausnahmen abgefangen, der den Prozess standardmäßig beendet. Weitere Informationen zur Ausnahmebehandlung finden Sie unter "Ausnahmebehandlung".

Weitere Informationen zu parallel_for und anderen parallelen Algorithmen finden Sie unter Parallel-Algorithmen.

Kompilieren des Codes

Kopieren Sie den Beispielcode, fügen Sie ihn in ein Visual Studio-Projekt ein, oder fügen Sie ihn in eine Datei ein, die benannt concrt-omp-exceptions.cpp ist, und führen Sie dann den folgenden Befehl in einem Visual Studio-Eingabeaufforderungsfenster aus.

cl.exe /EHsc /openmp concrt-omp-exceptions.cpp

Siehe auch

Migrieren von OpenMP zur Concurrency Runtime
Ausnahmebehandlung
Parallele Algorithmen