過去のParallel::Forの記事がかなりわかりにくかったので再度書く。過去記事:
以下サンプル
int i; int c1[100]; for (i = 0; i < 100; i ++) { c1[i] = i; }
#include "pch.h" using namespace System;
// Parallel::Forでデータを操作する関数を含んだクラス ref struct LoopObject { int *_array; public: LoopObject(int* data) { _array = data; } // データを操作する関数 // Parallel::Forの場合は、intの引数一つである必要がある // 引数 i ループカウンタ for(int i = 0;i<SIZE;i++){ function(i); } のような感じ
void function(int i) { // データを操作 _array[i] = i; } };
int main(array<System::String^>^ args) { // データ const int SIZE = 100; int c1[SIZE]; // Parallel::Forでデータを操作する関数を含んだクラスのインスタンスを生成 LoopObject^ forInstance = gcnew LoopObject(c1);// コンストラクタにデータを渡す // forの範囲を指定 int BEGIN = 0; int END = SIZE; // 並列処理実行 For( 開始Index , 終了Index , 一回分の処理を行う関数オブジェクト ) System::Threading::Tasks::Parallel::For( BEGIN, END, gcnew Action<int>(forInstance, &LoopObject::function) ); // 結果を表示 for (int i = 0; i < SIZE; i++) { System::Console::WriteLine( System::String::Format("mydata[{0}] = {1}", i, c1[i])); } Console::ReadLine(); return 0; }
Action<int>のintはLoopObject::functionの引数がintなので、ループカウンタを与える関数に合わせているのだが、問題はParallel::Forがintしか受け付けていないので、実質Action<int>以外に選択肢がない(Action<size_t>などやってもParallel::Forでビルドエラーになる)。
要は「関数オブジェクトを並列で呼び出す関数」がParallel::Forで、Actionのインスタンスが関数オブジェクトになる。C++でそれっぽいコードを書くと以下になる。
std::sort(begin,end,[](...){...});とやるときと考え方は同じ。
#include <functional> struct LoopObject { int* _array; public: LoopObject(int* data) { _array = data; } // データを操作する関数 // Parallel::Forの場合は、intの引数一つである必要がある // 引数 i ループカウンタ for(int i = 0;i<SIZE;i++){ function(i); } のような感じ void function(int i) { // データを操作 _array[i] = i; } }; namespace Parallel { void For(int start, int end, LoopObject* action) { // 本来はここは並列処理で呼び出すが // 今回はシングルスレッドで実行する for (int i = start; i < end; i++) { action->function(i); } } } int main() { int c1[100]; auto action = new LoopObject(c1); Parallel::For(0, 100, action); // 結果の表示 for (int i = 0; i < 100; i++) { printf("%d\n", c1[i]); } }