インテル® コンパイラーによる並列プログラミング:
OpenMP* 5.0 プレビュー2018 年 3 月
iSUS 編集部© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

このセッションの目的

明示的な並列プログラミング手法として注目されてきた OpenMP* による並列
プログラミングに加え、インテル® コンパイラーがサポートする OpenMP* 4.0 と4.5 の機能を使用したベクトル・プログラミングとオフロード・プログラミングの概要をリフレッシュし、インテル® コンパイラー V18.0 でサポートされる
OpenMP* 5.0 TR4 および TR6 の機能と実装を紹介します

セッションの対象者


既に OpenMP* でマルチスレッド・プログラミングを開発し、4.0 以降でサポートされる新たなベクトル化とオフロードを導入し、アプリケーションのパフォーマン
ス向上を計画する開発者© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

2

内容
 はじめに (OpenMP* が必要とされる背景)
 概要 (OpenMP* とは、歴史、各バージョンの機能概要)
 OpenMP* 4.0 と 4.5 および 5.0 の新機能

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

3

はじめに
 コードの現代化 (モダニゼーション)
 OpenMP* が求められる背景
 マルチスレッド化
 ベクトル化 ノード間の並列処理© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

4

Think Parallel or Perish

あれから 8 年 …

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

5

Vectorize or Die
Think Parallel or Perish

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

6

Code Modernization (コードのモダン化)
マルチコア・
プロセッサー

高帯域幅プロセッサー間通信
高速 I/O
高速メモリー

スレッド並列大きなキャッシュ

メニーコア・
プロセッサー© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

7

マルチレベルの並列性を実装する 5 つのステップ
ステージ 4:
3: 並列化
ベクトル化
2:スカラーとシリアルの最適化
1:
最適化ツールとライブラリーの活用
5:
マルチコアからメニーコアへスケール

http://www.isus.jp/article/article-parallel/what-is-code-modernization/© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

8

Parallel + SIMD は前進への鍵
インテル® Xeon® プロセッサーとインテル® Xeon Phi™ 製品ファミリーは、両者とも並列性を高めていますインテル®
Xeon® プロ
セッサー 64ビット

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロ
セッサー
コード名

インテル®
Xeon® プロセッサー
コード名

Woodcrest

Nehalem

Westmere

Sandy Bridge EP

Ivy Bridge

Haswell

Skylakeインテル® Xeon
Phi™ x200 プロ
セッサー & コプロ
セッサー (コード
名:

EP

EP

EP

EP

EP

Server1

Knights Landing)インテル® Xeon
Phi™ x100 コプロ
セッサー (コード名:
Knights Corner)

コア

1

2

4

6

8

12

18

28

61

72

スレッド

2

2

8

12

16

24

36

56

244

288

SIMD 幅

128

128

128

128

256

256

256

512

512

512

さらに多いコア

さらに多くのスレッド

より広いベクトル

OpenMP* は parallel + SIMD を前進させる最も重要な機能の 1 つ* ark.intel.com で公開されている出荷済の製品仕様

1.出荷前もしくは計画中。

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

9

内容
 はじめに (OpenMP* が必要とされる背景)
 概要 (OpenMP* とは、歴史、各バージョンの機能概要)
 OpenMP* 4.0 と 4.5 および 5.0 の新機能

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

10

OpenMP* API
ほぼ 20 年来の技術計算/HPC における共有メモリー並列プログラミング(C/C++ と Fortran) 向けの業界標準:• 最新の仕様: OpenMP* 4.5 (2015 年 11 月)• ディレクティブ (C/C++ ではプラグマ) ベース• ベンダーとプラットフォームにわたる移植性 - インテルは OpenMP* ARB (アーキテクチャー・レビュー委員会) のメンバーであり、OpenMP* のサポートを完全にコ
ミット• 各種並列性をサポート: スレッド、タスク、SIMD、オフロード• インクリメンタルな並列処理をサポート
仕様ドキュメント、サンプル、および各種情報は www.openmp.org を参照してください© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

11

OpenMP* の歴史
春に 7 つのベンダーと DOE
は並列ループの開発に同意しOpenMP* ARB を組織。10 月にFortran 向けのOpenMP* 仕様
1.0 がリリース

Fortran と C/C++の統合: 統合した
ものは両方の個別の仕様よりも拡大している。
最初の OpenMP*
国際ワークショップが開催される。これにより、ユーザー
がベンダーと対話できる主要な
フォーラムが生まれた

cOMPunity
OpenMP*
ユーザーグループ
が設立され、北米、
欧州、アジアでワークショップを開催

マイナーな修正
1.1

タスク並列処理導入。OpenMP*
における問題は、タスクの動的特性に対応しつつスレッドベースの特性を維持するのに苦労することだった

C/C++ でmin/max
リダクションを
サポート

1.0
2.0

MPI と OpenMP*を使用した最初のハイブリッド・アプリケーション
の登場

8

1998

8

taskloop、task の優先順位、
doacross ループ、およびロックのヒントをサポート。
非同期オフロードとホスト実行の依存関係をサポート

4.0

4.5

Fortran と C/C++
仕様の統合が開始
される

1.0

1997

3.1

3.0

2.5

アクセラレーター
やコプロセッサー・
デバイスへのオフロード、SIMD
並列処理などをサポート。
OpenMP* の従来の機能を拡張

2.0

1999

8

2000

11

2001

11

2002

11

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

13

13

15

15

17

17

19

22

11

13

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

2013

2014

2015

26

25

26

非常任 ARB

12コンパイラーが OpenMP* をサポートするか?


OpenMP* は最も簡単なマルチスレッド・プログラミング・モデルであるが、コンパイラーが OpenMP* をサポートしている必要がある

OpenMP* をサポートするコンパイラーは、_OPENMP マクロに仕様が公開された年月を数値で返す
仕様のバージョン値

代表的なコンパイラー

OpenMP* 5.0 TR4

201611

インテル® コンパイラー V18.0

OpenMP* 4.5

201511

インテル® コンパイラー V17.0 、 gcc 6.1

OpenMP* 4.0

201307

インテル® コンパイラー V14.0 、 gcc 4.9 (offload 5.1)

OpenMP* 3.1

201107

インテル® コンパイラー V12.1 、 gcc 4.7

OpenMP* 3.0

200805インテル® コンパイラー V11.0 、 gcc 4.4

OpenMP* 2.5

200505インテル® コンパイラー V9.0 、 gcc 4.2© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

13

13

記述している構文が OpenMP* のどの仕様か?

14

http://openmp.org/wp/openmp-specifications/ (英語)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

14

ソースとコンパイラーのバージョンの不一致
ソースコードで使用する OpenMP* の仕様よりもコンパイラーがサポートする OpenMP* 仕様が古い場合、コンパイルエラーとなります_OPENMP マクロでコンパイルを制御:#if _OPENMP >= 201611#pragma omp taskloop reduction(+:sum) private(x)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

15

インテル® OpenMP* ライブラリーのよくある質問









ほかのコンパイラーとのソースとオブジェクトの互換性
インテル® コンパイラーの異なるバージョンを使用するガイドライン
インテル® コンパイラーとその他のコンパイラーを併用するガイドライン
OpenMP* ライブラリーをその他のコンパイラーで使用する際の制限
Visual Studio® でインテルの OpenMP* ライブラリーを使用する際の制限
OS X* で OpenMP* を使用する際の注意
Fortran と C/C++ の混在
インテルの OpenMP* のサポートライブラリー© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

16

ほかのコンパイラーとのソースとオブジェクトの互換性
 インテル® C++ コンパイラーには、次のコンパイラーの OpenMP* サ
ポートとソースおよびオブジェクト・レベルの互換性があります:− Microsoft® Visual C++® 2012 以降のコンパイラー (Windows®)− GCC 4.4.2 以降 (Linux*)− インテル® C++ コンパイラー 10.0 以降

コンパイラーが異なるとサポートされる OpenMP* 仕様も異なります。
アプリケーションが使用する OpenMP* 機能に基づいて、どのバージョンのOpenMP* 仕様が必要かを判断してくださいS© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

17

複数のソースコードの一部のみで OpenMP* を使用する
 もしくは異なるバージョンのコンパイラーでプロジェクトをビルドする場合
main() {printf("OpenMP version %d ¥n", _OPENMP);
printf("OpenMP version %d ¥n", omp());}

インテル® コンパイラー 17.0 でコンパイル

int omp(void){
return _OPENMP;}

インテル® コンパイラー 16.0 でコンパイル

Visual C++® 2015 のコンパイラーでコンパイル

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

18

実行環境を確認する便利な機能
OpenMP* 4.0 以降のライブラリーでは、環境変数 OMP_DISPLAY_ENV が利用できます。 true に設定すると、実行時に情報を表示できます

true、false (デフォルト)、verbose が設定できますS© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

19

インテル® コンパイラーの異なるバージョンを使用する
ガイドライン
リンク時または実行時の問題を回避するには、次の点に注意してください: 現行のインテル® C++ コンパイラーで生成されたオブジェクト・モジュー
ルは、インテル® コンパイラー 10.0 より前のバージョンでコンパイルされたオブジェクト・モジュールとは互換性がありません OpenMP* スタティック・ライブラリーではなく、ダイナミック・ライブラ
リーを使用して、ライブラリーの複数のコピーが 1 つのプログラムにリンクされないようにします (Linux*、OS X*)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

20

インテル® C++ コンパイラーとその他のコンパイラーを併用するガイドライン
リンク時または実行時の問題を回避するには、次の点に注意してください: 常にインテル® C++ コンパイラーの OpenMP* ライブラリーを使用してリンクします。これにより、異なるコンパイラーから OpenMP* ランタイ
ム・ライブラリーの複数のコピーがリンクされるのを防ぎます 可能であれば、すべての OpenMP* ソースを同じコンパイラーでコンパイ
ルします OpenMP* スタティック・ライブラリーではなく、ダイナミック・ライブラ
リーを使用して、ライブラリーの複数のコピーが 1 つのプログラムにリンクされないようにします© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

21

OpenMP* ライブラリーをその他のコンパイラーで使用する際の制限
オブジェクト・レベルの互換性には、threadprivate オブジェクトに次の制限があります:インテル® C++ コンパイラーは threadprivate データを参照する際、デフォルト(/Qopenmp-threadprivate:legacy) で GCC や Microsoft® Visual C++® コンパイラーとは異なる方法を用います

コードで変数を threadprivate と宣言し、インテル® C++ コンパイラーと GCC / VisualC++® コンパイラーの両方でコンパイルする場合、インテル® C++ コンパイラーでコンパイルされたコードと GCC / Visual C++® コンパイラーでコンパイルされたコードでは、同じス
レッドによって参照されていたとしても、異なる場所の変数が参照されます

GCC / Visual C++® コンパイラーでコンパイルされたコードと同じ threadprivate 場所を参照させるには、インテル® C++ コンパイラーでのコンパイル時に、/Qopenmpthreadprivate:compat オプションを使用します© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

22

Visual Studio® でインテルの OpenMP* ライブラ
リーを使用する際の制限
Windows® システムで、Visual Studio® の Visual C++® 開発環境を一部変更すると、
インテル® C++ コンパイラーと Visual C++® を使用して、インテルの OpenMP* ライ
ブラリーを使用するアプリケーションを作成することができます
Microsoft Visual* C++ では、_OPENMP_NOFORCE_MANIFEST シンボルが定義されていなければなりません。定義されていない場合は、vcomp90 dll のマニフェストがインクルードされます。 これにより、ビルドシステムでは問題ありませんが、この DLL が
インストールされていない別のシステムにアプリケーションを移動すると問題が発生しますcl /MD /openmp /c f1.c f2.c
icl /MD /Qopenmp /c f3.c f4.clink f1.obj f2.obj f3.obj f4.obj /out:app.exe /nodefaultlib:vcomp libiomp5md.lib© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

23

OS X* で OpenMP* を使用する際の注意古いバージョンの OS X* プラットフォームでは、インテル® C++ コンパイラーとGCC コンパイラーを併用してコンパイルできます
OS X* 10.9 以降のプラットフォームには、GCC コンパイラーの代わりに Clang コ
ンパイラーが含まれていますが、このコンパイラーは OpenMP* 実装をサポートしていません。 Clang コンパイラーの将来のバージョンでは OpenMP* 実装がサポートされる可能性があります
OS X* 10.9 以降 (Xcode* 5.x 以降) には GCC コンパイラーが含まれていません
が、インテル® C++ コンパイラーと一緒に GCC コンパイラーをインストールできます© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

24

Fortran と C/C++ の混在
 gcc コンパイラー、インテル® C++ コンパイラー、インテル® Fortran コン
パイラーでコンパイルされた OpenMP* オブジェクト・ファイルを混在させることができます インテル® Fortran コンパイラーと gfortran コンパイラーでコンパイルされたオブジェクト・ファイルは混在させることはできません インテル® C++ コンパイラーを使用してアプリケーションをリンクするこができますが、-l オプションを使用して、リンク行で複数の gfortran ライ
ブラリーを渡す必要がありますC ソースとFortran ソースの混在

gfortran -fopenmp -c foo.f
icc -qopenmp -c ibar.c
icc -qopenmp foo.o bar.o -lgfortranbegin -lgfortran© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

25

OpenMP* のサポートライブラリー
OS

ダイナミック・リンク

スタティック・リンク

Linux*

libiomp5.so

libiomp5.a

OS X*

libiomp5.dylib

libiomp5.a

Windows®

libiomp5md.lib
libiomp5md.dll

なし

OpenMP* を使用するオプションは、インテル製マイクロプロセッサーおよび互換マイクロプ
ロセッサーの両方で利用可能ですが、両者では結果が異なります。 両者の結果が異なる可能性のある OpenMP* 構造および機能は、ロック (内部的なものおよびユーザーが利用可能なもの)、SINGLE 構造、バリア (暗黙的および明示的)、並列ループ・スケジュール、リダクション、メモ
リーの割り当て、スレッド・アフィニティー、バインドです© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

26

インテル® コンパイラーの OpenMP* 関連のオプション/Qopenmp ; OpenMP* ディレクティブに基づいてコンパイラーがマルチスレッド・コードを生成するようにします。無効にするには/Qopenmp- を使用します/Qopenmp-stubs ; シーケンシャル・モードで OpenMP* プログラムをコンパイルします。OpenMP* ディレクティブは無視され、OpenMP* ス
タブ・ライブラリーがリンクされます (シーケンシャル)/Qopenmp-lib:<ver> ; リンクする OpenMP* ライブラリーのバージョンを選択します
compat - Microsoft® 互換の OpenMP* ランタイム・ライブラリーを使用します (デフォルト)/Qopenmp-task:<arg> ; サポートする OpenMP* タスクモデルを選択します (廃止予定)
omp - OpenMP* 3.0 タスクをサポートします (デフォルト)。 intel - インテルのタスク・キューイングをサポートします/Qopenmp-threadprivate:<ver> ; 使用する threadprivate 実装を選択します
compat - GCC / Microsoft® 互換のスレッド・ローカル・ストレージを使用します。legacy - インテル互換の実装を使用します (デフォルト)/Qopenmp-simd ; OpenMP* SIMD コンパイルを有効にします。/Qopenmp を指定するとデフォルトで有効になります。無効にするには/Qopenmp-simd- を使用します/Qopenmp-offload[:<kind>] ; target プラグマの OpenMP* オフロードコンパイルを有効にします。このオプションは、インテル® MIC アーキ
テクチャーおよびインテル® グラフィックス・テクノロジーにのみ適用されます。/Qopenmp を指定するとデフォルトで有効になります。無効にするには /Qopenmp-offload- を使用します。target プラグマのデフォルトのデバイスを指定します
host - オフロードの準備はしますが、ターゲットコードをホストシステムで実行します
mic - インテル® MIC アーキテクチャー、gfx - インテル® グラフィックス・テクノロジー© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

27

先に進む前に少し思い出しておきましょう
OpenMP* 3.1 までの機能© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

28

OpenMP* のコンポーネント
ディレクティブ

ランタイム

環境変数



ワークシェア

スレッドの設定

スレッド管理



タスク処理



スレッドの制御

ワークシェア

アフィニティー



ワークシェア



タスク処理



アフィニティー



アクセラレーター

デバイスメモリー



オフロード



アフィニティー



キャンセル



アクセラレーター



同期



キャンセル



キャンセル



SIMD



操作可能



ロック

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

29

OpenMP* の実行モデル•

OpenMP* プログラムはシングルスレッドで処理を開始: マスタースレッド•

ワーカースレッドは並列領域でスポーンされ、マスターとともにスレッドのチームを形成•

並列領域の間ではワーカースレッドはスリー
プ状態になる。 OpenMP* ランタイムがすべてのスレッドの動作を管理

•

マスター
スレッド

コンセプト: フォークジョイン
•

スレーブス
スレーブス
レッド
ワーカー
レッド

シリアル領域
並列領域

スレッド

シリアル領域

並列領域

インクリメンタルな並列処理を許可© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

30

OpenMP* 並列領域: for ワークシェアの例#pragma omp parallel// N=12 を想定#pragma omp for#pragma omp parallel#pragma omp for
for(i = 1, i < N+1, i++)c[i] = a[i] + b[i];

i=1

i=5

i=9

i=2

i=6

i = 10i=3

i=7i = 11i=4

i=8i = 12

暗黙のバリア スレッドには独立したループ反復が割り当てられる スレッドはワークシェア構文の最後で待機© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

31

OpenMP* 並列領域: sections ワークシェアの例
独立したセクションのコードを同時に実行− 実行時間を短縮“非同期実行” で利用される (I/O、オフロードなど)#pragma omp parallel sections{#pragma omp section
phase1();#pragma omp section
phase2();#pragma omp section
phase3();}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

シリアル

並列

32

OpenMP* のリダクション#pragma omp parallel for reduction(+:sum)for(i=0; i<N; i++) {sum += a[i] * b[i];}各スレッドに sum のローカルコピーを作成
sum のすべてのローカルコピーはマージされ、 “グローバル” 変数にストアされるOpenMP* 4.0 と 4.5 でリダクションの概念が拡張された:- ユーザー定義リダクション- リダクション変数は、もやはスカラーの制限がない© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

!$OMP SIMD reduction(+:A)
do I=1,25,4
do J=1,8
A(J) = A(J) +B(I,J)*B(I,J)
end doend do33

OpenMP* 並列領域: single ワークシェアとタスク処理#pragma omp parallel// 8 スレッドを想定{#pragma omp single private(p){…
while (p) {#pragma omp task{
processwork(p);}p = p->next;}}}

ここで 8 スレッドのプールを作成

1 つのスレッドが while ループを実行“while ループ” を実行するスレッドは、
processwork() の各インスタンス向けにタスクを生成© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

34

OpenMP* の同期
 データのアクセス同期
atomic 構文、critical 構文、ロックルーチン
 実行制御barrier 句、master 句、single 句、flush 句、暗黙の同期、nowait 節#pragma omp atomic
x += tmp;#pragma omp critical
x += func(B);#pragma omp parallel{
int id=omp_get_thread_num();#pragma omp masterA[id] = big_calc1(id);#pragma omp barrier
B[id] = big_calc2(id, A);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

35

OpenMP* のデータ属性
 データ環境のデフォルト属性を変更：
default(private | none | shared) // private は Fortran のみ
 構文内のストレージの属性を変更 :shared, firstprivate, private 並列ループ内のプライベート変数の最後の値をループ外の共有変数に転送:
lastprivate© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

36

まとめ：ループとリダクションによる pi プログラム#include <omp.h>
static long num_steps = 100000; double x,step;
void main ()スレッドのチームを生成 ... parallel{
int i;
double x, pi, sum = 0.0;
構文がないと1スレッド以上にはな
step = 1.0/(double) num_steps;
りません#pragma omp parallel{#pragma omp for private(x) reduction(+:sum)for (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);
ループを分割してスレッドに割り当}てます ... sum へリダクション演算}を行うよう設定します。
pi = step * sum;
並列領域内でテンポラリー値を保持
注意 ... ループ・インデックスはデ}するため、各スレッドでプライベートのスカラー変数を使用します© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

フォルトでスレッドローカルです37本日の内容 概要 (OpenMP* とは、歴史、各バージョンの機能概要)
 OpenMP* 4.0 と 4.5 および 5.0 の新機能
 タスク
 omp simd
 オフロード© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

38

新しい機能を説明する前に Combine Construct (結合)シーケンス内の複数のプラグマのショートカットとして使用します。結合された構文は、別の構文内で入れ子になった、もう一方の構文を指定するショートカットとなります。結合された構文は、意味的には2番目の構文を含んでいますが、ほかのステートメントを含まない最初の構文を指定するのと同じです
例：#pragma omp parallel for Composite Construct (複合)複合構文は、2つの構文で構成されますが、入れ子になった構文のいずれかを指定する
同一の意味を持ちません。複合構文では、指定した構文が別々の意味を持ちます
例：#pragma omp for simd

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

39

OpenMP* 5.0 TR6 の機能










複数レベルのメモリーシステムのサポート: OpenMP* 5.0 では、異なる種類のメモリーにデータを配置する直観的なメモリー割り当てメカニズムがサポートされます
複雑なデータ構造のディープコピーをサポート: TR6 ではユーザー定義のマッパーが追加されます。オブジェ
クト指向のデータ構造を、アクセラレーター・デバイスに正しくコピーする構成可能なメカニズムを提供します
OpenMP* device 構文の追加拡張: その他、アクセラレーター向けの OpenMP* サポートの主要機能として、ユニファイド共有メモリーのサポート、デバイス固有の機能実装を使用する能力、明示的なデータマッピングの制御、および実行時のデバイスオフロードのオーバーライドなどが考えられています
記述的なループの最適化サポート: 並行性構造は、関連するループ入れ子のすべての反復が任意の順番で同時実行されることを示唆します。これは、コンパイラーによる実装固有の最適化により実現されます
OpenMP* アプリケーションの改善されたデバッグ機能をサポート: TR6 では OMPD を追加します。これはサードパーティー・ツール・インターフェイスによる直観的な OpenMP* コードのデバッグを可能にし、OpenMP* パフォーマンスの詳細な解析をサポートするため TR4 で追加されたファーストパーティー・ツール・インターフェイスである OMPT を補完します
タスク依存の新しい形式: 新しいメカニズムは、(1) セット中で相互排他を必要とするタスクセットと、他のタスクに関連する順序付け、および (2) 動的に発生する依存性のセットとタスクをサポートします
大きなメモリーモデルの柔軟性: OpenMP* 5.0 は、低レベルのメモリー同期の最適化を可能にする acquire(取得)/release (解放) セマンティクスをサポートします© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

40

OpenMP* タスクに関する拡張
task、taskwait、taskyield© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

41

タスクを使用しない OpenMP* ワークシェアの問題
OpenMP* ワークシェア構文が上手く構成されていない問題の例: 並列化された領域からインテル® MKL の dgemm を呼び出す
void example(){#pragma omp parallel{
compute_in_parallel(A);compute_in_parallel_too(B);// dgemm はパラレルもしくはシリアル
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
m, n, k, alpha, A, k, B, n, beta, C, n);}}

次のいずれかの状態となる:
 オーバーサブスクライブ (dgemm が内部で並列化されている場合)
 OpenMP* のオーバーヘッドによるパフォーマンスの低下、または
 部分行列に dgemm を適用するため、周辺コードが必要になる© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

42

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

43

OpenMP* のタスク処理: 簡単な例
#pragma omp parallel// 8 スレッドを想定{#pragma omp single private(p){…
while (p) {#pragma omp task{
processwork(p);}p = p->next;}}}

OpenMP* 3.1 の機能

ここで 8 スレッドのプールを作成

1 つのスレッドが while ループを実行“while ループ” を実行するスレッドは、
processwork() の各インスタンス向けにタスクを生成© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

44

OpenMP* 3.1 の機能

タスクによるフィボナッチ数列
int fib ( int n ){int x,y;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;}n は両方のタスクでfirstprivate

x と y は共有
最良の解決策sum を計算するため x とy 両方の値が必要© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

45

タスク動作を制御する例

OpenMP* 3.1 の機能#pragma omp task{…
while( (status = omp_test_lock(lock)) != true){ // ロックが取得できるまでループ#pragma omp taskyield}…
omp_unset_lock(lock);}while ループで OpenMP ロックの取得を待機していますが、タスクは消費されます© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

46

OpenMP* 4.0 の機能

task 間の変数の依存関係生成されたタスクの実行順序は不定、参照する変数に依存関係がある場合、意図する結果が得られないことがある
タスクが使用する変数を depend 節
で依存関係 in、out、inout を指定できるようになりました
フロー依存(out,in)、アンチ依存(in,out)、出力依存(out,out) を制御

int val=0;
int main(){#pragma omp parallel num_threads(3){#pragma omp single{#pragma omp task depend(out:val)
val = 100;
#pragma omp task depend(in:val)
val += 1000;}}
printf("Value is %d¥n", val);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

47

タスク依存関係 - 「OMP フローグラフ」
void blocked_cholesky( int NB, float *A[NB][NB] ) {int i, j, k;for (k=0; k<NB; k++) {#pragma omp task depend(inout:A[k][k])spotrf (A[k][k]) ;for (i=k+1; i<NB; i++)#pragma omp task depend(in:A[k][k])depend(inout:A[k][i])strsm (A[k][k], A[k][i]);// 末端の部分行列を更新
for (i=k+1; i<NB; i++) {for (j=k+1; j<i; j++)#pragma omp task depend(in:A[k][i],A[k][j])depend(inout:A[j][i])sgemm( A[k][i], A[k][j], A[j][i]);#pragma omp task depend(in:A[k][i])depend(inout:A[i][i])ssyrk (A[k][i], A[i][i]);}}}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

OpenMP* 4.0 の機能* イメージのソース: BSC

48

Do-across ループ並列

OpenMP* 4.5 の機能依存性はループ反復間で生じる

以下のコードは、ループ伝搬後方依存がある
void lcd_ex(float* a, float* b, size_t n, int m, float c1, float c2) {size_t K;
ループを並列化するとき、ループ伝搬依存がないと
きは、Doallループとして並列化し、ループ伝搬依存#pragma omp parallel for ordered(1)があるときは、同期操作がある Doacrossループとfor (K = 17; K < n; K++) {して並列化します#pragma omp ordered depend(sink: K–17) そのため、ordered 句を伴う入れ子になった Do
Across ループをサポートするため、depend 節のa[K] = c1 * a[K - 17] + c2 * b[K];source と sink 依存性タイプがサポートされまし#pragma omp ordered depend(source)
た。
}
これにより、構造化された依存性を持つループを並列化できるようになりました
}

0

1

2

3

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

49

OpenMP* 4.5 の機能

taskloop 句
OpenMP* task を使用してループを並列化 (Fortran と C/C++) :#pragma omp taskloop [simd] [節]for/do ループ
ループをチャンクへ分割

オプションの grainsize と num_tasks 節でタスクの生成を制御インテル® Cilk™ Plus の“cilk_for” に類似

それぞれのループチャンク向けにタスクを生成void CG_mat(Matrix *A, double *x, double *y){// ...
#pragma omp taskloop
private(j,is,ie,j0,y0) ¥grainsize(500)for (i = 0; i < A->n; i++) {y0 = 0;is = A->ptr[i];ie = A->ptr[i + 1];
for (j = is; j < ie; j++) {j0 = index[j];y0 += value[j] * x[j0];}y[i] = y0;// ...
}

4.5 ではまだ気軽に taskloop は使えない …

// ...

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

50

OpenMP* のタスク処理: さらに ...
キャンセル (cancel)• OpenMP* 4.0 以前では、並列実行を途中でキャンセルできなかった– コード領域は常に最後まで実行された (もしくはすべて実行しないか)• OpenMP* 4.0 の cancel 句は OpenMP* 領域の中断を可能にする

タスクグループ (taskgroup)• 次のような処理のため、タスクを論理的にグループ化する– 同期– キャンセル© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

51

OpenMP* 4.0 の機能

cancel 句

指定された構文タイプの最も内側の並列領域の要求をキャンセルします。if 文、while
文、do 文、switch 文とラベルの後には指定できません：#pragma omp cancel [構文タイプ] [[,] if 節]
構文タイプ： parallel、sections、for、taskgroupif 節： if(スカラー式)
注：構文に到達したとき、デッドロックを引き起こす可能性があるロックやその他のデータ構造を解放する必要があります。ブロックされたスレッドは取り消すことができません© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

52

cancellation point 句

OpenMP* 4.0 の機能指定された構文タイプの最も内側の並列領域のキャンセルが要求された場合に、キャンセルをチェックする位置を指定：#pragma omp cancellation point [構文タイプ]
構文タイプ： parallel、sections、for、taskgroup
制約事項：• この構文は、実行文が許可されている場所にのみ追加できます• if 文のアクション文として使用したり、プログラムで参照されるラベルの実行文として使用することはできません© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

53

#define N 10000

cancel 句の例

void example() {std::exception *ex = NULL;#pragma omp parallel shared(ex){#pragma omp forfor (int i = 0; i < N; i++) {// no 'if' that prevents compiler optimizations
try {causes_an_exception();}catch (std::exception *e) {// 後で例外を処理するため ex にステータスをストア#pragma omp atomic write
ex = e;#pragma omp cancel for // for ワークシェアリングをキャンセル}}
if (ex) // 例外が発生したら parallel 構文をキャンセル#pragma omp cancel parallel
phase_1();#pragma omp barrier
phase_2();}// 例外がワークシェア・ループ内でスローされている場合は継続
if (ex)// ex の例外処理} // parallel のおわり

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

OpenMP* 4.0 の機能

例外をキャッチしたら for ワー
クシェア並列処理をキャンセル

例外をキャッチしたら parallel
並列処理をキャンセル

54

cancellation point 句の例
subroutine example(n, dim)
integer, intent(in) :: n, dim(n)integer :: i, s, err
real, allocatable :: B(:)
err = 0!$omp parallel shared(err)! ...
!$omp do private(s, B)
do i=1, n!$omp cancellation point doallocate(B(dim(i)), stat=s)
if (s .gt. 0) then!$omp atomic write
err = s!$omp cancel do
endif
!
...
! deallocate private array B
if (allocated(B)) thendeallocate(B)
endif
enddo
!$omp end parallel
end subroutine

OpenMP* 4.0 の機能

ほかのスレッドはこの位置でキャンセルをチェック

allocate 文からエラーが返されたときにcancel do をアクティブにします© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

55

OpenMP* 4.0 の機能

taskgroup 構文

taskgroup 構文は、現在のタスクの子タスク（孫タスク）の完了を待機することを指示できます
int main(){
int i; tree_type tree;
init_tree(tree);#pragma omp parallel#pragma omp single{#pragma omp task
start_background_work();for (i = 0; i < max_steps; i++) {#pragma omp taskgroup{#pragma omp task
compute_tree(tree);} // このステップの tree トラバースを待機check_step();}} // ここで start_background＿work の完了を待機
print_results();
return 0;}

この 2 つのタスクは同時に実行され、start_background_work() はcompute_tree() の同期の影響を受けない
なぜ taskwait が使用できないのか？

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

56

task 句の priority 節

OpenMP* 4.5 の機能

priotity 節は生成されたタスクの優先度に関するヒントです。実行準備が整っている
タスクの中で、優先度の高いものより優先度の高いタスク (数値が大きいもの) を実行します：#pragma omp task priority[優先順位]
優先順位: タスクの実行順序のヒントを提供する負でない数値のスカラー式です

この機能はバージョン 17 では未サポートです© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

57

OpenMP* 5.0 の task 機能強化OpenMP* 5.0 の機能

task、taskgroup、taskloop 句でのリダクション演算のサポート
taskloop 構文で collapse 節をサポート
taskwait 句に depend 節が指定できるようになりました
depend 節に排他 inout セットをサポートする mutexinoutset タイプが追加されましたhttps://www.isus.jp/products/c-compilers/openmp-50-support-in-180/https://www.isus.jp/products/c-compilers/openmp_tr6_new_features/https://www.isus.jp/hpc/pu27-01-present-and-future-of-openmp/© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

58

taskloop でのリダクション演算

OpenMP* 5.0 の機能

OpenMP 4.5 までは次のようなリダクションを含むワークシェア構文を taskloopに書き換えることは困難でした#pragma omp parallel#pgarma omp single#pragma omp paralleltaskloopfor
reduction(+:sum)private(x)reduction(+:sum)private(x)for (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}
pi = step * sum;
OpenMP* 5.0 では、taskloop でリダクション演算が利用できます© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

59

OpenMP* 5.0 の機能

taskgroup を適用して次のように記述できます
task_reduction と in_reduction を使用#pragma omp parallel#pragma omp single#pragma omp taskgroup task_reduction(+:sum)#pragma omp taskloop in_reduction (+:sum) private(x)for (i=0;i< num_steps; i++){x = (i+0.5)*step;sum = sum + 4.0/(1.0+x*x);}
pi = step * sum;© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

60

task_reduction と in_reduction

OpenMP* 5.0 の機能

int find_minimum(list_t * list) {in_reduction が指定されないタスク
int minimum = INT_MAX;
list_t * ptr = list;の変数はリダクションに参加しません#pragma omp parallel#pragma omp single#pragma omp taskgroup task_reduction(min:minimum){for (ptr = list; ptr ; ptr = ptr->next) {#pragma omp task firstprivate(ptr) in_reduction(min:minimum){
int element = ptr->element;
minimum = (element < minimum) ? element : minimum;}}}
return minimum;}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

61

taskloop 構文中での collapse 節

OpenMP* 5.0 の機能

void taskloop_example() {#pragma omp taskgroup{#pragma omp task
long_running_task() // 同時に実行可能#pragma omp taskloop collapse(2) grainsize(500) nogroupfor (int i = 0; i < N; i++)for (int j = 0; j < M; j++)loop_body();

この構文は、ループの反復空間をチャンクに分割し、それぞれのチャンクに対して 1
つのタスクを生成します。

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

62

taskwait 句での depend 節
main ( ){int x = 2;#pragma omp task // shared(x) mergeable{x++;}#pragma omp taskwait // depend(in:x)
printf("%d¥n",x); // prints 3}

OpenMP* 5.0 の機能

V18 では未実装

2 つのタスクのデータスコープ
は異なりますtaskwait 構文に depend 節が指定される場合、マージ可能なインクルード・タスクを生成する空の構造化ブロックを持つ task 構文であるかのように動作します© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

63

相互排他を必要とするタスクセット
mutexinoutset 依存関係タイプ
int val=0;

OpenMP* 5.0 の機能

V18 では未実装

タスク⽣成構⽂に mutexinoutset 依存関係タイプを持つ
depend 節のリスト項⽬がある場合、異なるタスク⽣成構⽂のmutexinoutset 依存関係タイプを持つ depend 節のリスト項⽬と同じストレージである必要があります。両⽅の構⽂は兄弟タスクを⽣成し、兄弟タスクは排他タスクとなります

int main(){#pragma omp parallel{#pragma omp single{#pragma omp task depend(mutexinoutset:val)…
#pragma omp task depend(mutexinoutset:val)…
}}printf("Value is %d¥n", val);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

64

明示的な SIMD プログラミング・モデル© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

65

なぜ SIMD 拡張? OpenMP* 4.0 以前
コンパイラー・ベンダー固有の拡張機能をサポート
 プログラミング・モデル (例えば、インテル® Cilk™ Plus) コンパイラー・プラグマ (例えば、 #pragma vector)
 低レベルの構文 (例えば、 __mm_add_pd() 組込み関数)#pragma omp parallel for#pragma vector always#pragma ivdepfor (int i = 0; i < N; i++) {a[i] = b[i] + ...;}

コンパイラーが "正しい"ことをするのを信頼する必要がある© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

66

ベクトル化に影響するプログラムの要素
ループ伝搬依存不明なループカウント

DO I = 2, N
A(I) = A(I-1) + B(I)ENDDO

struct _x { int d; int bound; };void doit(int *a, struct _x *x){
for(int i = 0; i < x->bound; i++)a[i] = 0;}関数呼び出しfor (i = 1; i < nx; i++) {x = x0 + i * h;sumx = sumx + func(x, y, xp);}

ポインター・エイリアシング
void scale(int *a, int *b){for (int i = 0; i < 1000; i++)b[i] = z * a[i];}さらに ....

間接メモリーアクセス
DO i=1, N
A(B(i)) = A(B(i)) + C(i)*D(i)
ENDDO

外部ループ
DO I = 1, MAX
DO J = I, MAX
D(I,J) = D(I,J) + 1;
ENDDO
ENDDO

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

67

自動ベクトル化: シリアル・セマンティクスによる制限
コンパイラーは以下をチェックする:
•
•
•
•
•

for(i = 0; i < *p; i++) {A[i] = B[i] * C[i];sum = sum + A[i];}*p はループ不変か?
A[]、B[]、C[] はオーバーラップしているか?
sum は、B[] および/または C[] とエイリアスされているか?
演算操作の順番は重要か?
ターゲット上のベクトル演算はスカラー演算よりも高速であるか?
(ヒューリスティックの評価)

自動ベクトル化は言語規則によって制限される: 意図することを表現できない© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

68

OpenMP* 4.0 の機能

SIMD プラグマ/ディレクティブによる明示的なベクトル・プログラミング#pragma omp simd reduction(+:sum)
プログラマーの主張:
•
•
•
•
•
•

for(i = 0; i < *p; i++) {A[i] = B[i] * C[i];sum = sum + A[i];}*p はループ不変
A[] は、B[] および C[] とオーバーラップしない
sum は、B[] および C[] とエイリアスされていない
sum はリダクションされる
コンパイラーが効率良いベクトル化のため順番を入れ替えることを許容する
ヒューリスティックの評価が利点をもたらさなくても、ベクトル化されたコードを生成する

明示的ベクトル・プログラミングにより何を意図するかを表現できる!
© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

69

OpenMP* 4.0 の機能

プログラマーの意図: ベクトルループ中のデータ
float sum = 0.0f;
float *p = a;
int step = 4;
#pragma omp simdfor (int i = 0; i < N; ++i) {sum += *p;p += step;
}

•
•
•
•

+= 操作を行う 2 つの行は、互いに異なる意味を持つ
プログラマーは、この違いを表現する必要がある
コンパイラーは、異なるコードを生成する必要がある
変数 i、p、そして step は、それぞれ異なる意味を持つ© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

70

OpenMP* 4.0 の機能

プログラマーの意図: ベクトルループ中のデータ
float sum = 0.0f;
float *p = a;
int step = 4;
#pragma omp simd reduction(+:sum) linear(p:step)for (int i = 0; i < N; ++i) {sum += *p;p += step;
}

•
•
•
•

+= 操作を行う 2 つの行は、互いに異なる意味を持つ
プログラマーは、この違いを表現する必要がある
コンパイラーは、異なるコードを生成する必要がある
変数 i、p、そして step は、それぞれ異なる意味を持つ© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

71

OpenMP* SIMD ディレクティブ

OpenMP* 4.0 の機能

Pragma SIMD:
simd 構文は、ループを SIMD ループに変換することを明示的に指示 (それぞれのルー
プ反復は、SIMD 命令を使用して同時に実行される)
シンタックス:#pragma omp simd [節 [,節]…]for ループ
for ループは「標準ループ形式」でなければいけない

リダクション変数には、ランダム・アクセス・イテレーターが必要 (C++ の整数型やポイ
ンター型)
 インダクション変数のテストとデクリメントの制限
 ループを実行する前に反復回数が判明していること
 …
© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

72

OpenMP* SIMD ディレクティブの節

OpenMP* 4.0 の機能
OpenMP* 4.5 の機能•

safelen(レングス):
SIMD 命令によって同時に 2 つの反復が実行できない場合、この値でより大きな論理的反復空間を指定します•private(v1, v2, …): 変数は各ループ反復でプライベート•

lastprivate(…): 最後反復の値がグローバル変数にコピーされる•

linear(v1: ステップ1, v2: ステップ2, …)
このスカラーループの各反復では、v1 はステップ 1 でインクリメントされる
そのため、ベクトルループではステップ 1 * ベクトル長になる•

reduction(演算子: v1, v2, …): 変数 v1、v2、… は、演算子によるリダクション変数•

collapse(n): 入れ子になったループを崩して 1 つの大きなループに再構成する•

aligned(v1:ベース, v2:ベース, …): 変数 v1、v2、… がアライメントされていることを通知(デフォルトはアーキテクチャー固有のアライメント)• simdlen (レングス): 正の整数式で関数の同時引数の数を指定します© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

73

OpenMP* SIMD の例

OpenMP* 4.0 の機能

データの依存性と間接的な制御フローの依存性がないことを明示してアライメントを指示
void vec1(float *a, float *b, int off, int len){#pragma omp simd safelen(32) aligned(a:64, b:64)
for(int i = 0; i < len; i++){a[i] = (a[i] > 1.0) ?
a[i] : b[i];a[i + off] * b[i];}}LOOP BEGIN at simd.cpp(4,5)
remark #15388: ベクトル化のサポート: 参照 a にアラインされたアクセスが含まれています。[ simd.cpp(6,9) ]remark #15388: ベクトル化のサポート: 参照 b にアラインされたアクセスが含まれています。[ simd.cpp(6,9) ]…
remark #15301: OpenMP SIMD LOOP がベクトル化されました。
…
LOOP END© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

74

ループ・スケジュールの SIMD 修飾子OpenMP* 4.5 の機能

void sprod(float *a, float *b, int n) {float sum = 0.0f;#pragma omp parallel for simd reduction(+:sum) schedule(simd:static,5)for (int k=0; k<n; k++)sum += a[k] * b[k];return sum;}

並列化

スレッド 0スレッド 1スレッド 2

ベクトル化

新しい SIMD 修飾子は、コンパイラーとランタイムが SIMD レジスターのレングスにチャンクサイズを合わせることを可能にする•

新しいチャンクサイズは、chunk_size/simdlen * simdlen•

インテル® AVX2: 新しいチャンクサイズは、8 以上の 2 の累乗•

インテル® SSE: 新しいチャンクサイズは、4 以上の 2 の累乗© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

75

75

SIMD 対応関数

OpenMP* 4.0 の機能

SIMD 対応関数 (以前は declare simd 構文と呼ばれていた):
SIMD ループから呼び出される関数が、SIMD命令を使用した処理を行う複数のバージョンを生成することを有効にすることを指示。 [OpenMP* 4.0 の API: 2.8.2]
シンタックス:#pragma omp declare simd [節 [,節]…]関数定義または宣言
目的:
スカラー計算 (カーネル) としてワークを表現し、コンパイラーにベクトルバージョンを生成させる。ベクトルサイズは移植性を考慮してコンパイル時に指定できる(インテル® SSE、インテル® AVX、インテル® AVX-512)
注意:
関数定義と関数宣言 (ヘッダーファイル) の両方で同じように指定する必要がある© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

76

SIMD 対応関数の節

OpenMP* 4.0 の機能• simdlen(len)len は 2 の累乗: 引数ごとに多くの要素を渡すことを可能にする (デフォルトは実装依存)• linear(v1: ステップ 1, v2: ステップ 2, …)
引数 v1、v2、 … を SIMD レーンにプライベートに定義し、ループのコンテキストで使用される
場合リニアな関係を持ちます (ステップ 1、ステップ 2、…)

• uniform(a1, a2, …)
引数 a1、a2、… は、ベクトルとして扱われません (SIMD レーンに定数がブロードキャストされる)• inbranch, notinbranch: SIMD 対応関数は分岐から呼び出される、または呼び出されない• aligned(a1:ベース, a2:ベース, …): 引数 a1、a2、… がアライメントされていることを通知 (デフォ
ルトはアーキテクチャー固有のアライメント)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

77

OpenMP*: SIMD 対応関数のベクトル化

OpenMP* 4.0 の機能#pragma omp declare simd
float min(float a, float b) {return a < b ? a : b;}

vec8 min_v(vec8 a,vec8 b){
return a < b ? a : b;}#pragma omp declare simd
float distsq(float x, float y) {return (x - y) * (x - y);}vec8 distsq_v(vec8 x,vec8 y) {return (x - y) * (x - y);}void example() {#pragma omp parallel for simd}

vd = min_v(distsq_v(va, vb), vc)

for (i=0; i<N; i++) {d[i] = min(distsq(a[i], b[i]), c[i]);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

78

SIMD 対応関数：Linear/ Uniform

OpenMP* 4.0 の機能• なぜこれらが必要なのか?
• uniform もしくは linear が省略されると、関数への引数はベクトルとして扱われる#pragma omp declare simd uniform(a) linear(i:1)
void foo(float *a, int i):a は、ポインターi は、 int [i, i+1, i+2, …] のシーケンス
a[i] は、ユニットストライドなロード / ストア ([v]movups)

dec_simd2.c#pragma omp declare simd
void foo(float *a, int i):a は、ポインターのベクトル
i は、int のベクトルa[i] は、スキャッター/ギャザーとなる

参考文献： http://software.intel.com/en-us/articles/usage-of-linear-and-uniform-clause-in-elemental-function-simd-enabled-function-clause© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

79

OpenMP* 4.0 の機能

SIMD 対応関数：呼び出しの依存性
呼ばれる側

dec_simd3.c#pragma omp declare simd uniform(a),linear(i:1),simdlen(4)void foo(int *a, int i){
std::cout<<a[i]<<"¥n";}

呼び出し側#pragma omp simd safelen(4)for(int i = 0; i < n; i++)foo(a, i);ベクトル化レポート
testmain.cc(5):(col. 13) remark: OpenMP SIMD LOOP がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました

参考文献：http://software.intel.com/en-us/articles/call-site-dependence-for-elemental-functions-simd-enabled-functions-in-c© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

80

SIMD 対応関数：呼び出しの依存性

OpenMP* 4.0 の機能

呼ばれる側#pragma omp declare simd uniform(a),linear(i:1),simdlen(4)void foo(int *a, int i){
std::cout<<a[i]<<"¥n";}

呼び出し側#pragma omp simd safelen(4)for(int i = 0; i < n; i++) foo(a, i);#pragma omp simd safelen(4)for(int i = 0; i < n; i++){k = b[i]; // k はリニアでない
foo(a, k);}

ベクトル化レポート
testmain.cc(14):(col. 13) remark: OpenMP SIMD LOOP がベクトル化されました
testmain.cc(21):(col. 9) remark: 関数 '?foo@@YAXPEAHH@Z' の適切なベクトルバージョンが見つかりません
testmain.cc(18):(col. 1) remark: OpenMP SIMD LOOP がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

81

SIMD 対応関数：複数のベクトル定義

OpenMP* 4.0 の機能

呼ばれる側#pragma omp declare simd uniform(a),linear(i:1),simdlen(4)#pragma omp declare simd uniform(a),simdlen(4)void foo(int *a, int i){
std::cout<<a[i]<<"¥n";}

呼び出し側#pragma omp simd safelen(4)for(int i = 0; i < n; i++) foo(a, i);#pragma omp simd safelen(4)for(int i = 0; i < n; i++){k = b[i]; // k はリニアでない
foo(a, k);}

ベクトル化レポート
testmain.cc(14):(col. 13) remark: OpenMP SIMD LOOP がベクトル化されました
testmain.cc(18):(col. 1) remark: OpenMP SIMD LOOP がベクトル化されました
header.cc(3):(col. 24) remark: FUNCTION がベクトル化されました© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

82

SIMD 対応関数を使用する際の制限事項

OpenMP* 4.0 の機能• 引数は 1 つの uniform または linear 句に記述できます• linear 句に constant-linear-step 式が指定される場合、正の整数式でなければな
りません• 関数やサブルーチンは、構造化ブロックでなければなりません• SIMD ループから呼び出される関数やサブルーチンは、OpenMP* 構造を実行する
ことはできません• 関数やサブルーチンの実行では、SIMD チャンクの同時反復の実行を変更する副作用があってはなりません• 関数の内側から外側へ、または外側から内側へ分岐するプログラムは不適合です• C/C++: 関数は、longjmp や setjmp を呼び出してはなりません© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

83

ボルテックス・コード: 外部ループのベクトル化#pragma omp simd// SIMD 関数の呼び出し側での外部ループのための simd pragma
for (int i = beg*16; i < end*16; ++i)
particleVelocity_block(px[i], py[i], pz[i],destvx + i, destvy + i, destvz + i, vel_block_start, vel_block_end);#pragama
staticomp declare simd linear(velx,vely,velz) uniform(start,end) aligned(velx:64, vely:64, velz:64)

particleVelocity_block(const float
float *velx,for (int j = start; j < end; ++j) {const float del_p_x = posx - px[j];

}

}

void

posx, const float posy, const float posz,
float *vely, float *velz, int start, int end) {

const

float

del_p_y= posy - py[j];

const

float

del_p_z= posz - pz[j];

const

float

dxn= del_p_x * del_p_x + del_p_y * del_p_y + del_p_z * del_p_z +pa[j]* pa[j];

const

float

dxctaui= del_p_y * tz[j] - ty[j] * del_p_z;

const

float

dyctaui= del_p_z * tx[j] - tz[j] * del_p_x;

const

float

dzctaui= del_p_x * ty[j] - tx[j] * del_p_y;

const

float

dst

= 1.0f/std::sqrt(dxn);

const
*velx
*vely
*velz

float

dst3

= dst*dst*dst;-= dxctaui * dst3;-= dyctaui * dst3;-= dzctaui * dst3;

KNC✝ のパフォーマンス改善
2 倍以上
内部ループから外部ループのベクトル化✝開発コード名© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

84ベクトル化の効率を評価する
 完全な最適化オプションでビルドして実行 同じオプションに以下を追加してビルド：/Qopenmp-simd- (-qopenmp-simd-)
 2 つの結果を比較する
スピードアップ(S) = 実行時間(no-vec) / 実行時間(vec) スピードアップは 1.0 以上であること。スピードアップの上限：
 単精度： インテル® SSE では S <= 4、インテル® AVX では S <= 8、インテル® AVX-512 では S <= 16 倍精度： インテル® SSE では S <= 2、インテル® AVX では S <= 4、インテル® AVX-512 では S <= 8
 高い値が良い、上限を目指す 例外：インテル® MKL を呼び出しているコード領域は、効率良くベクトル化され、将来にわたって有効！
© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

85

OpenMP* 5.0 の simd 機能強化

OpenMP* 5.0 の機能

V18 では未実装

 simd 構文に nontemporal 節が追加されました nontemporal 節は、リスト項目のトレージ位置へのアクセスが、ループ反復間で低い時間的な局所性を持つことを指定します simd 構文で collapse 節をサポートしました simd 構文でも入れ子のループを 1 つのループに展開できるようになりました simd 構文で atomic 節が利用できるようになりました© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

86

GPU、コプロセッサーおよび SoC 向けの
Target (または Offload) 拡張© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

87

データ共有/マッピング : 共有もしくは分散メモリー
分散メモリー

共有メモリー
メモリー

メモリー X

プロセッ
サー X

コプロセッ
サー Y

キャッシュ

キャッシュ

A

A

コプロセッサー Y

A

スレッドは共有メモリーへアクセスできる
 共有データ向けに
 各スレッドは、同期バリア間の共有メモリー(レジスター、キャッシュなど) の一時的なビューを保持できるスレッドはプライベート・メモリーを持つ
 プライベート・データ向けに
 各スレッドは、実行される各タスクのローカル・データ・スタックを保持できるプロセッサーX

例: インテル® Xeon Phi™
コプロセッサーメモリー Y

キャッシュ
A

A

A

デバイスデータ環境に対応する変数は、元の変数とストレージを共有

対応する変数への書き込みは、元の変数の値を更新© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

88

OpenMP* デバイスモデル
OpenMP* は、アクセラレーターとコプロセッサーをサポート
デバイスモデル: 1 つのホスト
 同種の複数のアクセラレーター/コプロセッサー/GPGPU

プロセッサー/コプロセッサー/GFX/GPGPU© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

ホスト

89

インテル® Xeon Phi™ コプロセッサーへ
オフロードする際の注意点
要件:
1. インテル® MPSS を入手する
http://www.isus.jp/hpc/software-stack-mpss/
2. インテル® コンパイラー14.0 以降を入手する
3. インテル® MPSS 環境を設定する

Windows® 環境でビルドのみ行う場合、Intel® Xeon Phi™ coprocessor
essentials のみをインストール© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

90

OpenMP* 4.0/4.5 Target 拡張
ターゲットデバイス上で実行するためコードをオフロード

omp target [節[[,] 節],…] [nowait]

アクセラレーション向けのワークシェア


構造化ブロックomp declare target

omp distribute [節[[,] 節],…]for ループ

ターゲットデバイスへ変数をマップ



omp teams [節[[,] 節],…]構造化ブロック[関数定義または宣言]

赤字が OpenMP* 4.5 での拡張

map ([マップタイプ修飾子][マップタイプ:] リスト)


マップタイプ := alloc | tofrom | to | from |release | delete

マップタイプ修飾子: always

omp target [enter | exit] data [節[[,] 節],…]構造化ブロック

omp target update [節[[,] 節],…]

omp declare target

ランタイム・サポート・ルーチンvoid omp_set_default_device(int dev_num )
int omp_get_default_device(void)
int omp_get_num_devices(void);
int omp_get_num_teams(void)
int omp_get_team_num(void);Int omp_is_initial_device(void);
環境変数

OMP_DEFAULT_DEVICE を介してデフォルトデバイスを制御
負ではない整数値[関数定義または宣言]© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

91

オフロードとデバイスデータのマッピング
ホスト

target 構文を使用して

ホストからターゲット
デバイスへ制御を転送
ホストとターゲットデバイスのデータ環境間で変数を
マップ

デバイス
1

pA

alloc(…)

2
to(…)

4
from(…)#pragma omp target ¥map(alloc:...)¥
map(to:...)¥
map(from:...){ ...}
3

ホストスレッドはターゲット (オフロードされた) タスクをスポーン
 同期オフロード (スレッドはターゲットタスクを待機) 非同期オフロード (スレッドはターゲットタスクを待機することなく継続)
map 節は、データ環境の元の変数をデバイスデータ環境の対応する変数にどのようにマップするかを決定する© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

92

例: target + map#define N 1000
#pragma omp declare target
float p[N], v1[N], v2[N];#pragma omp end declare target
extern void init(float *, float *, int);
extern void output(float *, int);
void vec_mult(){
int i;
init(v1, v2, N);グローバル変数がプログラム全体でデバ
イスデータ環境にマップされることを示す

ホストとデバイス間で一貫性を保つため target update を使用する#pragma omp target update to(v1, v2)#pragma omp target#pragma omp parallel for simdfor (i=0; i<N; i++)p[i] = v1[i] * v2[i];parallel for simd ループがターゲッ
トへオフロードされることを示す#pragma omp target update from(p)output(p, N);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

93

例: OpenMP* 4.0 での非同期オフロード実装
OpenMP* 4.0 の target 構文は、非同期オフロードをサポートするため既存の OpenMP* の機能 (task) を活用できる

ターゲット
ホスト

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

ホスト#pragma omp parallel sections{#pragma omp task{
#pragma omp target map(in:input[:N]) map(out:result[:N])#pragma omp parallel forfor (i=0; i<N; i++) {result[i] = some_computation(input[i], i);}}#pragma omp task{
do_something_important_on_host();}}94

例: OpenMP* 4.5 での非同期オフロード実装
非同期オフロードをサポートするため target 構文に nowait 節が追加された。taskwait で待機

ターゲット
ホスト

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

ホスト#pragma omp parallel sections{#pragma omp target map(in:input[:N]) map(out:result[:N]) nowait#pragma omp parallel forfor (i=0; i<N; i++) {result[i] = some_computation(input[i], i);}// 以下をホストで非同期に実行
do_something_important_on_host();#pragma omp taskwait}

95

例: teams+parallel for (SAXPY – アクセラレーター向けコード)
int main(int argc, const char* argv[]) {float *x = (float*) malloc(n * sizeof(float));*y = (float*) malloc(n * sizeof(float));floatSAXPY// Define scalars n, a, b & initialize x, y#pragma omp target data map(to:x[0:n]){#pragma omp target map(tofrom:y)#pragma omp teams num_teams(num_blocks) thread_limit(nthreads)
すべてが同じことを行う
for (int i = 0; i < n; i += num_blocks){
for (int j = i; j < i + num_blocks; j++) {y[j] = a*x[j] + y[j];} }}1 つ以上のループの反復を実行
するスレッドチームを生成。
マスタースレッドで実行を開始

free(x); free(y); return 0;}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

96

例: teams+parallel for (SAXPY – アクセラレーター向けコード)
int main(int argc, const char* argv[]) {float *x = (float*) malloc(n * sizeof(float));float *y = (float*) malloc(n * sizeof(float));// Define scalars n, a, b & initialize x, y#pragma omp target data map(to:x[0:n]){#pragma omp target map(tofrom:y)#pragma omp teams num_teams(num_blocks) thread_limit(nthreads)

 SAXPYコプロセッサー/アクセラレーター
すべてが同じことを行う#pragma omp distributefor (int i = 0; i < n; i += num_blocks){

1 つ以上のループの反復をすべてのスレッドチームのマスタースレッド
間で共有するかどうかを指定

ワークシェア (barrier なし)#pragma omp parallel forfor (int j = i; j < i + num_blocks; j++) {ワークシェア (barrier あり)

distribute されたスレッドのチー
ムで、ループ反復をワークシェア

y[j] = a*x[j] + y[j];} }} free(x); free(y); return 0; }© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

97

OpenMP* と OpenACC* の比較例
OpenMP* 4.0 / 4.5 – チームとスレッド間で parallel for ループをアクセラレート#pragma omp target teams map(X[0:N]) num_teams(numblocks)#pragma omp distribute parallel forfor (i=0; i<N; ++1) {X[i] += sin(X[i]);}OpenACC* 2.0 / 2.5 – ギャングとワーカー間で for ループをアクセラレート#pragma acc parallel copy(X[0:N]) num_gangs(numblocks)#pragma acc loop gang worker
for (i=0; i<N; ++i) {X[i] += sin(X[i]);}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

98

OpenMP* と OpenACC* 対応
機能

OpenACC*

OpenMP*

オフロード

parallel または kernels

target

データ環境

data

target data

データ転送、変数定義

copy(変数)/ create(変数)map(tofrom:変数)
map(alloc:変数)

並列処理(チーム）

loop gang
num_gangs(n)teams distribute
num_teams(n)thread_limit(n)並列処理

loop vector
vector_length(n)parallel for© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

99

GFX へオフロードする際の注意点 (Windows®)
要件：
1. インテル® C++ コンパイラー 15.0 以降を入手する
2. 最新のインテル® HD グラフィックス・ドライバーを入手する
http://downloadcenter.intel.com
3. Binutils パッケージを入手する
http://software.intel.com/en-us/articles/open-source-downloads
4. サンプルフォルダーにある gfx_samples.tar.gz を任意のディレクトリーに展開します。この zip ファイルは、プロセッサー・グラフィックスへの計算オフロードを行う
いくつかのサンプルコードを含んでいます。それらのコードをビルドして実行でき
れば、環境は正しく設定されていると言えます

http://www.isus.jp/products/psxe/getting-started-with-compute-offload-to-gfx/© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

100

GFX へオフロードする際の注意点 (Linux*)
要件：
1. インテル® C++ コンパイラー 15.0 以降を入手する
2. インテル® HD グラフィックス・ドライバー、またはオープンソース・メディア・カーネ
ル・ランタイムを入手する
3. 「video」グループの権限を持つアカウントで、Linux* マシンにログインする
4. /usr/lib/x86_64-linux-gnu を LD_LIBRARY_PATH に追加する:
export LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH

5. リンカーがライブラリーを検索できるようにするため、/etc/ld.so.conf.d/x86_64linux-gnu.conf ファイルに /usr/lib/x86_64-linux-gnu パスを追加する

Linux* ドライバーのバージョンによる OS サポート:
http://www.isus.jp/products/psxe/getting-started-with-compute-offload-to-gfx/© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

101

GFX へのオフロード: OpenMP* 4.0 offload への追加機能
bool Sobel::execute_offload(){
int w = COLOR_CHANNEL_NUM * image_width;
float *outp = this->output;
float *img = this->image;int iw = image_width;
int ih = image_height;#pragma omp target map(to: ih, iw, w) ¥map(tofrom: img[0:iw*ih*COLOR_CHANNEL_NUM], ¥outp[0:iw*ih*COLOR_CHANNEL_NUM])#pragma omp parallel for collapse(2)for (int i = 1; I < ih – 1; i++) {for (int k = COLOR_CHANNEL_NUM; k < (iw - 1) * COLOR_CHANNEL_NUM; k++) {float gx = 1 * img[k + (i - 1) * w -1 * 4]
+ 2 * img[k + (i - 1) * w +0 * 4]
+ 1 * img[k + (i - 1) * w +1 * 4]
- 1 * img[k + (i + 1) * w -1 * 4]
- 2 * img[k + (i + 1) * w +0 * 4]
- 1 * img[k + (i + 1) * w +1 * 4];
float gy = 1 * img[k + (i - 1) * w -1 * 4]
- 1 * img[k + (i - 1) * w +1 * 4]
+ 2 * img[k + (i + 0) * w -1 * 4]
- 2 * img[k + (i + 0) * w +1 * 4]
+ 1 * img[k + (i + 1) * w -1 * 4]
- 1 * img[k + (i + 1) * w +1 * 4];outp[i * w + k] = sqrtf(gx * gx + gy * gy) / 2.0;}}
return true;}

利用方法:− OpenMP* の一部の機能のみをサポート− 配列データはポインター渡し“tofrom” を “pin” へマップ
− GFX 向けのコンパイルを指示“-qopenmp-offload=gfx” を指定© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

102

target ディレクティブで depend 節を使用して GPU
へ非同期オフロードする例// arr1 を初期化 - ターゲットへオフロード#pragma omp target map(from: arr1[0:SIZE]) depend(out:arr1) nowait#pragma omp parallel forfor (int i = 0; i < SIZE; i++) { arr1[i] += i; }// arr2 の初期化
#pragma omp task depend(out:arr2)#pragma omp parallel forfor (int i = 0; i < SIZE; i++) { arr2[i] += -i; }

親タスク
(ホスト)
子タスク 1(GPU)
スポーン

子タスク 3(ホスト)
依存関係// ターゲット上で中間結果を計算#pragma omp target ¥map(to: arr1[0:SIZE], arr2[0:SIZE]) ¥map(from:arr3[0:SIZE]) ¥nowait depend(in:arr1, arr2)#pragma omp parallel forfor (int i = 0; i < SIZE; i++) { arr3[i] = arr1[i] + arr2[i]; }

arr1

依存関係

arr2

子タスク 2(GPU)

バリア#pragma omp taskwait#pragma omp parallel forfor (int i = 0; i < SIZE; i++) { res[i] += arr3[i]; }© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

103

OpenMP* 4.5 Offload 拡張 (pragma omp target)
OpenMP* 4.5 によるオフロード拡張への追加機能


主要機能は、インテル® コンパイラー 16.0 で実装済み

新機能:

target 構文と API への新しいデバイスポインター節の追加#pragma omp target data … use_device_ptr(list) …
void omp_target_free(void * device_ptr, int device_num);link 節による遅延マップ#pragma omp declare target … [to] ( extended-list ) link (list)target 構文の節の多様性#pragma omp declare target … private(list) firstprivate(list) if (…)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

104

オフロードレポートの活用
このトピックは、インテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキ
テクチャーにのみ適用されます。 コードのオフロード領域の実行時間と実行中のデータ転送量を測定することができます
ホストとターゲットで実行が進むと、オフロードに関する情報を含むオフロードレポートを取得することができます: コードのオフロード領域の実行時間
 ホストとターゲット間のデータ転送量 デバイスの初期化と個々の変数の転送を含む詳細
次のメカニズムを使用してオフロードレポートを有効または無効にすることができます: OFFLOAD_REPORT 環境変数
 _Offload_report API© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

105

オフロードレポートの内容
行マーカー

説明

[状態]

オフロードの一部として実行されている処理。

[変数]

転送された変数名および転送の向き。

[CPU 時間]

ホスト上の offload プラグマの実行時間。

[MIC 時間]ターゲット上のオフロード実行時間。
ホストとターゲット間のデータ転送時間を除く、ターゲット上の実行時間のみカウントされます。

[CPU->MIC データ]

ホストからターゲットへ転送されたデータのバイト数。

[MIC->CPU データ]

ターゲットからホストへ転送されたデータのバイト数。

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

106

OpenMP* 5.0 の offload 拡張








プログラマーの負担を軽減するため、いくつかの関数 (C、C++、Fortran) とサブルーチ
ン (Fortran) で暗黙の declare target ディレクティブが追加されました [2.15.5、
2.15.7]
入れ子になった declare target ディレクティブのサポートが追加されました [2.15.7]
デバイス固有の関数実装をサポートするため、declare target ディレクティブに
implements 節が追加されました [2.15.7]
複雑なデータタイプのマッピングをサポートするため、declare mapper ディレクティ
ブが追加されました [2.15.8]
配列セクションへのマップで、ポインター変数へのマップ (C/C++) とデバイスメモリーのアドレス割り当てが追加されました [2.20.6.1]
スレッドがどのデバイスで実行されているかを特定するため、omp_get_device_num
ランタイムルーチン [3.2.36] が追加されました
オフロード動作の制御をサポートするため、OMP_TARGET_OFFLOAD 環境変数が追加されました [5.17]© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

107

暗黙の declare target ディレクティブ


オフロード領域で呼び出されている関数を自動的に検出して、それらの関数がdeclare target ディレクティブで指定されているかのように扱います。以前は、オフロード領域で呼び出されるすべての関数は、declare target ディレクティブによって明示的にタグ付けされている必要がありました#pragma omp declare target
void foo() {// ...
}#pragma omp end declare target
void bar() {#pragma omp target{
foo();}
OpenMP* バージョン 4.5
}

のスタイル

void foo() {// ...
}
void bar() {#pragma omp target{
foo();}}

OpenMP* バージョン 5.0 のスタイル© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

108

静的記憶域を含む変数の自動検出
 OpenMP* 5.0 では、静的記憶域を含む変数も自動的に検出できます。これにより、次の 2 つの例は等価となります
int x;#pragma omp declare target to (x)void bar() {#pragma omp target{
x = 5;}}

int x;
void bar() {#pragma omp target{
x = 5;}}© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

109

配列セクションへのマップで、ポインター変数へのマップ (C/C++) とデバイスメモリーのアドレス割り当て OpenMP* バージョン 4.5 では、use_device_ptr 節が追加されましたが、use_device_ptr の変数は、使用する前にマップする必要があります。
変数は 1 つのデータ節にのみ記述できるため、プログラマーは個別の#pragma target data 節を記述する必要がありました:#pragma omp target data map(buf)#pragma omp target data use_device_ptr(buf) OpenMP* 5.0 では、単一構文で変数を map 節と use_device_ptr 節の両方に記述できる例外が追加されました:#pragma omp target data map(buf) use_device_ptr(buf)© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

110

つづき
 OpenMP* 4.5 では、最初の構造がターゲットである結合構造のreduction 節または lastprivate 節で使用されるスカラー変数は、ター
ゲット構造の firstprivate として扱われます。ホストの変数が更新されることはありません。ホストの変数を更新するには、プログラマーは結合構
造から omp target ディレクティブを分離してスカラー変数を明示的にマップする必要があります OpenMP* 5.0 では、これらの変数は自動的にmap(tofrom:variable) が適用されているかのように扱われます© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

111

omp declare target 内の静的データメンバー
 OpenMP* 5.0 では、スタティック・データ・メンバー
が omp declare target 構
文内のクラスで使用できるようになりました。
 また、スタティック・メン
バーを含むクラス・オブジェ
クトは map 節でも使用できます#pragma omp declare target
class C {static int x;
int y;}
class C myclass;#pragma omp end declare target
void bar() {#pragma omp target map(myclass){myclass.x = 10}}

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

112

入れ子になった declare target のサポート
 外側の omp target
data 構文内で構造体
変数のフィールドをマップして、内側の入れ子の omp target 構
文内で構造体変数のア
ドレスを使用すると、構造体の一部がすでにマップされている場
合、構造体変数全体をマップしようとします

struct {int x,y,z} st;
int A[100];#pragma omp target data map(s.x A[10:50]){#pragma omp target{
A[20] = ; // OpenMP* 4.5
5.0foo(&st); // OpenMP* 4.5
5.0}#pragma omp target map(s.x, A[10:50]){
A[20] = ; // OpenMP* 4.5
5.0
OKfoo(&st); // OpenMP* 4.5
5.0
OK
}
}

OK
OK

OpenMP 5.0 では、プログラマーが想定した動作になるように、
これらのケースが修正されました© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

113

ヘテロジニアス・プログラミングの向上
OpenMP* のデバイスサポートを向上するために次のような機能が検討されています: 現在、map 節の構造は、構造のポインターフィールドを含めて、ビット単位でコピーされます。ポインターフィールドが有効なデバイスメモリーを指すようにプログラマーが要求した場合、デバイス上にメモリーを確保してデバイスのポインターフィールドを明示的に更新する必要があります。委員会は、構造のポインターフィールドのサポートを拡張することにより、プログラマーが map 節を使用して構造のポインターフィールドの自動割り当て/
割り当て解除を指定できるようにする拡張について議論しています 関数ポインターを target 領域で使用できるようにすること、および関数ポインターを
declare target に記述できるようにすることを検討しています 非同期に実行できる新しいデバイス memcpy ルーチンのサポート
 target 構文の「デバイスで実行または失敗」セマンティクスのサポート。現在、デバイスが利用できない場合、ターゲット領域はホストで実行されます デバイスのみに存在し、ホストベースのコピーでない変数や関数のサポート
 単一アプリケーションでの複数のデバイスタイプのサポート© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

114

アフィニティー拡張© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

115

NUMA はここに属する ...
 (ほとんど）すべてのマルチソケット計算サーバーは、NUMA システム
 異なるメモリー位置へのアクセス・レイテンシーは一定ではない
 異なるメモリー位置の帯域幅が異なる可能性がある
 例：インテル® Xeon® プロセッサー E5-2600 v2 製品ファミリー

Xeon® E52600v2

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

116

スレッド・アフィニティー - なぜ重要なのか ?
STREAM Triad
インテル® Xeon® プロセッサー E5-2697 v2
80.00
60.00
40.00
20.00

24

23

22

21

20

19

18

17

16

15

14

13

12

11

10

9

8

7

6

5

4

3

2

0.00

1

GB/秒 [高値がより良い]

100.00スレッド/コア数
compact, parscatter, parcompact, seq© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

scatter, seq

117

KMP_AFFINITY: 柔軟性のある OMP スレッドの割り当て(インテル固有の実装)
マシン/ノード

パッケージ
0

1

コア
スレッド・
コンテキスト

0

1

0

1

0

1

0

1

0

1

0

0

4

2

6

1

5

3

1
7

OpenMP* グローバルスレッド ID

サンプル: 2x2x2 マシントポロジー (2 パッケージ/ソケット、2 コア、2 論
理スレッド); 次の設定で OpenMP* スレッドをバインド
KMP_AFFINITY=”granularity=fine,scatter”© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

118

KMP_PLACE_THREADS (インテル固有の実装)
スレッドの分配を制御– ソケット数– ソケットあたりのコア数– コアあたりのスレッド数
 KMP_PLACE_THREADS 変数は、プログラムで使用されるハードウェア・リ
ソースを制御。この変数は、使用するソケット数、各ソケットで使用するコア数、および各コアに割り当てるスレッド数を指定
 例えば、インテル® Xeon Phi™ コプロセッサーでは、各コプロセッサーの最大スレッド数は 4 であるが、コアあたり 3 スレッド以下にしてもパフォーマンス
が向上することがある サンプル: KMP_PLACE_THREADS=2s,4c,2t
© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

119

OpenMP* 4.0: 標準化されたアフィニティー
parallel 領域向けの追加された節: proc_bind (アフィニティー・タイプ)
環境変数によるアフィニティー設定制御:
 OMP_PROC_BIND
例えば: export OMP_PROC_BIND=“spread,spread,close”
 OMP_PLACES
例えば: export OMP_PLACES=“{0,1,2,3},{4,5,6,7},{8:4},{12:4}”
OMP_PLACES は実装依存で、OpenMP* では定義されない© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

120

OpenMP* 5.0 のメモリーと同期管理© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

121

新しい allocate ディレクティブ

新しい allocate ディレクティブは、API 呼び出しで割り当てられない変数の割り当てを制御するために提案されたものです (自動変数または静的変数など)
OpenMP* ディレクティブによる割り当て操作に使用できます (変数のプライベー
ト・コピーなど)
int a[N], b[M];#pragma omp allocate(a,b) memtraits(bandwidth=highest, pagesize=2*1024*1024)
void example() {#pragma omp parallel private(b) allocate(memtraits(latency=lowest):b){// ...
}}

2MB ページを使用する最も高い帯域幅のメモリーに変数 a と b の割り当てを変更© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

122

OpenMP* 4.5 でロックのヒントを定義
現代のプロセッサー・アーキテクチャーの中には、トランザクショナル・メモリーをサポートするものがある。例えば、インテル® TSX (インテル® Transactional Synchronization Extensions )

この機能が同期 (ロック) を最適に実行するかどうかは、競合条件に依存

開発者は、コンパイラーの実装へこの情報を渡す意味を知っている必要がある

OpenMP* 4.5 では、これに相当する拡張を提供:•追加された OpenMP* API/ランタイムルーチン:サポートされるヒント:

omp_init_lock_with_hint(omp_lock_t *lock,
omp_lock_hint_t hint)
omp_init_nest_lock_with_hint(omp_nest_lock_t *lock,
omp_lock_hint_t hint)•

omp_lock_hint_none
omp_lock_hint_uncontended
omp_lock_hint_contended
omp_lock_hint_nonspeculative
omp_lock_hint_speculative

critical 構文の新たな節 hint(type): “type” は、新しいロック API と同じ値を指定可能© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

123

OpenMP* 5.0 で同期のヒントを定義
ロックヒント (Lock hint) の名前が同期ヒント (synchronization hint) に変更されました。古い名前は廃止予定です。[2.18.11]
 OpenMP* ロック機能の一部
 C/C++ の omp_lock_hint_t と Fortran の omp_lock_hint_kind タイプを廃止予定
 および、ロックのヒント定数 omp_lock_hint_none、
omp_lock_hint_uncontended、omp_lock_hint_contended、
omp_lock_hint_nonspeculative、および
omp_lock_hint_speculative を廃止
lock

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

124

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

125

OpenMP* 4.x と 5.0 機能のまとめ
OpenMP* 4.x 機能のまとめ
 OpenMP* 4.5 はバグフィックスのためのリリースではない OpenMP* 4.0 で実装されていなかった重要な機能を追加

OpenMP* 5.0 は TR6 の実装作業中
 Supercomputing 2018 でリリースされる見込み
 インテル® コンパイラーは、V18 で TR4 を実装

OpenMP* の明示的な Target、Parellel および SIMD プログラミングは、「ハードウェアのパフォーマンス」を最大限に引き出す道を開く© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

126

インテル® コンパイラーの OpenMP* サポート状況
インテル® コンパイラー 16.0 は、ほとんどすべての OpenMP* 4.0 といくつかのOpenMP* 4.5 仕様をサポート
 OpenMP* 4.0 で確認中な物: ユーザー定義のリダクションの完全なサポート– 作業中: OMP PARALLEL における C/C++ の POD 型 (「plain old data」)– 未実装: Fortran、SIMD、および非 POD 型 (C++)

インテル® コンパイラー 17.0 は大部分の OpenMP* 4.5 仕様をサポート
 ロックとクリティカル領域のトランザクショナル・メモリー・サポートを除く
 2016 年 9 月リリース

インテル® コンパイラー 18.0 は OpenMP* 5.0 TR4 をサポート
 2017 年 9 月リリース

インテル® コンパイラー次期バージョンで OpenMP* 5.0 TR6 をサポート予定© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

127

参考資料








OpenMP* TR6 (テクニカル・レポート 6) に含まれる新機能
インテル® コンパイラー 18.0 の OpenMP* 5.0 サポート
OpenMP* 誕生から 20 年 Part1
OpenMP* 誕生から 20 年 Part2
現在と将来の OpenMP* API 仕様
OpenMP* バージョン 4.5: 標準化の進化
OpenMP サポートのまとめ

オンライン・トレーニング・コース：
 インテル® コンパイラーによる OpenMP* 入門 (8回)
 OpenMP* 4.x による新しいレベルの並列化 (2回) インテル® Parallel Studio XE によりアプリケーション・パフォーマンスを大幅に向上© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

128

関連書籍
アプリケーションの並列化がさまざまな分野で求められる昨今、開発者に求められる並列プログラミングのスキルは科学技術計算の分野のみならず、一般のコンシューマー・アプリケーションや自社開発のアプリケーションでも求められるようになっています。
Windows® や Linux* をはじめとする近年のオペレーティング・システムは、マルチプロセスおよびマルチスレッドのプログラミング環境をサポートしていますが、残念ながらそれらは統一されたものではありません。開発者はそれぞれの環境ごとに API などの使い方を学習し、OS ごとに異なるプログラムを開発しなければいけません。マルチスレッド環境以前にも皆さんは GUI のプログラミングなどで同じことを経験していることでしょう。プログラムがさらに複雑になるのは大変なことです。
異なる OS 環境で同じプログラミング手法が利用できればそれに越したことはありません。OpenMP* はそのような開発環境を提供す
る優れたプログラミング手法であり、スレッド化に際しプログラムの構造を変えることなく容易にマルチスレッド機能を実装することができます。
本書は C/C++ プログラマー向けの OpenMP* 入門書として書かれています。皆さんが利用しているコンパイラーはすでに OpenMP*をサポートしているかもしれません。ぜひこの機会に OpenMP* プログラミングを始めてください。
2009 年 7 月に本書初版が出版された後、2011 年 7 月に OpenMP* 3.1 の仕様が公開されました。本書では第 2 版 (増補版) として付
録 F に新しい仕様の説明を加えるとともに、一部改訂しています。

本書は、Knights Landing✝ に含まれる多くの拡張機能を最大限に活用する並列プログラミング手法に焦点を当てています。以前の書籍では、第 1 世代のインテル® Xeon Phi™ 製品 (開発コード名: Knights Corner) について紹介しましたが、その後、多くのことが起こっています。Knights Corner✝ で得た多くの経験を、利用可能になった第 2 世代インテル® Xeon Phi™ 製品に活用できることに興奮を覚えます。これらの経験は、一貫してすべてのインテル® Xeon Phi™ 製品の心臓部であるインテル® メニー・インテグレーテッド・コア (インテル® MIC) アーキテクチャーの「デュアル・チューニング (二重のチューニング)」という価値を高めるのに役立ちました。インテル® Xeon
Phi™ 製品のプログラミング向けの 「デュアル・チューニング (二重のチューニング)」の特徴は、ソフトウェア開発者が「インテル® Xeon
Phi™ 製品が登場するまで、私たちは、インテル® Xeon® プロセッサーの素晴らしさを実感していませんでした」、そして 「インテル®
Xeon Phi™ 製品向けのチューニングは、常にインテル® Xeon® プロセッサーでも実質的な利益をもたらします」とコメントしたように、彼らを奮い立たせました。これこそが、マルチコア・プログラミングにおいて並列性を活用するため、コードを変更するモチベーションとなっていることを示しています。このような作業は、メニーコアとマルチコア・プロセッサーで同じコードを使用してパフォーマンスを向上することで恩恵を受けます。そのため、「デュアル・チューニング(二重のチューニング)」と呼びます。この一連の作業は、「コード・モダニ
129
ゼーション (コードの現代化)」と呼ばれています。
✝開発コード名© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

129

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

130

付録: OpenMP* の仕様の違い
•
•
•
•
•

4.5 -> 5.0
4.0 -> 4.5
3.1 -> 4.0
3.0 -> 3.1
2.5 -> 3.0© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

131

OpenMP* 5.0 で廃止予定の機能
 ICV nest-var の廃止に伴う廃止予定の機能
 OMP_NESTED 環境変数
 omp_set_nested および omp_get_nested API
 OpenMP* ロック機能の一部
 C/C++ の omp_lock_hint_t と Fortran の omp_hint_hint_kind タイプを廃止予定
 および、ロックのヒント定数 omp_lock_hint_none、
omp_lock_hint_uncontended、omp_lock_hint_contended、
omp_lock_hint_nonspeculative、および
omp_lock_hint_speculative© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

132

バージョン 4.5 と 5.0 の違い
1.

指定されたフラッシュ特性に従って異なるタイプのフラッシュ操作を区別するためメモリーモデルが拡張され[1.4.4] 、同期フラッシュ操作の前に行われるように定義されました。[1.4.5]
2. C11、C++11、および C++14 の初期サポートを提供するため仕様全体を通してさまざまな変更が行われました。[1.7]
3. Fortran 2003 のいくつかの機能をのサポートが追加されました。[未サポートの機能については 1.7 を参照]
4. タスク生成構文の depend 節に指定できるリスト項目 (C/C++ のすべての lvalue 表現を含む) が拡張されました。[2.1、2.18.10]
5. デバイス間の一般及び共有メモリー実装固有の機能を必要とするアプリケーションをサポートするため、
require ディレクティブ [2.3] が追加されました。
6. デバイス構文の実行をランタイム制御するため、target-offload-var 内部制御変数 (ICV) [2.4] とOMP_TARGET_OFFLOAD 環境変数 [5.17] が追加されました。
7. nest-var ICV のデフォルト値が、実装依存から false に変更されました。[2.4.2]nest-var ICV [2.4.1]、
OMP_NESTED 環境変数 [5.6]、および omp_set_nested/omp_get_nested ランタイムが廃止予定となりました。[3.2.10、3.2.11]
8. リスト表現が複数の式に拡張される可能性を表現できるようイテレーターが追加されました。[2.6]9. 事前定義メモリー・アロケーター [2.7] とディレクティブ、節 [2.14]、および API ルーチン [3.6] が、異なる種類のメモリーをサポートするため追加されました。
10. C/C++ の正規表現ループ形式の relational-op が、!= を含むように拡張されました。[2.9]© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

133

バージョン 4.5 と 5.0 の違い (続き)11. 不完全な入れ子ループに関連する collapse が、ループ [2.10.1]、simd [2.11.1]、taskloop [2.13.2]、
distribute [2.15.11] 構文で定義されました。
12. SIMD 構文 [2.11] 内で atomic 構文が使用できるよう拡張されました。
13. simd 構文に nontemporal 節が追加されました。[2.11.1]
14. 任意の順番で同時実行されるループ反復をコンパイラーが最適化できるよう concurrent 構文が追加されました。[2.12]
15. タスクのリダクションをサポートするため、task [2.13.1] と target [2.15.5] 構文が in_reduction 節[2.20.4.6] を受け入れるように拡張され、taskgroup 構文 [2.18.6] が task_reduction 節 [2.20.4.5] を受け入れるように拡張されました。
16. taskloop リダクションをサポートするため、taskloop [2.13.2] と taskloop simd [2.13.3] 構文が reduction
節 [2.20.4.4] と in_reduction 節 [2.20.4.6] を受け入れるように拡張されました。
17. 排他 inout セットをサポートするため、depend 節 [2.13.6、2.18.10] に mutexinoutset dependence-typeが追加されました。
18. プログラマーの負担を軽減するため、いくつかの関数 (C、C++、Fortran) とサブルーチン (Fortran) で暗黙のdeclare target ディレクティブが追加されました。[2.15.5、2.15.7]
19. 入れ子になった declare target ディレクティブのサポートが追加されました。[2.15.7]
20. デバイス固有の関数実装をサポートするため、declare target ディレクティブに implements 節が追加されました。[2.15.7]© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

134

バージョン 4.5 と 5.0 の違い (続き)21. 複雑なデータタイプのマッピングをサポートするため、declare mapper ディレクティブが追加されました。[2.15.8]
22. taskwait 構文に depend 節が追加されました。[2.18.5]
23. Weak メモリー順序付けのメモリー要求と解放セマンティクスをサポートするため、atomic 構文 [2.18.7]と flush 構文 [2.18.8] に acq_rel、acquire、および release 節が追加されました。
24. atomic 構文に hint 節が拡張されました。[2.18.7]
25. イテレーターをサポートするため depend 節 [2.18.10] が拡張されました。
26. ロックヒント (Lock hint) の名前が同期ヒント (synchronization hint) に変更されました。古い名前は廃止予定です。[2.18.11]
27. lastprivate 変数に条件付きの割り当てをサポートするため、lastprivate 節に conditional 修飾子が追加されました。[2.20.3.5]
28. 構造体メンバーのマッピングを明確に説明するため、map 節の説明が変更されました。[2.20.6.1]
29. 配列セクションへのマップで、ポインター変数へのマップ (C/C++) とデバイスメモリーのアドレス割り当てが追加されました。[2.20.6.1]
30. 構文が明示的にマップする必要がある、すべての変数、すべての変数参照の要求をサポートするため、
defaultmap 節 [2.20.6.2] が none パラメーターを許容するように拡張されました。

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

135

バージョン 4.5 と 5.0 の違い (続き)31. OpenMP* スレッド・アフィニティーの情報を提供するため、ランタイムルーチン [3.2.29、3.2.30、3.2.31、
3.2.32] と環境変数 [5.13、5.14] が追加されました。
32. スレッドがどのデバイスで実行されているかを特定するため、omp_get_device_num ランタイムルーチン[3.2.36] が追加されました。
33. ファーストパーティーのツール・インターフェイス [4.1] のサポートが追加されました。
34. サードパーティーのツール・インターフェイス [4.2] のサポートが追加されました。
35. オフロード動作の制御をサポートするため、OMP_TARGET_OFFLOAD 環境変数が追加されました。[5.17]© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

136

バージョン 4.0 と 4.5 の違い
•
•
•
•
•
•
•
•
•
•
•

Fortran 2003 のいくつかの機能のサポートが追加されました。
ループ構文の ordered 句に引数が追加されました。これにより、ordered 構文にループ伝搬後方依存があるルー
プで simd 構文を使用可能にするため doacross ループ入れ子がサポートされます。
ループ構文に linear 句が追加されました。
SIMD チャンクごとに必要な反復数の指定をサポートするため simd 構文に simdlen 句が追加されました。
明示的なタスクの実行優先順位に関するヒントの指定をサポートするため、task 構文に priority 句が追加されました。優先順位の値を取得するため omp_get_max_task_priority ルーチンが、そして許可する優先順位の最大値の値を制御するため OMP_MAX_TASK_PRIORITY 環境変数が追加されました。
OpenMP* タスクを生成するネスト可能な並列ループをサポートするため、taskloop 構文が追加されました。
ネイティブデバイスの実装との対話をサポートするため、target data 構文に use_device_ptr 句が追加され、
target 構文に is_device_ptr 句が追加されました。
target 領域の非同期実行のサポートを改善するため、target 構文に nowait と depend 句が追加されました。
target 構文に private、firstprivate および defaultmap 句が追加されました。
declare target ディレクティブが、特定のデバイスの実行に関連するグローバル変数の割り当てと、C/C++ での拡張
リストの指定を可能にするため拡張されました。
デバイスへの非構造化データ割り当てをサポートするため、target enter data と target exit data 構文が追加され、map 句が変更されました。

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

137

バージョン 4.0 と 4.5 の違い (続き)
•
•
•
•
•
•
•
•
•
•
•
•

デバイス構文へのショートカットを充実されるため、target parallel、target parallel loop、target parallel
loop SIMD、および target simd の結合構文が追加されました。
結合構文に適用できるように、if 句にデバイス名修飾子が指定できるようになりました。
critical 構文に hint 句が追加されました。
Doacross ループの入れ子をサポートするため、depend 句に source と sink 依存性タイプが追加されました。
target 領域内のスカラー変数向けの明示的なデータ共有属性が、firstprivate に変更されました。
いくつかのデータ共有属性句でいくつかの C++ 参照型の使用が許可されました。
C/C++ 配列セクションでのリダクション向けのセマンティクスが追加され、リダクションにおける配列とポインターの使用に関する制限がなくなりました。
linear 句に ref、val および uval 修飾子が追加されました。
map 句に構造体要素を処理する機能のサポートが追加されました。
OpenMP* スレッドのアフィニティーを問い合わせるクエリー関数が追加されました。
ロック API が、アプリケーション・コードの意図するロックの利用を実装が選択できるように、ヒント付きのロックをサポートするためルーチンが拡張されました。
明示的な割り当て、再割り当て、メモリー転送、およびメモリーへの関連付けを可能にするため、デバイス・メモ
リー・ルーチンが追加されました。

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

138

バージョン 3.1 と 4.0 の違い
•
•
•
•
•
•
•
•
•
•
•

•

Fortran 2003 の初期サポートを提供するため仕様全体を通してさまざまな変更が行われました。
配列セクションをサポートするため C/C++ 配列シンタックスが拡張されました。
スレッドのアフィニティーをサポートするため、proc_bind 句 、OMP_PLACES 環境変数および
omp_get_proc_bind ランタイムルーチンが追加されました。
SIMD 並列をサポートするため SIMD 構文が追加されました。
デバイス上での実行をサポートするため、デバイス構文、OMP_DEFAULT_DEVICE 環境変数、
omp_set_default_device、omp_get_default_device、omp_get_num_devices、omp_get_num_teams、
omp_get_team_num および omp_is_initial_device ランタイムルーチンがサポートされました。
untied タスク向けのタスクのスケジューリング・ポイント実装定義が削除されました。
タスクの依存性をサポートするため depend 句が追加されました。
柔軟性のある深いタスクの同期をサポートするため taskgroup 構文が追加されました。
ユーザー定義リダクションをサポートするため、reduction 句が拡張され、declare reduction 構文が追加されました。
atomic 構文が、capture 句で atomic スワップをサポートし、新しい atomic updtae と capture 形式を利用できるようにし、seq_cst 句でシーケンシャルで一貫した atomic 操作をサポートするように拡張されました。
cancel 構文、cancellation point 構文、omp_get_cancellation ランタイムルーチンと OMP_CANCELLATION 環
境変数がキャンセルのコンセプトをサポートするために追加されました。
OMP_DISPLAY_ENV 環境変数が、OpenMP* 環境変数と関連する内部変数の値を表示するため追加されました。

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

139

バージョン 3.0 と 3.1 の違い
•
•
•
•
•
•
•
•
•
•
•

final と mergeable 句が、 タスクデータ環境の最適化をサポートする task 構文に追加されました。
ユーザー定義のタスク・スケジュール・ポイントをサポートするため taskyield 句が追加されました。
atomic 構文に read、write、capture 形式が追加され、既存の atomic 構文の形式に適用できる update 句が追加されました。
データ環境の制限が変更され、intent(in) と const 修飾型が firstprivate 句で許可されるようになりました。
データ環境の制限が変更され、firstprivate 句と lastprivate 句で Fortran ポインターが許可されました。
C と C/C++ に新しいリダクション演算子 min と max が追加されました。
atomic 領域内に密接した OpenMP* 領域を許可しないことが明確化されました。これにより、atomic 領域を
ほかの OpenMP* 領域と一貫性を持って定義し、すべてのコードを atomic 構文に含めることができます。
final task 領域の同期をサポートするため omp_in_final ランタイムルーチンが追加されました。
内部変数 nthreads-var は、ネストされた並列領域レベルごとに使用するスレッド数のリストに変更されています。内部変数の値は、 OMP_NUM_THREADS 環境変数を使用して設定できますが、アルゴリズムが並列領域で使用するスレッド数を決定する場合、リストを処理するように変更されています。
内部変数 bind-var が追加されました。これは、スレッドをプロセッサーにバインドされるかどうかを制御します。内部変数の値は、OMP_PROC_BIND 環境変数を使用して設定できます。
Fortran インターフェイスの omp_integer_kind の誤った用法を select_int_kind に置き換えました。

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

140

バージョン 2.5 と 3.0 の違い
•
•
•
•
•
•
•
•
•
•
•
•
•
•
•

OpenMP* 実行モデルにタスクの概念を導入しました。
タスクを明示的に作成するメカニズムとして、task 構文が追加されました。
タスクが生成した子タスクの完了を待機するため、taskwait 構文が追加されました。
OpenMP* メモリーモデルが、アトミックなメモリーアクセスをカバーできるようになりました。flush 操作の項目から volatile の振る舞いの説明が削除されました。
バージョン 2.5 では、プログラム全体で 1 つの nest-var、dyn-var、nthreads-var および run-sched-var 内部制御変数を持っていました。
バージョン 3.0 では、タスクごとに 1 つのコピーを持ちます。その結果、omp_set_num_threads、omp_set_nested および
omp_set_dynamic ランタイム・ライブラリー・ルーチンは、並列領域内から呼び出されても効果を持つようになりました。
アクティブな parallel 領域の定義が変更されました: OpenMP* 3.0 では、2 つ以上のスレッドで構成されるチームによって実行される場合
parallel 領域はアクティブです。
parallel 領域で使用されるスレッド数を決定する規則が変更されました。
バージョン 3.0 では、ループ構造における反復のスレッドへの割り当ては、static スケジュールがデフォルトです。
バージョン 3.0 では、ループ構造は完全に入れ子になった複数のループに関連付けられることがあります。関連するループの数は、collapse
句で制御できます。
ランダム・アクセス・イテレーターと符号なし整数型変数が、ループ構造に関連付けられたループ内のループ・イテレーターとして使用できます。
スケジュールの種別に auto が追加されました。これにより実装でループ構造をスレッドのチームへループ反復をマッピングする自由度が高まります。
Fortran の形状引き継ぎ配列が、事前定義されたデータ共有属性を持ちます。
Fortran において、default 句への引数として firstprivate 節が指定できるようになりました。
private 句のリスト項目で、実装では元のリスト項目のストレージを使用して、マスタースレッド上に新しいリスト項目を保持することを許可しなくなりました。parallel 領域内で元のリスト項目を参照しない場合、その値は parallel 領域から出ても定義されています。
バージョン 3.0 では、 Fortran の割り当て可能配列を private、firstprivate、lastprivate、reduction、copyin そして copyprivate 句に指定できるようになりました。
© 2018 iSUS *その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。

141

バージョン 2.5 と 3.0 の違い (続き)
•
•
•
•
•
•
•
•
•
•
•
•

バージョン 3.0 では、threadprivate ディレクティブに静的クラスメンバー変数を指定できるようになりました。
バージョン 3.0 では、private と threadprivate クラス型変数のコンストラクターとデストラクターの呼び出し場所と引数が明確にされました。
ランタイム・ライブラリー・ルーチン omp_set_schedule と omp_get_schedule が追加されました。このルーチンは、内部制御変数 runsched-var の値を設定および取得します。
OpenMP* プログラムが使用する最大スレッド数を制御する内部制御変数 thread-limit-var が追加されました。この内部制御変数の値は、
OMP_THREAD_LIMIT 環境変数で設定し、omp_get_thread_limit ランタイム・ライブラリー・ルーチンで取得できます。
アクティブな parallel 領域の入れ子数を制御する内部制御変数、max-active-levels-var が追加されました。この内部制御変数は、
OMP_MAX_ACTIVE_LEVELS 環境変数と omp_set_max_active_levels ランタイム・ライブラリー・ルーチンを使用して設定し、
omp_get_max_active_levels ランタイム・ライブラリー・ルーチンで取得できます。
OpenMP* 実装が作成するスレッドのスタックサイズを制御する内部制御変数 stacksize-var が追加されました。内部制御変数の値は、
OMP_STACKSIZE 環境変数を使用して設定できます。
待機中のスレッドの振る舞いを制御する内部制御変数 wait-policy-var が追加されました。内部制御変数の値は、OMP_WAIT_POLICY 環境
変数を使用して設定できます。
この呼び出しを含むタスクの parallel 領域の入れ子レベルを返す omp_get_level ランタイム・ライブラリー・ルーチンが追加されました。
呼び出しを行ったスレッドの入れ子レベルの祖先のスレッド番号を返す、omp_get_ancestor_thread_num ランタイム・ライブラリー・ルーチンが追加されました。
呼び出しを行ったスレッドの入れ子レベルの祖先に関連するスレッドチームのサイズを返す、omp_get_team_size ランタイム・ライブラリー・ルーチンが追加されました。
この呼び出しを含むタスクの入れ子になったアクティブな parallel 領域の数を返す omp_get_active_level ランタイム・ライブラリー・ルーチンが追加されました。
バージョン 3.0 では、ロックはスレッドではなくタスクによって保持されます。

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

142