Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieses Beispiel zeigt die Vorgehensweise bei der Konvertierung einer OpenMP Parallelfor-Schleife, die eine Ausnahmebehandlung durchführt, um den Ausnahmebehandlungsmechanismus der Concurrency 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 Concurrency Runtime eine Ausnahme im Hauptteil einer Arbeitsfunktion auslösen, die Sie an eine Aufgabengruppe (z. B. ein concurrency::task_group oder concurrency::structured_task_group Objekt) oder an einen parallelen Algorithmus (z. B. concurrency::parallel_for) übergeben, speichert die Runtime diese Ausnahme und leitet sie an den Kontext weiter, der auf die Beendigung der Aufgabengruppe oder des Algorithmus wartet. Bei Aufgabengruppen ist der wartende Kontext der Kontext, der concurrency::task_group::wait, concurrency::structured_task_group::wait, concurrency::task_group::run_and_wait oder concurrency::structured_task_group::run_and_wait anfragt. 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 Funktion do_work führt eine Anforderung zur Speicherzuweisung durch, die nicht erfolgreich ist und daher eine Ausnahme vom Typ std::bad_alloc auslöst. 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 in dem Beispiel im Thema Vorgehensweise: Konvertieren einer OpenMP-Schleife, die Abbruch verwendet, um die Concurrency Runtime zu verwenden, würden nachfolgende Schleifeniterationen nichts tun, wenn das Flag gesetzt ist. 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 Behandlung von Ausnahmen finden Sie unter Ausnahmebehandlung.
Weitere Informationen über parallel_for und andere parallele Algorithmen finden Sie unter Parallele Algorithmen.
Kompilieren des Codes
Kopieren Sie den Beispielcode, und fügen Sie ihn in ein Visual Studio-Projekt ein. Alternativ dazu können Sie ihn auch in eine Datei mit dem Namen concrt-omp-exceptions.cpp einfügen und dann folgenden Befehl in einem Visual Studio-Eingabeaufforderungsfenster ausführen.
cl.exe /EHsc /openmp concrt-omp-exceptions.cpp
Weitere Informationen
Migrieren von OpenMP zur Concurrency Runtime
Ausnahmebehandlung
Parallele Algorithmen