#概要
ガッツリイチから解説しているのと、本当に触りのところだけ解説が多い気がしたので、Visual Studio C++で、最低限OpenMPをサクッと使う方法を知りたかった。
#準備
・プロジェクトのプロパティ
C/C++ → 言語 → OpenMP のサポート
を「はい (/openmp)
」にする
C/C++ → コマンド ライン に
「/Zc:twoPhase-
」を追加
(OpenMP時は、2フェーズ名前解決が出来ない、というエラー対策)
#コード
前置きとして、上記設定を行っていなかったとしてもビルド警告が出ず、並列化したつもりが実は出来ていなかったとかありえるので、まずは簡単な処理で並列化して実行してみて、実行順が順不同になったことを確認した方が良いです。
(順不同になったということは、順次実行ではなくなったということで、並列化が効いたと考えられるはず。)
##必要なインクルード
#include <omp.h>
##for文を並列化
#pragma omp parallel for for () { }
#pragma omp parallel for
for (int i = 0; i < count; i++) {
// ここは並列実行される
}
##クリティカルセクションを指定
#pragma omp critical([セクション名]) { }
int aaaa = 0; // スコープ外の変数は、共有されるので、排他制御が必要
#pragma omp parallel for
for (int i = 0; i < 100; i++) {
// ここは並列実行される
int bbbb = 0; // スコープ内のローカル変数は自動でスレッド数分用意される
#pragma omp critical(crit_sct)
{
// この内部だけ順次実行される
aaaa += 1;
}
// ここは並列実行される
}
##順番通り(並列化せず)に実行
(ただし、1つのforの中に1つしか書けない)
#pragma omp ordered {}
int count = 100;
// ordered使う時は、"ordered"句を後ろにくっつけて、どの"parallel for"を順次実行するのか指定する必要がある
#pragma omp parallel for ordered
for (int i = 0; i < count; i++) {
#pragma omp ordered
{
// ここは順番通りに実行される
}
}
#まとめサンプルコード
(この記事には記載していませんが、くれぐれも、mutexなどの排他処理は慎重に)
#include <iostream>
#include <Windows.h>
#include <omp.h>
int main(void)
{
const int LOOP_MAX = 10;
#pragma omp parallel for
for (int i = 0; i < LOOP_MAX; i++) {
cout << "para. ";
cout << i << endl;
}
cout << endl;
#pragma omp parallel for
for (int i = 0; i < LOOP_MAX; i++) {
#pragma omp critical(crit_sct)
{
cout << "crit. ";
cout << i << endl;
}
}
cout << endl;
#pragma omp parallel for ordered
for (int i = 0; i < LOOP_MAX; i++) {
#pragma omp ordered
{
cout << "orde. ";
cout << i << endl;
}
}
Sleep(10000);
return 0;
}
para. 0
para. 1
para. para. 5
para. 6
para. 7
para. 8
para. 9
2
para. 3
para. 4
crit. 5
crit. 6
crit. 7
crit. 8
crit. 9
crit. 0
crit. 1
crit. 2
crit. 3
crit. 4
orde. 0
orde. 1
orde. 2
orde. 3
orde. 4
orde. 5
orde. 6
orde. 7
orde. 8
orde. 9
間違い等あれば、ご指摘いただければ幸いです
#バージョン・規格
- 試したバージョン: Visual Studio 2017
- OpenMP Specifications
- Microsoft Docs | OpenMP Directives
また、Visual C++はOpenMP 2.0までしかサポートしていないらしいです。
(ご指摘コメントありがとうございます。)