Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Questo esempio illustra come convertire un ciclo OpenMP parallelofor che esegue la gestione delle eccezioni per usare 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 che esegue l'escape dell'area parallela viene intercettata dal gestore eccezioni non gestito, che termina il processo per impostazione predefinita.
Nel runtime di concorrenza, quando si genera un'eccezione nel corpo di una funzione di lavoro passata a un gruppo di attività, ad esempio una concorrenza::task_group o un oggetto concurrency::structured_task_group o a un algoritmo parallelo, ad esempio concurrency::p arallel_for, il runtime archivia tale eccezione e lo effettua al 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 in attesa è il contesto che ha chiamato tale algoritmo. Il runtime arresta anche tutte le attività attive presenti nel gruppo di attività, incluse quelle nei gruppi di attività figlio, e rimuove tutte le attività che non sono ancora state avviate.
Esempio
In questo esempio viene illustrato come gestire le eccezioni in un'area OpenMP parallel e in una chiamata a parallel_for. La do_work funzione esegue una richiesta di allocazione di memoria che non riesce e quindi genera un'eccezione di tipo std::bad_alloc. Nella versione che usa OpenMP, anche il thread che genera l'eccezione deve intercettarlo. In altre parole, ogni iterazione di un ciclo parallelo OpenMP deve gestire l'eccezione. Nella versione che usa 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 il seguente output:
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 che usa OpenMP, l'eccezione si verifica in e viene gestita da ogni iterazione del ciclo. Nella versione che usa il runtime di concorrenza, il runtime archivia l'eccezione, arresta tutte le attività attive, rimuove tutte le attività non ancora avviate e effettua il marshalling dell'eccezione al contesto che chiama parallel_for.
Se è necessario che la versione che usa OpenMP termini dopo l'eccezione, è possibile usare un flag booleano per segnalare ad altre iterazioni del ciclo che si è verificato l'errore. Come nell'esempio dell'argomento Procedura: Convertire un ciclo OpenMP che usa l'annullamento per usare il runtime di concorrenza, le iterazioni successive del ciclo non eseguirebbero alcuna operazione se il flag è impostato. Viceversa, se è necessario che il ciclo che usi il runtime di concorrenza continui dopo che si verifica l'eccezione, gestire l'eccezione nel corpo del ciclo parallelo stesso.
Altri componenti del runtime di concorrenza, ad esempio agenti asincroni e attività leggere, non trasportano eccezioni. Al contrario, le eccezioni non gestite vengono rilevate dal gestore di eccezioni non gestite, che termina il processo per impostazione predefinita. Per altre informazioni sulla gestione delle eccezioni, vedere Gestione delle eccezioni.
Per altre 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 oppure incollarlo in un file denominato concrt-omp-exceptions.cpp e quindi eseguire il comando seguente in una finestra del prompt dei comandi di Visual Studio.
cl.exe /EHsc /openmp concrt-omp-exceptions.cpp
Vedi anche
Migrazione da OpenMP al runtime di concorrenza
Gestione delle eccezioni
Algoritmi paralleli