Megosztás a következőn keresztül:


Útmutató: A kivételkezelést használó OpenMP-hurok átalakítása az egyidejűségi futtatókörnyezet használatára

Ez a példa bemutatja, hogyan lehet egy OpenMP párhuzamos for ciklust, amely kivételkezelést végez, átalakítani az egyidejűségi futtatókörnyezet kivételkezelési mechanizmusának használatára.

Az OpenMP-ben egy párhuzamos régióban megjelenő kivételt ugyanazon a szálon kell elkapni és kezelni ugyanabban a régióban. A párhuzamos régióból kikerülő kivételt a kezeletlen kivételkezelő fogja, amely alapértelmezés szerint leállítja a folyamatot.

Az egyidejűségi futtatókörnyezetben, amikor kivételt dob a munkafüggvény törzsében, amit egy feladatcsoportnak, például egy egyidejűség::task_group vagy egyidejűség::structured_task_group objektumnak, vagy egy párhuzamos algoritmusnak, például az egyidejűség::parallel_for, ad át, a futtatási környezet eltárolja ezt a kivételt, és továbbítja azt arra a környezetre, amely a feladatcsoport vagy algoritmus befejezésére vár. Feladatcsoportok esetében a várakozási környezet az a környezet, amely concurrency::task_group::wait, concurrency::structured_task_group::wait, concurrency::task_group::run_and_wait vagy concurrency::structured_task_group::run_and_wait hívást kezdeményezi. Párhuzamos algoritmus esetén a várakozási környezet az a környezet, amelyik meghívta az algoritmust. A futtatókörnyezet a tevékenységcsoportban lévő összes aktív tevékenységet is leállítja, beleértve a gyermektevékenység-csoportokban lévőket is, és elveti azokat a tevékenységeket, amelyek még nem kezdődtek el.

példa

Ez a példa bemutatja, hogyan kezelheti a kivételeket egy OpenMP-régióban parallel és egy hívásban parallel_for. A do_work függvény olyan memóriafoglalási kérelmet hajt végre, amely nem sikerül, ezért kivételt képez az std::bad_alloc típus alól. Az OpenMP-t használó verzióban annak a szálnak, amelyik a kivételt dobja, el is kell fognia azt. Más szóval egy OpenMP párhuzamos ciklus minden iterációjának kezelnie kell a kivételt. A Concurrency Runtime-t használó verzióban a fő szál kivételt kap, amelyet egy másik szál dob ki.

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

Ez a példa a következő kimenetet hozza létre.

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.

A példa OpenMP-t használó verziójában a kivétel az egyes ciklus iterációkban fordul elő, és azokat kezeli. Az egyidejűségi futtatókörnyezetet használó verzióban a futtatókörnyezet tárolja a kivételt, leállítja az összes aktív tevékenységet, elveti azokat a tevékenységeket, amelyek még nem kezdődtek el, és a kivételt a meghívó parallel_forkörnyezetbe helyezi.

Ha azt szeretné, hogy az OpenMP-t használó verzió a kivétel bekövetkezése után leálljon, logikai jelzővel jelezheti a hiba előfordulását más ciklus iterációknak. Amint a példában szerepel a témában Hogyan alakítsunk át egy megszakítást használó OpenMP-ciklust az egyidejű futási környezet használatára, a későbbi ciklusok nem csinálnak semmit, ha a jelző be van állítva. Ezzel szemben, ha azt szeretné, hogy a párhuzamos futtatókörnyezetet használó hurok a kivétel bekövetkezése után is folytatódjon, akkor kezelje a kivételt a párhuzamos ciklus törzsében.

Az egyidejűségi futtatókörnyezet egyéb összetevői, például az aszinkron ügynökök és az egyszerűsített feladatok nem szállítanak kivételeket. Ehelyett a kezeletlen kivételeket a nem kezelt kivételkezelő fogja, amely alapértelmezés szerint leállítja a folyamatot. A kivételkezelésről további információt a Kivételkezelés című témakörben talál.

További információ a parallel_for párhuzamos algoritmusokról és más párhuzamos algoritmusokról: Párhuzamos algoritmusok.

A kód összeállítása

Másolja ki a példakódot, és illessze be egy Visual Studio-projektbe, vagy illessze be egy elnevezett concrt-omp-exceptions.cpp fájlba, majd futtassa a következő parancsot egy Visual Studio parancssori ablakban.

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

Lásd még

Migrálás az OpenMP-ről az egyidejűségi futtatókörnyezetbe
Kivételkezelés
Párhuzamos algoritmusok