Практическое руководство. Преобразование цикла 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 к среде выполнения с параллелизмом
Обработка исключений
Параллельные алгоритмы