OpenMP* 検証サンプル
taskloop 初級編

このセッションは、「インテル® コンパイラーを使用した OpenMP* 5.0 による並列プログラミング・セミナー【パート 1】」で公開されているオンラインセミナーの補足セッションです内容◼

ワークシェアを taskloop に移行する利点はあるか− 典型的な pi の計算の例− ループ反復の負荷が均一ではない prime の例− 並列構造の入れ子
このセッションは、「インテル® コンパイラーを使用した OpenMP* 5.0 による並列プログラミング・セミナー【パート 1】」
で公開されているオンラインセミナーの補足セッションです
動画を再生する際、お客様情報を入力していただく必要がありますので、予めご了承ください© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 2ここで使用する環境
Windows* 10 Pro 1909
◼ インテル® Core™ i7-9700K プロセッサー (8 コア、8 スレッド)、
メモリー 16GB◼ インテル® C++ コンパイラー 19.1 Update 2 (VS2017 ライブラリー)◼ インテル® VTune™ プロファイラー 2020 Update2 (日本語パッケージ)◼

© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 3

ｔaskloop ディレクティブ#pragma omp taskloop[節[ [, ]節] ...]

for ループ
1 つ以上の関連するループ反復を OpenMP* タスクを使用して並列に実行します節:
shared(list)、default(shared | none)
private(list)、 firstprivate(list)、lastprivate(list)
reduction([default,][reduction-identifier: list)]
in_reduction(reduction-identifier: list)
grainsize(grain-size)、num_tasks(num_tasks)
collapse(n)、priority(priority-value)
untied、mergeable、nogroup
allocate([allocator:] list)if([taskloop:]scalar-expression)
final(scalar-expression)

赤字は OpenMP* 5.0 で追加

https://www.isus.jp/products/c-compilers/openmp-ref-5-0-0519-released/© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 4

parallel for と taskloop の動作を確認 (pi)for ワークシェアを単純に taskloop にする利点はあるのか?
#ifdef TASKLOOP#pragma omp parallel#pragma omp single#pragma omp taskloop simd reduction(+:sum) private(x)#else#pragma omp parallel for simd reduction(+:sum) private(x)#endiffor (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}
pi = step * sum;

デフォルトのスレッド数 = 論理コア数© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 5

parallel for と taskloop の動作を確認 (pi)#ifdef TASKLOOP#pragma omp parallel#pragma omp single#pragma omp taskloop simd reduction(+:sum) private(x)#else#pragma omp parallel for simd reduction(+:sum) private(x)#endiffor (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}
pi = step * sum;© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 6

インテル® VTune™ プロファイラーのタイムラインで確認
parallel for ワークシェアのタイムライン

taskloop のタイムライン◼ parallel for ではスレッドのチームを構成するのに時間を要しているように見える◼ taskloop は CPU 時間が連続する期間が短い◼ taskloop の GRAINSIZE は自動的に調整される◼ parallel for の for ループはデフォルトで (ループサイズ/スレッド数) でブロック化される© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 7

taskloop の粒度を強制 (サイズ 10)#pragma omp parallel#pragma omp single#pragma omp taskloop simd reduction(+:sum) private(x) grainsize(10)for (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 8

taskloop の粒度を強制 (ループサイズ/スレッド数)#pragma omp parallel#pragma omp single#pragma omp taskloop simd reduction(+:sum) private(x)grainsize(num_steps/omp_get_num_threads())
for (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 9

taskloop の利点

OMP_NUM_THREADS=16 のケース

◼ for ワークシェアでは、16 個のスレッドにループが均等に分割され、スレッドは OS のスケジューラーでスケジュールされる (スレッド過度の状態)◼ taskloop では、生成された 16 個のスレッドが OS スケジューラーでスケジュールされアクティブなときにキューからタスクを取得して実行 (タスクがスケジュール・アウトされる可能性が低い)© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 10

prime を parallel for と taskloop で実行#ifdef TASKLOOP#pragma omp parallel#pragma omp single#pragma omp taskloop reduction(+:gPrimesFound)#else#pragma omp parallel for reduction(+:gPrimesFound)#endiffor( int i = start; i <= end; i+=2 ){if( TestForPrime(i) )gPrimesFound++;}}© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

変数 end は 50000000 であり、潜在的に TestForPrime 関数は大きな値を評価するほど時間がかかります| 11for ワークシェアと taskloop の違い

parallel for の場合

taskloop の場合© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 12

for と taskloop の入れ子の並列処理構造
main(){…
for(int i=0; i<MAX; i++)re[i]=fib(i);…
}int fib(int n){
int x, y;if(n<2) return n;
x = fib(n-1);
y = fib(n-2);
return x+y;}

for ループを並列実行できない?

再帰呼び出しを並列実行できない?

#pragma omp parallel for
for(int i=0; i<MAX; i++)re[i]=fib(i);#pragma omp parallel#pragma omp single#pragma omp taskloop
for(int i=0; i<MAX; i++)re[i]=fib(i);if(n<2) return n;#pragma omp single{#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);}#pragma omp taskwait
return x+y;

© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

if(n<2) return n;#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);#pragma omp taskwait
return x+y;| 13適切なタスク処理構造は?
main(){…
for(int i=0; i<MAX; i++)re[i]=fib(i);…
}int fib(int n){
int x, y;if(n<2) return n;
x = fib(n-1);
y = fib(n-2);
return x+y;}task と taskwait

task と taskgroup#pragma omp parallel#pragma omp single
for(int i=0; i<MAX; i++)re[i]=fib(i);#pragma omp parallel#pragma omp single#pragma omp taskloop
for(int i=0; i<MAX; i++)re[i]=fib(i);if(n<2) return n;#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);#pragma omp taskwait
return x+y;if(n<2) return n;#pragma omp taskgroup{#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);}
return x+y;

© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 14適切なタスク処理構造は?
main(){…
for(int i=0; i<MAX; i++)re[i]=fib(i);…
}int fib(int n){
int x, y;if(n<2) return n;
x = fib(n-1);
y = fib(n-2);
return x+y;}task と taskwait

task と taskgroup#pragma omp parallel#pragma omp single
for(int i=0; i<MAX; i++)re[i]=fib(i);#pragma omp parallel#pragma omp single#pragma omp taskloop
for(int i=0; i<MAX; i++)re[i]=fib(i);if(n<2) return n;#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);#pragma omp taskwait
return x+y;if(n<2) return n;#pragma omp taskgroup{#pragma omp task shared(x)x = fib(n-1);#pragma omp task shared(y)y = fib(n-2);}
return x+y;

© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 15

まとめ
単純にループ・ワークシェア構造を taskloop に置き換えるメリットは少ない− 何らかの理由が必要◼ 並列構造の入れ子では、ループ・ワークシェア構造とタスク構造を混在するのは避けるべき◼ タスク構造を入れ子にする必要がある場合、taskgroup の利用も検討してください◼ 並列構造の入れ子は注意深く構成する必要があります◼

Intel、インテル、Intel ロゴ、Intel Core、VTune は、アメリカ合衆国および / またはその他の国における Intel Corporation またはその子会社の商標です。
© 2020 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

| 16

ソフトウェア・セミナー