Compartilhar via


Como: Converter um loop de OpenMP que use manipulação de exceção para usar o tempo de execução de concorrência

Este exemplo mostra como converter um loop de OpenMP paralelapara que executa manipulação de exceção para usar o mecanismo de manipulação de exceção de tempo de execução de simultaneidade.

Em OpenMP, uma exceção que é lançada em uma região paralela deve ser interceptada e tratado na mesma região pelo mesmo segmento.Uma exceção que escape a região paralela é capturada pelo manipulador de exceção não tratada, terminando o processo por padrão.

Em tempo de execução de concorrência, quando você gera uma exceção no corpo de uma função de trabalho que você passe a um grupo de trabalho como um objeto de concurrency::task_group ou de concurrency::structured_task_group , ou um algoritmo paralelo como concurrency::parallel_for, o tempo de execução que armazena exceção e ele lê ao contexto que espera o grupo de trabalho ou o algoritmo para concluir.Para grupos de trabalho, 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 que chamou o algoritmo.O runtime também para todas as tarefas ativas que estão no grupo de trabalho, incluindo aqueles em grupos de trabalho filhos, e em descarta todas as tarefas que ainda não começarem.

Exemplo

Este exemplo mostra como tratar exceções em uma região de OpenMP parallel e em uma chamada para parallel_for.A função de do_work executa uma solicitação de alocação de memória que não tenha êxito e consequentemente lança uma exceção de tipo std::bad_alloc.Na versão que usa OpenMP, o segmento que gera a exceção deve também capturou.Ou seja cada iteração de um loop de paralela de OpenMP deve tratar a exceção.Na versão que usa o tempo de execução de concorrência, o segmento principal capturar uma exceção que é lançada por outro segmento.

// 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.

  
  
  
  
  
  
  
  
  
  
  
  
  

Na versão deste exemplo que usa OpenMP, a exceção ocorre em e é tratada por cada iteração do loop.Na versão que usa o tempo de execução de concorrência, os armazenamentos de tempo de execução pára a exceção, todas tarefas ativas, descarta em algumas tarefas que ainda não começarem, e em controla a exceção ao contexto que chama parallel_for.

Se você requer que a versão que usa OpenMP finaliza após a exceção ocorre, você pode usar um sinalizador booleano para sinalizar a outras iterações do loop que ocorreu o erro.Como no exemplo no tópico Como: Converter um loop de OpenMP que usa o botão para usar o tempo de execução de concorrência, as iterações subsequentes de loop não fariam nada se o parâmetro é definido.Por outro lado, se você requer que o loop que usa o tempo de execução de simultaneidade é retomada após a exceção ocorre, lida com a exceção no corpo de loop paralelo própria.

Outros componentes de tempo de execução de concorrência, como agentes assíncronos e tarefas leve, não transmitem exceções.Em vez disso, as exceções não tratadas são detectadas pelo manipulador de exceção não tratada, terminando o processo por padrão.Para obter mais informações sobre manipulação de exceção, consulte Manipulação de exceção em tempo de execução de concorrência.

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 cole-o em um projeto do Visual Studio, ou cole em um arquivo denominado concrt-omp-exceptions.cpp e execute o seguinte comando em uma janela de prompt de comando do Visual Studio.

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

Consulte também

Conceitos

Migrando de OpenMP ao tempo de execução de concorrência

Manipulação de exceção em tempo de execução de concorrência

Algoritmos paralelos