Compartir a través de


Cómo: Convertir un bucle OpenMP que usa el control de excepciones para usar el runtime de simultaneidad

En este ejemplo se muestra cómo convertir un bucle parallel for de OpenMP que realiza el control de excepciones para usar el mecanismo de control de excepciones del runtime de simultaneidad.

En OpenMP, el mismo subproceso debe detectar y controlar en la misma región una excepción que se produce en una región paralela. Una excepción que escape de la región paralela será detectada por el controlador de excepciones no controladas, que finaliza el proceso de forma predeterminada.

En el runtime de simultaneidad, cuando se produce una excepción en el cuerpo de una función de trabajo que se pasa a un grupo de tareas como un objeto Concurrency::task_group o Concurrency::structured_task_group, o a un algoritmo paralelo como Concurrency::parallel_for, el runtime almacena esa excepción y calcula las referencias en el contexto donde espera que el grupo de tareas o el algoritmo finalice. Para los grupos de tareas, el contexto que espera es el contexto que llama a Concurrency::task_group::wait, Concurrency::structured_task_group::wait, Concurrency::task_group::run_and_wait o Concurrency::structured_task_group::run_and_wait. Para un algoritmo paralelo, el contexto que espera es el contexto que llamó a ese algoritmo. El runtime también detiene todas las tareas activas que están en el grupo de tareas, incluidas las que se encuentran en grupos de tareas secundarios, y descarta cualquier tarea que no se haya iniciado todavía.

Ejemplo

En este ejemplo se muestra cómo controlar excepciones en una región parallel de OpenMP y en una llamada a parallel_for. La función do_work realiza una solicitud de asignación de memoria que no tiene éxito y, por tanto, produce una excepción de tipo std::bad_alloc. En la versión que usa OpenMP, el subproceso que produce la excepción también debe detectarla. Es decir, cada iteración de un bucle paralelo de OpenMP debe controlar la excepción. En la versión que usa el runtime de simultaneidad, el subproceso principal detecta una excepción producida por otro subproceso.

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

Este ejemplo produce el siguiente resultado.

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.

En la versión de este ejemplo que usa OpenMP, la excepción se produce y controla en cada iteración del bucle. En la versión que usa el runtime de simultaneidad, el runtime almacena la excepción, detiene todas las tareas activas, descarta cualquier tarea que no se haya iniciado y calcula las referencias de la excepción en el contexto que llama a parallel_for.

Si necesita que la versión que usa OpenMP termine después de producirse la excepción, podría usar una marca booleana para indicar a otras iteraciones del bucle que se produjo el error. Como en el ejemplo del tema Cómo: Convertir un bucle OpenMP que usa la cancelación para usar el runtime de simultaneidad, las iteraciones subsiguientes del bucle no harán nada si se establece la marca. Por el contrario, si necesita que el bucle que usa el runtime de simultaneidad continúe después de que se produzca la excepción, controle la excepción en el cuerpo del bucle paralelo propiamente dicho.

Otros componentes del runtime de simultaneidad, como los agentes asincrónicos y las tareas ligeras, no transportan excepciones. En su lugar, el controlador de excepciones no controladas, que de forma predeterminada finaliza el proceso, detecta las excepciones no controladas. Para obtener más información acerca del control de excepciones, vea Control de excepciones en el runtime de simultaneidad.

Para obtener más información sobre parallel_for y otros algoritmos paralelos, vea Algoritmos paralelos.

Compilar el código

Copie el código de ejemplo y péguelo en un proyecto de Visual Studio o péguelo en un archivo denominado concrt-omp-exceptions.cpp y, a continuación, ejecute el siguiente comando en una ventana del símbolo del sistema de Visual Studio 2010.

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

Vea también

Conceptos

Control de excepciones en el runtime de simultaneidad

Algoritmos paralelos

Otros recursos

Migrar de OpenMP al Runtime de simultaneidad