プラグマは、Fortran および C/C++ プログラムで高レベルの並列処理を指定するために使用できる一連のコンパイラ ディレクティブ、ライブラリ ルーチン、および環境変数OpenMP
の仕様である からのものです。
は#pragma omp parallel for schedule(dynamic,3)
、他のいくつかのプラグマを組み合わせた省略表現です。それらを見てみましょう:
#pragma omp parallel
次のステートメントを並列に実行する一連のスレッドで並列ブロックを開始します。
for loop
:のように「並列ループ」を指定することもできます#pragma omp parallel for
。このプラグマは、並列ブロック内のすべてのスレッド間で for ループを分割し、各スレッドがループのその部分を実行します。
例えば:
#pragma omp parallel
{
#pragma omp for
for(int n(0); n < 5; ++n) {
std::cout << "Hello\n";
}
これにより、for ループを実行する並列ブロックが作成されます。スレッドは、指定された順序ではなく、標準出力にHello
5 回出力します (つまり、スレッド #3 は、スレッド #1 の前に「Hello」を出力できます)。
これで、各スレッドが受け取る作業のチャンクをスケジュールすることもできます。いくつかのポリシーがあります: static
(デフォルト) とdynamic
. スケジューリング ポリシーに関しては、この素晴らしい回答を確認してください。
現在、このプラグマはすべて 1 つに短縮できます。
#pragma omp parallel for schedule(dynamic,3)
これにより、for ループを実行する並列ブロックが作成され、動的スケジューリングが行われ、ブロック内の各スレッドがループの 3 回の反復を実行してから、スケジューラにさらにチャンクを要求します。
プラグマは、次のブロックのcritical
実行を一度に 1 つのスレッドに制限します。あなたの例では、一度に1つのスレッドのみがこれを実行します:
{
if(classes_training_data.count(class_) == 0) { //not yet created...
classes_training_data[class_].create(0,response_hist.cols,response_hist.type());
classes_names.push_back(class_);
}
classes_training_data[class_].push_back(response_hist);
}
の紹介がありますOpenMP 3.0
。
最後に、言及した変数はチュートリアルで指定されています。投稿されたコードの前を見てください。
vector<KeyPoint> keypoints;
Mat response_hist;
Mat img;
string filepath;
map<string,Mat> classes_training_data;
Ptr<FeatureDetector > detector(new SurfFeatureDetector());
Ptr<DescriptorMatcher > matcher(new BruteForceMatcher<L2<float> >());
Ptr<DescriptorExtractor > extractor(new OpponentColorDescriptorExtractor(Ptr<DescriptorExtractor>(new SurfDescriptorExtractor())));
Ptr<BOWImgDescriptorExtractor> bowide(new BOWImgDescriptorExtractor(extractor,matcher));
bowide->setVocabulary(vocabulary);