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 parallelfor 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 si genera un'eccezione nel corpo di una funzione di lavoro che si passa a un gruppo di attività, ad esempio un concurrency::task_group o concurrency::structured_task_group oggetto, o a un algoritmo parallelo, ad esempio concurrency::parallel_for, il runtime memorizza l'eccezione ed esegue il marshalling al contesto che attende l'algoritmo o un gruppo di attività completare l'operazione.Per i gruppi di attività, il contesto di attesa è il contesto 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 di Visual Studio o incollarlo in un file denominato omp-concrt-exceptions.cpp e quindi eseguire il comando riportato di seguito in una finestra del prompt dei comandi di Visual Studio.
cl.exe /EHsc /openmp concrt-omp-exceptions.cpp
Vedere anche
Concetti
Migrazione da OpenMP al runtime di concorrenza