Практическое руководство. Преобразование цикла OpenMP, использующего обработку исключений для использования среды выполнения с параллелизмом

В этом примере показано, как преобразовать параллельOpenMP для цикла, выполняющего обработку исключений для использования механизма обработки исключений среды выполнения параллелизма.

В OpenMP исключение, которое создается в параллельном регионе, должно быть поймано и обработано в том же регионе тем же потоком. Исключение, которое экранирует параллельный регион, перехватываются необработанным обработчиком исключений, который завершает процесс по умолчанию.

В среде выполнения параллелизма при возникновении исключения в тексте рабочей функции, передаваемой в группу задач, например параллелизм::task_group или параллелизм::structured_task_group объект или параллельный алгоритм, например параллелизм::p arallel_for, среда выполнения сохраняет это исключение и маршалирует его в контекст, который ожидает завершения группы задач или алгоритма. Для групп задач контекст ожидания — это контекст, который вызывает параллелизм::task_group::wait, concurrency::structured_task_group::wait, concurrency::task_group::run_and_wait или параллелизм:::structured_task_group:::run_and_wait. Для параллельного алгоритма контекст ожидания — это контекст, который называется этим алгоритмом. Среда выполнения также останавливает все активные задачи, которые находятся в группе задач, в том числе в дочерних группах задач, и отключает карта все задачи, которые еще не запущены.

Пример

В этом примере показано, как обрабатывать исключения в регионе OpenMP parallel и в вызове parallel_for. Функция do_work выполняет запрос на выделение памяти, который не завершается успешно и поэтому создает исключение типа std::bad_alloc. В версии, использующая OpenMP, поток, который вызывает исключение, также должен перехватывать его. Другими словами, каждая итерация параллельного цикла OpenMP должна обрабатывать исключение. В версии, которая использует среду выполнения параллелизма, основной поток перехватывает исключение, которое создается другим потоком.

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

В этом примере формируются следующие данные:

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.

В версии этого примера, использующего OpenMP, исключение выполняется и обрабатывается каждой итерацией цикла. В версии, в которой используется среда выполнения параллелизма, среда выполнения сохраняет исключение, останавливает все активные задачи, не карта выполняет все задачи, которые еще не запущены, и маршалирует исключение в контексте, который вызываетparallel_for.

Если требуется, чтобы версия, использующая OpenMP, завершается после возникновения исключения, можно использовать логический флаг для сигнала другим итерациям цикла об ошибке. Как показано в примере в разделе Практическое руководство. Преобразование цикла OpenMP, использующего отмену для использования среды выполнения параллелизма, последующие итерации цикла не будут делать ничего, если флаг задан. И наоборот, если требуется, чтобы цикл, использующий среду выполнения параллелизма, продолжался после возникновения исключения, обработайте исключение в самом теле параллельного цикла.

Другие компоненты среды выполнения параллелизма, такие как асинхронные агенты и упрощенные задачи, не передают исключения. Вместо этого необработанные исключения перехватываются необработанным обработчиком исключений, который завершает процесс по умолчанию. Дополнительные сведения об обработке исключений см. в разделе "Обработка исключений".

Дополнительные сведения о parallel_for и других параллельных алгоритмах см. в разделе "Параллельные алгоритмы".

Компиляция кода

Скопируйте пример кода и вставьте его в проект Visual Studio или вставьте его в файл с именем concrt-omp-exceptions.cpp , а затем выполните следующую команду в окне командной строки Visual Studio.

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

См. также

Переход от OpenMP к среде выполнения с параллелизмом
Обработка исключений
Параллельные алгоритмы