Condividi tramite


Procedura: convertire un ciclo OpenMP che utilizza la gestione delle eccezioni per l'utilizzo del runtime di concorrenza

In questo esempio viene illustrato come convertire un ciclo parallel for di OpenMP che esegue la gestione delle eccezioni in modo da utilizzare il meccanismo di gestione delle eccezioni del runtime di concorrenza.

In OpenMP un'eccezione generata in un'area parallela deve essere intercettata e gestita nella stessa area dallo stesso thread. Un'eccezione ignorata nell'area parallela viene rilevata dal gestore delle eccezioni non gestite che per impostazione predefinita termina il processo.

Nel runtime di concorrenza quando viene generata un'eccezione nel corpo di una funzione lavoro passata a un gruppo di attività come un oggetto Concurrency::task_group o Concurrency::structured_task_group o a un algoritmo parallelo come Concurrency::parallel_for, il runtime archivia l'eccezione e ne esegue il marshalling nel contesto che attende il completamento del gruppo di attività o dell'algoritmo. Per i gruppi di attività il contesto di attesa è il contesto che chiama Concurrency::task_group::wait, Concurrency::structured_task_group::wait, Concurrency::task_group::run_and_wait o Concurrency::structured_task_group::run_and_wait. Per un algoritmo parallelo, il contesto di attesa è il contesto che ha chiamato l'algoritmo. Il runtime arresta inoltre tutte le attività attive presenti nel gruppo di attività, comprese quelle presenti nei gruppi di attività figlio, ed elimina le attività che non sono ancora state avviate.

Esempio

In questo esempio viene illustrato come gestire le eccezioni in un'area parallel di OpenMP e in una chiamata a parallel_for. La funzione do_work esegue una richiesta di allocazione della memoria che non ha esito positivo e pertanto genera un'eccezione di tipo std::bad_alloc. Nella versione che utilizza OpenMP il thread che genera l'eccezione deve anche intercettarla. In altre parole, ogni iterazione di un ciclo parallelo OpenMP deve gestire l'eccezione. Nella versione che utilizza il runtime di concorrenza, il thread principale intercetta un'eccezione generata da un altro thread.

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

Questo esempio produce l'output che segue.

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.

Nella versione di questo esempio in cui viene utilizzato OpenMP l'eccezione viene generata e gestita da ogni iterazione del ciclo. Nella versione che utilizza il runtime di concorrenza, il runtime archivia l'eccezione, arresta inoltre tutte le attività attive, elimina le attività che non sono ancora state avviate ed esegue il marshalling dell'eccezione nel contesto che chiama parallel_for.

Se è necessario che la versione che utilizza OpenMP termini dopo la generazione dell'eccezione, è possibile utilizzare un flag booleano per segnalare alle altre iterazioni del ciclo che si è verificato l'errore. Come nell'esempio riportato nell'argomento Procedura: convertire un ciclo OpenMP che utilizza l'annullamento per l'utilizzo del runtime di concorrenza, se è impostato il flag le iterazioni successive del ciclo non eseguono alcuna operazione. Al contrario, se è necessario che il ciclo che utilizza il runtime di concorrenza continui dopo la generazione dell'eccezione, gestire l'eccezione nel corpo del ciclo parallelo stesso.

Gli altri componenti del runtime di concorrenza, ad esempio gli agenti asincroni e le attività leggere, non trasportano le eccezioni. Le eccezioni non gestite vengono invece rilevate dal gestore delle eccezioni non gestite che per impostazione predefinita termina il processo. Per ulteriori informazioni sulla gestione delle eccezioni, vedere Gestione delle eccezioni nel runtime di concorrenza.

Per ulteriori informazioni su parallel_for e altri algoritmi paralleli, vedere Algoritmi paralleli.

Compilazione del codice

Copiare il codice di esempio e incollarlo in un progetto Visual Studio oppure incollarlo in un file denominato concrt-omp-exceptions.cpp, quindi eseguire il comando seguente in una finestra del prompt dei comandi di Visual Studio 2010.

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

Vedere anche

Concetti

Gestione delle eccezioni nel runtime di concorrenza

Algoritmi paralleli

Altre risorse

Migrazione da OpenMP al runtime di concorrenza