Udostępnij za pośrednictwem


Porady: konwertowanie pętli OpenMP używającej obsługi wyjątków do korzystania ze współbieżności środowiska wykonawczego

W tym przykładzie pokazano, jak przekonwertować równoległy protokółOpenMP dla pętli, która wykonuje obsługę wyjątków w celu korzystania z mechanizmu obsługi wyjątków środowiska uruchomieniowego współbieżności.

W programie OpenMP wyjątek zgłaszany w regionie równoległym musi zostać przechwycony i obsłużony w tym samym regionie przez ten sam wątek. Wyjątek, który ucieka przed regionem równoległym, jest przechwytywany przez nieobsługiwaną procedurę obsługi wyjątków, która domyślnie kończy proces.

W środowisku uruchomieniowym współbieżności podczas zgłaszania wyjątku w treści funkcji pracy przekazywanej do grupy zadań, takiej jak współbieżność::task_group lub współbieżność::structured_task_group obiekt, lub do algorytmu równoległego, takiego jak concurrency::p arallel_for, środowisko uruchomieniowe przechowuje ten wyjątek i marshaluje go do kontekstu, który oczekuje na zakończenie grupy zadań lub algorytmu. W przypadku grup zadań kontekst oczekiwania jest kontekstem wywołującym współbieżność::task_group::wait, concurrency::structured_task_group:wait, concurrency::task_group::run_and_wait lub concurrency::structured_task_group::run_and_wait. W przypadku algorytmu równoległego kontekst oczekiwania jest kontekstem, który nazwał ten algorytm. Środowisko uruchomieniowe zatrzymuje również wszystkie aktywne zadania, które znajdują się w grupie zadań, w tym w podrzędnych grupach zadań i odrzuca wszystkie zadania, które nie zostały jeszcze uruchomione.

Przykład

W tym przykładzie pokazano, jak obsługiwać wyjątki w regionie OpenMP parallel i w wywołaniu metody parallel_for. Funkcja do_work wykonuje żądanie alokacji pamięci, które nie powiedzie się i dlatego zgłasza wyjątek typu std::bad_alloc. W wersji używającej protokołu OpenMP wątek, który zgłasza wyjątek, również musi go przechwycić. Innymi słowy, każda iteracja pętli równoległej OpenMP musi obsługiwać wyjątek. W wersji używającej środowiska uruchomieniowego współbieżności główny wątek przechwytuje wyjątek zgłaszany przez inny wątek.

// 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();
}

W tym przykładzie są generowane następujące dane wyjściowe.

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.

W wersji tego przykładu, która używa protokołu OpenMP, wyjątek występuje w systemie i jest obsługiwany przez każdą iterację pętli. W wersji używającej środowiska uruchomieniowego współbieżności środowisko uruchomieniowe przechowuje wyjątek, zatrzymuje wszystkie aktywne zadania, odrzuca wszystkie zadania, które nie zostały jeszcze uruchomione, i marshaluje wyjątek do kontekstu, który wywołuje parallel_forelement .

Jeśli wymagana jest wersja używająca protokołu OpenMP kończy działanie po wystąpieniu wyjątku, możesz użyć flagi logicznej, aby zasygnalizować inne iteracji pętli, że wystąpił błąd. Jak w przykładzie w temacie How to: Convert an OpenMP Loop that Use the Cancellation to Use the Concurrency Runtime , kolejne iteracje pętli nie będą robić nic, jeśli flaga jest ustawiona. Z drugiej strony, jeśli wymagana jest pętla korzystająca ze środowiska uruchomieniowego współbieżności będzie kontynuowana po wystąpieniu wyjątku, obsłuż wyjątek w samej treści pętli równoległej.

Inne składniki środowiska uruchomieniowego współbieżności, takie jak agenci asynchroniczne i lekkie zadania, nie transportują wyjątków. Zamiast tego nieobsługiwane wyjątki są przechwytywane przez nieobsługiwaną procedurę obsługi wyjątków, która domyślnie kończy proces. Aby uzyskać więcej informacji na temat obsługi wyjątków, zobacz Obsługa wyjątków.

Aby uzyskać więcej informacji na temat parallel_for i innych algorytmów równoległych, zobacz Parallel Algorithms (Algorytmy równoległe).

Kompilowanie kodu

Skopiuj przykładowy kod i wklej go w projekcie programu Visual Studio lub wklej go w pliku o nazwie concrt-omp-exceptions.cpp , a następnie uruchom następujące polecenie w oknie wiersza polecenia programu Visual Studio.

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

Zobacz też

Migrowanie z OpenMP do środowiska uruchomieniowego współbieżności
Obsługa wyjątków
Algorytmy równoległe