並列パターン ライブラリ (PPL)における取り消し処理 タスク グループ、構造タスク グループのcancel()メソッドで実行中の並列処理を中断する方法、および、try-catch文で中断する方法をメモします。 下記のソースでは、配列にあるデータをサーチする処理として、タスク グループの使い方、および並列処理中断方法を記述します。 // parallel_cancel.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #include <windows.h> #include <ppl.h> #include <iostream> using namespace std; using namespace Concurrency; //配列を宣言します。 int dat[10000]; //時間テストの為に、遅延を入れます。 void delay() { for (int i = 0; i < 20000; i ++); } //シリアルのサーチ処理。 int SearchDataSeiral(int from, int to, int key) { for (int i = from; i < to; i ++) { delay(); if (key == dat[i]) return i; } return INT_MAX; } //タスクグループで、2つの処理を同時にさせます。 int SearchData_TaskGroup(int key) { int n1; int n2; task_group tg; tg.run([&](){n1 = SearchDataSeiral(0,5000, key);}); tg.run([&](){n2 = SearchDataSeiral(5000,10000, key);}); tg.wait(); return min(n1, n2); } //構造タスクグループで、2つの処理を同時にさせます。 int SearchData_StructuredTaskGroup(int key) { int n1; int n2; structured_task_group stg; auto task1 = make_task([&](){n1 = SearchDataSeiral(0,5000, key);}); stg.run(task1); auto task2 = make_task([&](){n2 = SearchDataSeiral(5000,10000, key);}); stg.run(task2); stg.wait(); return min(n1, n2); } //構造タスクグループ内で、parallel_forを実行します。 //ある条件で、構造タスクグループのcancel()を呼び出して、処理をキャンセルさせます。 int SearchData_StructuredTaskGroup_Cancel(int key) { structured_task_group stg; int n; task_group_status status = stg.run_and_wait([&] { parallel_for(0, 10000, [&](int i) { delay(); if (key == dat[i]) { n = i; stg.cancel(); } }); }); // Print the task group status. cout << "The task group status is: "; switch (status) { case not_complete: cout << L"not complete." << endl; n = INT_MAX; break; case completed: cout <<"completed." << endl; n = INT_MAX; break; case canceled: cout << "canceled." << endl; break; default: cout << "unknown." << endl; n = INT_MAX; break; } return n; } //try-catchで、parallel_forをキャンセルさせます。 int SearchData_Parallel_Try_Catch_Cancel(int key) { int n = INT_MAX; try { parallel_for(0, 10000, [&](int i) { // Throw an exception to cancel the task when i is 50. delay(); if (key == dat[i]) { throw i; } }); } catch (int inx) { cout << "Caught " << inx << endl; n = inx; } return n; } int _tmain(int argc, _TCHAR* argv[]) { //配列初期化(乱数) srand(::GetTickCount()); for (int i = 0; i < 10000; i ++) dat[i] = abs(rand()) % 2000; //以下は、各関数のテストです。 DWORD begin = 0, end = 0; int result = 0; begin = ::GetTickCount(); result = SearchData_TaskGroup(1000); end = GetTickCount(); cout << "SearchData_TaskGroup" << endl; cout << end - begin<<" ms "<< result << endl; begin = 0, end = 0, result = 0; begin = ::GetTickCount(); result = SearchData_StructuredTaskGroup(1000); end = GetTickCount(); cout << "SearchData_StructuredTaskGroup" << endl; cout << end - begin<<" ms "<< result << endl; begin = 0, end = 0, result = 0; begin = ::GetTickCount(); result = SearchData_StructuredTaskGroup_Cancel(1000); end = GetTickCount(); cout << "SearchData_StructuredTaskGroup_Cancel" << endl; cout << end - begin<<" ms "<< result << endl; begin = 0, end = 0, result = 0; begin = ::GetTickCount(); result = SearchData_Parallel_Try_Catch_Cancel(1000); end = GetTickCount(); cout << "SearchData_Parallel_Try_Catch_Cancel" << endl; cout << end - begin<<" ms "<< result << endl; getchar(); return 0; } /*-------------------------------------- Output: SearchData_TaskGroup 157 ms 982 SearchData_StructuredTaskGroup 156 ms 982 The task group status is: canceled. SearchData_StructuredTaskGroup_Cancel 78 ms 982 Caught 982 SearchData_Parallel_Try_Catch_Cancel 63 ms 982 */ |