Compartilhar via


Como: Converter um Loop do OpenMP usa o tratamento de exceção para usar o Runtime de simultaneidade

Este exemplo demonstra como converter um OpenMP paralela para loop realiza a manipulação de exceção para usar a mecanismo de manipulação de exceção de Runtime de simultaneidade.

Em OpenMP, uma exceção é acionada em uma região paralela deve ser detectada e manipulada na mesma região pelo mesmo thread. Uma exceção que expõe a região paralela é capturada pelo manipulador de exceção sem tratamento, encerra o processo por padrão.

No Runtime de simultaneidade, quando você lançar uma exceção no corpo de uma função de trabalho que você passa para um grupo de tarefas, como um Concurrency::task_group ou Concurrency::structured_task_group o objeto, ou para um algoritmo paralelo, como Concurrency::parallel_for, o runtime armazena essa exceção e dispõe o contexto que aguarda o algoritmo ou o grupo de tarefas concluir. Para grupos de tarefas, o contexto de espera é o contexto que chama Concurrency::task_group::wait, Concurrency::structured_task_group::wait, Concurrency::task_group::run_and_wait, ou Concurrency::structured_task_group::run_and_wait. Para um algoritmo paralelo, o contexto de espera é o contexto de chamada desse algoritmo. O runtime também interrompe todas as tarefas ativas que estão no grupo de tarefas, inclusive aqueles em grupos de tarefas filho, e descarta quaisquer tarefas que ainda não iniciaram.

Exemplo

Este exemplo demonstra como tratar exceções em um OpenMP parallel região e, em uma chamada para parallel_for. O do_work função realiza uma solicitação de alocação de memória que não terá êxito e, portanto, lança uma exceção do tipo std::bad_alloc. Na versão que usa o OpenMP, o thread que lança a exceção deve também alcançá-la. Em outras palavras, cada iteração de um loop de paralela OpenMP deve tratar a exceção. Na versão que usa o Runtime de simultaneidade, o thread principal detecta uma exceção que é lançada por outro 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();
}

O exemplo produz a seguinte saída.

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.

Na versão desse exemplo que usa o OpenMP, a exceção ocorre em e é tratada por cada iteração do loop. Na versão que usa o Runtime de simultaneidade, o tempo de execução armazena a exceção, interrompe todas as tarefas ativas, descarta todas as tarefas que ainda não iniciado e empacota a exceção para o contexto que chama parallel_for.

Se você precisar que a versão que usa o OpenMP encerra depois que a exceção ocorre, você poderia usar um sinalizador booleano para sinalizar para outras iterações do loop, o erro ocorreu. Como no exemplo no tópico Como: Converter um Loop do OpenMP usa o cancelamento para usar o Runtime de simultaneidade, iterações do loop subseqüentes faria nada se o sinalizador é definido. Por outro lado, se você precisar que o loop que usa o Runtime de simultaneidade continua após a exceção ocorre, manipule a exceção no próprio corpo do loop paralelo.

Outros componentes do Runtime de simultaneidade, como agentes assíncronos e tarefas leves, não transporte exceções. Em vez disso, as exceções não tratadas são detectadas pelo manipulador de exceção sem tratamento, encerra o processo por padrão. Para obter mais informações sobre o tratamento de exceções, consulte O Runtime de simultaneidade de manipulação de exceção.

Para obter mais informações sobre parallel_for e outros algoritmos paralelos, consulte Algoritmos paralelos.

Compilando o código

Copie o código de exemplo e colá-lo em um Visual Studio do projeto, ou colá-lo em um arquivo que é chamado omp-concrt-exceptions.cpp e, em seguida, execute o seguinte comando um Visual Studio 2010 janela do Prompt de comando.

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

Consulte também

Conceitos

O Runtime de simultaneidade de manipulação de exceção

Algoritmos paralelos

Outros recursos

Migrando do OpenMP para o Runtime de simultaneidade