共用方式為


HOW TO:轉換使用例外狀況處理的 OpenMP 迴圈來使用並行執行階段

這個範例示範如何轉換執行例外狀況處理的 OpenMP parallel for 迴圈,以使用並行執行階段例外狀況處理機制。

在 OpenMP 中,在平行區域中擲回的例外狀況必須在相同區域中由相同執行緒攔截及處理。 逸出平行區域的例外狀況是由未處理例外處理常式攔截,該處理常式預設會結束處理序。

並行執行階段時擲回例外狀況在函式主體的工作,例如經過到工作群組中 concurrency::task_groupconcurrency::structured_task_group 物件,或以平行的演算法,例如 concurrency::parallel_for,執行階段會儲存該例外狀況並之間封送處理等待完成的工作群組或演算法的內容。 為工作群組,請等候內容是內容會呼叫 concurrency::task_group::waitconcurrency::structured_task_group::waitconcurrency::task_group::run_and_wait,或 concurrency::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 的版本在例外狀況發生之後結束,可以使用 Boolean 旗標對發生錯誤的其他迴圈反覆項目發出信號。 如 HOW TO:轉換使用取消的 OpenMP 迴圈來使用並行執行階段主題的範例所示,如果設定了旗標,後續迴圈反覆項目就不會執行任何動作。 相反地,如果您需要使用並行執行階段的迴圈在例外狀況發生之後繼續進行,請在平行迴圈主體本身內處理例外狀況。

並行執行階段的其他元件 (例如非同步代理程式和輕量型工作) 不會傳輸例外狀況。 而未處理例外狀況是由未處理例外處理常式攔截,而該處理常式預設會結束處理序。 如需例外狀況處理的詳細資訊,請參閱並行執行階段的例外狀況處理

如需 parallel_for 和其他平行演算法的詳細資訊,請參閱平行演算法

編譯程式碼

將範例程式碼複製並貼上它在 Visual Studio 專案中,或將它貼在檔名為 concrt-omp-exceptions.cpp ,然後執行下列命令,Visual Studio 的命令提示字元] 視窗中。

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

請參閱

概念

從 OpenMP 移轉至並行執行階段

並行執行階段的例外狀況處理

平行演算法