OpenMP* オフロードのチューニング・ガイド

インテル® oneAPI

この記事は、インテル® デベロッパー・ゾーンに公開されている『oneAPI GPU Optimization Guide』の「OpenMP* Offloading Tuning Guide」からの抜粋の日本語参考訳です。原文は更新される可能性があります。原文と翻訳文の内容が異なる場合は原文を優先してください。


LLVM ベースのインテル® C/C++ および Fortran コンパイラー (icxicpx、および ifx) は、GPU への OpenMP* オフロードをサポートします。OpenMP* を使用する場合、プログラマーはソースコードにデバイス・ディレクティブを挿入して、アプリケーションの特定の領域を GPU にオフロードするようにコンパイラーに指示します。計算集約型のコードをオフロードすることで、適切なパフォーマンスを期待できます。

このセクションでは、OpenMP* オフロードに関連する以下のトピックと、オフロードされたコードのパフォーマンスを向上させる方法について説明します。

OpenMP* ディレクティブ

インテル® コンパイラー (icxicpx、および ifx) は、計算のオフロードとデバイスへのデータマッピングを制御するさまざまな OpenMP* デバイス・ディレクティブをサポートしています。これには以下のものがあります。

  • target
  • teams
  • distribute
  • target data
  • target enter data
  • target exit data
  • target update
  • declare target
  • dispatch

target 構造では、コードの特定の領域がデバイスで実行されること、およびデータがデバイスにどのようにマッピングされるかを指定します。

teams 構造は、プライマリー・スレッドと複数のワーカースレッドで構成されるスレッドのチームを作成します。teamsnum_teams 節なしで指定されると、チーム数は実装定義になります。

distribute 構造は、ループ反復を各チームのプライマリー・スレッドに分散させます。

target data 構造は、デバイスのデータ環境に変数をマップします。変数は、任意の map 節によって target data 領域の範囲にマッピングされます。

target enter data ディレクティブではデバイスへマップする変数を指定します。このディレクティブの map 節で指定されるマップタイプは、to または alloc である必要があります。

target exit data ディレクティブは、変数がデバイスからアンマップされることを指示します。このディレクティブの map 節で指定できるマップタイプは、fromrelease または delete です。

target update ディレクティブは、指定される motion 節に従って、デバイス上の変数値を元のホストの変数値と一致させます。

declare target ディレクティブは、デバイスにマップされる変数、関数 (C/C++、Fortran) およびサブルーチン (Fortran) を指定します。

declare variant ディレクティブはベース関数の特殊バリアントを宣言し、そのバリアントが使用されるコンテキストを指定します。

dispatch 構造は、関数呼び出しに対しバリアントへの置き換えを行うかどうかを制御します。declare variantdispatch ディレクティブは、target 構造内からインテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL) ルーチンを呼び出す際に役立ちます。

map 節は、元のホスト変数をデバイス上の対応する変数にどのようにマップするかを決定します。マップタイプには以下があります。

  • to: ホストのオリジナル変数が target 領域の入り口でデバイスにコピーされます。
  • from: デバイス上の変数の値は、target 領域の出口でデバイスから元のホスト変数にコピーされます。
  • tofrom: 元のホスト変数の値は、target 領域の入り口でデバイスにコピーされ、target 領域の出口でホストにコピーバックされます。
  • alloc: 元のホストの変数と同じタイプとサイズの変数をデバイスに割り当てます (値はホストからコピーされません)。

ディレクティブは組み合わせることができます。例えば、次のように組み合わせることができます。

  • target teams
  • target teams distribute
  • target teams distribute parallel for
  • target teams distribute parallel for simd

コンパイラーとランタイムがオフロードされたループ反復を GPU で実行するため、最良の方法で分割できるよう可能な限り複合ディレクティブを使用することを推奨します。

OpenMP* 実行モデル

OpenMP* 実行モデルでは、ホストデバイスは単一ですが、複数のターゲットデバイスを持つことができます。デバイスは論理実行エンジンであり、固有のローカルストレージとデータ環境を持ちます。

ATS と PVC で実行する場合、2 つのタイルで構成される 1 つのGPU デバイス、または各タイルをそれぞれデバイスと見なすこともできます。

OpenMP* はホスト上で実行を開始します。ホストスレッドが target 構造に到達すると、データはホストからデバイスに転送され (例えば、map 節で指定されている場合)、構造内のコードはデバイスにオフロードされます。target 領域の終端では、データはデバイスからホストに転送されます (指定されていれば)。

デフォルトでは、ホストスレッドは target 領域が完了するのを待って処理を続行します。target 構造に nowait 節が指定されると、ホストスレッドは target 領域の完了を待機せずに処理を続行します。つまり、nowait 節を使用すると target 領域を非同期に実行できます。

非同期に実行されるコード領域間の同期は、taskwait ディレクティブ、depend 節、(暗黙および明示的な) バリア、または他の同期メカニズムによって行うことができます。

用語

ここでは、オフロードされた並列ループの反復処理を説明するため、OpenMP* と DPC++ の用語を同じ意味で使用しています。

「DPC++ スレッド階層とマッピング」で説明したように、GPU にオフロードされた並列ループ (実行レンジ) の反復は、work-group、sub-group、そして work-item に分割されます。ND-range はすべての実行範囲を表しており、同じサイズの work-group に分割されます。work-group は、1 次元、2 次元、または 3 次元の work-item の集合です。各 work-group は sub-group に分割できます。sub-group は、SIMD ベクトルとして同時に処理される連続した work-item の短い範囲を表します。

次の表は、DPC++ の概念が OpenMP* と CUDA* の概念とどのように関連するかを示しています。

DPC++ OpenMP* CUDA*
ワーク項目 OpenMP* スレッドまたは SIMD レーン CUDA* スレッド
ワークグループ チーム スレッドブロック
ワークグループ・サイズ チームサイズ スレッド・ブロック・サイズ
ワークグループ数 チーム数 スレッドブロック数
サブグループ SIMD チャンク simdlen = 8、16、32) ワープ (size = 32)
work-group あたりの work-item の最大数 スレッドリミット スレッドブロックあたりの CUDA* スレッドの最大数

OpenMP* アプリケーションのコンパイルと実行

インテル® GPU へのオフロードを有効にするには、次のコンパイルオプションを使用します。

  • -qopenmp -fopenmp-targets=spir64 (Linux*)
  • /Qopenmp /Qopenmp-targets=spir64 (Windows*)

次のコンパイルオプションを追加して、コンパイラー最適化レポートの出力を有効にします。

  • -qopt-report=3 -O3 (Linux*)
  • /Qopt-report=3 /O3 (Windows*)

デフォルトでは、コンパイルは JIT (Just-In-Time) であるため、次のコンパイルコマンドを実行すると JIT コンパイルされます。

  • icx -fiopenmp -fopenmp-targets=spir64_gen <source_file> (Linux*)
  • icx /Qiopenmp /Qopenmp-targets=spir64_gen <source_file> (Windows*)

事前コンパイル (AOT) を行うには、次のコマンドを使用します。

ATS-P A0 ステッピング向け:

  • icx -fiopenmp -fopenmp-targets=spir64_gen -Xopenmp-target-backend "-device xehp" -Xopenmp-target-backend "-revision_id 1" <source_file>

ATS-P B0 ステッピング向け:

  • icx -fiopenmp -fopenmp-targets=spir64_gen -Xopenmp-target-backend "-device xehp" -Xopenmp-target-backend "-revision_id 4" <source_file>

デバイスに関連する環境変数には次のものがあります。

  • ZE_AFFINITY_MASK=0.0
    (1 タイルで実行)
  • EnableWalkerPartition=1
    (暗黙のスケーリングにより 2 タイルで実行)
  • OMP_TARGET_OFFLOAD=MANDATORY
    (デバイス構造またはデバイス・メモリー・ルーチンに到達した際に、デバイスが利用できない、または実装でサポートされていない場合にプログラムの実行が終了することを指定します)
  • LIBOMPTARGET_DEBUG=1
    (libomptarget.so ライブラリーからのデバッグ情報出力を有効にします)

デバイスに関連するランタイムルーチンには次のものがあります。

  • omp_target_alloc
  • omp_target_free
  • omp_target_memcpy

次のランタイムルーチンは、インテル® コンパイラーの拡張としてサポートされます。

  • omp_target_alloc_host
  • omp_target_alloc_device
  • omp_target_alloc_shared

omp_target_free を呼び出すと、インテル拡張のルーチンで割り当てたメモリーも解放できます。

icxicpx、および ifx コンパイラーでサポートされる OpenMP* 機能は以下を参照してください。

開発コード名


製品および性能に関する情報

1 性能は、使用状況、構成、その他の要因によって異なります。詳細については、http://www.intel.com/PerformanceIndex/ (英語) を参照してください。

タイトルとURLをコピーしました