C/C++ または Fortran と OpenMP* オフロード・プログラミング・モデル
インテル® oneAPI DPC++/C++ コンパイラーおよび、インテル® Fortran コンパイラーを使用すると、OpenMP* ディレクティブを使用してワークをインテルのアクセラレーター・デバイスにオフロードし、アプリケーションのパフォーマンスを向上できます。
このセクションでは、OpenMP* ディレクティブを使用して計算をアクセラレーター・デバイスにオフロードする方法について説明します。OpenMP* ディレクティブに慣れていない開発者は、インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス (英語) や インテル® Fortran コンパイラー・デベロッパー・ガイドおよびリファレンス (英語) の OpenMP* サポートのセクションで基本的な使い方をご覧いただけます。
注
OpenMP* は、FPGA デバイスではサポートされません。
基本的な OpenMP* target 構造
OpenMP* target 構造は、ホストからターゲットデバイスへ制御を移行するために使用されます。変数はホストとターゲットデバイスでマッピングされます。ホストスレッドは、オフロードされた計算が完了するまで待機します。ほかの OpenMP* タスクは、ホストで非同期に実行できます。それには、nowait 節を使用して、スレッドがターゲット領域の完了を待機しないようにします。
C/C++
次の C++ のコードは、SAXPY 計算をアクセラレーターにオフロードします。
#pragma omp target map(tofrom:fa), map(to:fb,a)
#pragma omp parallel for firstprivate(a)
for(k=0; k<FLOPS_ARRAY_SIZE; k++)
fa[k] = a * fa[k] + fb[k]配列 fa は、計算の入力と出力の両方で使用されるため、アクセラレーターの to と from にマップされます。配列 fb と変数 a は計算の入力であり変更されることがないため、その出力をコピーする必要はありません。 変数 FLOPS_ARRAY_SIZE はアクセラレーターに暗黙にマップされます。ループ・インデックス k は、OpenMP* に従って暗黙的にプライベートです。
Fortran
この Fortran のコードのコードスニペットは、行列乗算をアクセラレーターにオフロードします。
!$omp target map(to: a, b ) map(tofrom: c )
!$omp parallel do private(j,i,k)
do j=1,n
do i=1,n
do k=1,n
c(i,j) = c(i,j) + a(i,k) * b(k,j)
enddo
enddo
enddo
!$omp end parallel do
!$omp end target配列 a と b はアクセラレーターの入力にマップされ、配列 c はアクセラレーターの入力と出力にマップされます。変数 n はアクセラレーターに暗黙にマップされます。ループ・インデックスは OpenMP* 仕様に従って自動的に private となるため、private 節はオプションです。
map 変数
ホストとアクセラレーター間のデータ共有を最適化するため、target data ディレクティブは変数をアクセラレーターにマップし、変数はその領域の範囲内でターゲットのデータ領域に維持されます。この機能は、複数のターゲット領域にまたがって変数をマップするのに役立ちます。
C/C++
#pragma omp target data [clause[[,] clause],...]
構造化ブロックFortran
!$omp target data [clause[[,] clause],...]
構造化ブロック
!$omp end target data節の使用例
節には次の 1 つ以上を指定できます。詳細は、TARGET DATA (英語)を参照してください。
DEVICE (整数式)
IF ([TARGETDATA :] スカラー論理式)
MAP ([[マップタイプ修飾子 [,]] マップタイプ: ] リスト)
注
マップタイプには以下を複数指定できます:
alloctofromtofromdeleterelease
SUBDEVICE ([整数定数,] 整数式[ : 整数式[ : 整数式]])
USE_DEVICE_ADDR (リスト) //
ifxでのみ利用可能USE_DEVICE_PTR (ポインターリスト)
注
この SUBDEVICE 節は、以下のような場合に無視されます:
ZE_FLAT_DEVICE_HIERARCHY が FLAT または COMBINED に設定されている場合
env LIBOMPTARGET_DEVICES が SUBDEVICE/SUBSUBDEVICE に設定されている場合
env ONEAPI_DEVICE_SELECTOR を使用してデバイスが選択されている場合
DEVICE (integer-expression) IF ([TARGET DATA:] scalar-logical-expression) MAP ([[map-type-modifier[,]] map-type: alloc | to | from | tofrom | delete | release] list) SUBDEVICE ([integer-constant ,] integer-expression [ : integer-expression [ : integer-expression]]) USE_DEVICE_ADDR (list) // ifx でのみ利用可能 USE_DEVICE_PTR (ptr-list)
ホストの元の変数をデバイスの対応する変数と同期するには、target update ディレクティブ、または map 句内の always マップタイプ修飾子使用します。
OpenMP* TARGET を使用するコンパイル
次のコマンドは、OpenMP* target を使用するアプリケーションをコンパイルする例を示します。
C/C++
Linux*:
icx -fiopenmp -fopenmp-targets=spir64 code.c
Windows* (
icxまたはicpxを使用):icx /Qiopenmp /Qopenmp-targets=spir64 code.c
Fortran
Linux*:
ifx -fiopenmp -fopenmp-targets=spir64 code.f90
Windows*:
ifx /Qiopenmp /Qopenmp-targets=spir64 code.f90
OpenMP* オフロードの追加のリソース
インテルは、OpenMP* ディレクティブを使用してアクセラレーターをターゲットとする方法を示すサンプルコードを https://github.com/oneapi-src/oneAPI-samples/tree/master/DirectProgramming で提供しています。具体的なサンプルには以下があります。
行列乗算は、2 つの大きな行列を乗算して結果を検証する簡単なプログラムです。このプログラムは、SYCL* または OpenMP* の 2 つの方法で実装されます。
ISO3DFD OpenMP* オフロード サンプルは、等方性媒体における 3 次元差分波伝播のリファレンスです。ISO3DFD は、3D 等方性媒質を伝搬する波形をシミュレートする 3 次元ステンシルであり、複雑なアプリケーションで OpenMP* オフロード・デバイスをターゲットとして高いパフォーマンスを実現する一般的な課題といくつかの手法を示しています。
openmp_reduction は円周率を求める簡単なプログラムです。このプログラムは、インテル® アーキテクチャー・ベースの CPU およびアクセラレーター向けの C++ および OpenMP* により実装されています。
LLVM/OpenMP* ランタイム (英語) は、利用可能な各種タイプのランタイムについて説明しており、OpenMP* オフロードをデバッグする際に役立ちます。
oneAPI GPU 最適化ガイド (PDF) では、 GPU 上で oneAPI プログラムのパフォーマンスを最大限に引き出すヒントを提供します。
「インテルツールによる OpenMP* アプリケーションのオフロードと最適化」(英語) では、OpenMP* ディレクティブを使用してアプリケーションに並列処理を追加する方法について説明しています。
openmp.org にはサンプルのドキュメントがあります: https://www.openmp.org/wp-content/uploads/openmp-examples-4.5.0.pdf (英語)。例題ドキュメントの第 4 章では、アクセラレーターと target 構造に焦点を当てています。
有用な OpenMP* の書籍も数多くあります。リストについては、https://www.openmp.org/resources/openmp-books (英語) をご覧ください。
サポートされているオプションのリストやサンプルコードなど、OpenMP* オフロードでインテル® コンパイラーを使用する方法の詳細については、コンパイラー・デベロッパー・ガイドを参照してください: