インテル® oneAPI プログラミング・ガイド
Intel Corporationwww.intel.com (英語)
著作権と商標について

注意事項:
この日本語マニュアルは、インテル コーポレーションのウェブサイト https://software.intel.com/content/www/
us/en/develop/documentation/oneapi-programming-guide/top.html (英語) で公開されている『Intel® oneAPI
Programming Guide』 (バージョン 202３.2、更新日 2023/7/14) の参考訳です。
インテル社の許可を得て iSUS (IA Software User Society) が翻訳版を作成した iSUS の著作物です。
原文は Intel Corporation の Copyright であり、日本語参考訳版にも適用されます。

インテル® oneAPI プログラミング・ガイド

目次
1

はじめに ........................................................................................................................................................................................................... 7
1.1
oneAPI プログラミングの概要............................................................................................................................................................. 8
1.2
インテル® oneAPI ツールキットの配布について ......................................................................................................................... 9
1.3
関連ドキュメント ...................................................................................................................................................................................... 10
2oneAPI プログラミング・モデル ........................................................................................................................................................ 11
2.1
SYCL* を使用した C++ のデータ並列処理 .................................................................................................................................. 11
2.1.1
キューラムダ参照を使用した簡単なサンプルコード .................................................................................................... 11
2.1.2
関連情報............................................................................................................................................................................................. 13
2.2
C/C++ または Fortran と OpenMP* オフロード・プログラミング・モデル ................................................................... 13
2.2.1
基本的な OpenMP* target 構造 ............................................................................................................................................ 14
2.2.2
map 変数 ............................................................................................................................................................................................ 14
2.2.3
omp target を使用するコンパイル ................................................................................................................................... 16
2.2.4
OpenMP* オフロードの追加のリソース ............................................................................................................................. 16
2.3
デバイスの選択 .......................................................................................................................................................................................... 17
2.3.1
ホストコードでの DPC++ デバイス選択.............................................................................................................................. 17
2.3.2
デバイス選択の例........................................................................................................................................................................... 18
2.3.3
ホストコードでの OpenMP* デバイスの確認と選択 ..................................................................................................... 192.4
SYCL* スレッドとメモリー階層 .......................................................................................................................................................... 19
2.4.1
スレッド階層 ..................................................................................................................................................................................... 19
2.4.2
メモリー階層 .................................................................................................................................................................................... 20
3oneAPI 開発環境の設定 ....................................................................................................................................................................... 22
3.1
インストール・ディレクトリー ............................................................................................................................................................... 22
3.2
環境変数 ....................................................................................................................................................................................................... 22
3.3
setvars と vars ファイル................................................................................................................................................................. 22
3.4
modulefile (Linux* のみ) ................................................................................................................................................................ 23
3.5
Windows* で setvars スクリプトを使用 .................................................................................................................................. 23
3.5.1
コマンドライン引数....................................................................................................................................................................... 24
3.5.2
実行方法............................................................................................................................................................................................. 24
3.5.3
確認方法............................................................................................................................................................................................. 25
3.5.4
複数の実行 ........................................................................................................................................................................................ 25
3.5.5
ONEAPI_ROOT 環境変数 ........................................................................................................................................................... 26
3.5.6
Windows* で setvars.bat 設定ファイルを使用 ....................................................................................................... 26
3.5.7
Microsoft* Visual Studio* で setvars.bat スクリプトを自動化 ...................................................................... 30
3.6Linux* または macOS* で setvars スクリプトを使用 ........................................................................................................ 31
3.6.1
コマンドライン引数....................................................................................................................................................................... 31
3.6.2
実行方法............................................................................................................................................................................................. 32
3.6.3
確認方法............................................................................................................................................................................................. 32
3.6.4
複数の実行 ........................................................................................................................................................................................ 33
3.6.5
ONEAPI_ROOT 環境変数 ........................................................................................................................................................... 33
3.6.6
Linux* または macOS* で setvars.sh 設定ファイルを使用................................................................................ 34
3.6.7
Eclipse* で servars.sh スクリプトを自動化................................................................................................................ 37
3.6.8
SETVARS_CONFIG 環境変数の状態 .................................................................................................................................... 382

インテル® oneAPI プログラミング・ガイド

3.6.9
SETVARS_CONFIG 環境変数の定義 .................................................................................................................................... 38
3.7Linux* で modulefile を使用 ........................................................................................................................................................ 39
3.8
oneAPI アプリケーションで CMake* を使用 .............................................................................................................................. 44
4oneAPI プログラムのコンパイルと実行........................................................................................................................................ 46
4.1
単一ソースのコンパイル ....................................................................................................................................................................... 46
4.2
コンパイラーの起動................................................................................................................................................................................. 46
4.3
インテル® oneAPI DPC++/C++ コンパイラーの標準オプション ...................................................................................... 47
4.4
コンパイル例 .............................................................................................................................................................................................. 47
4.4.1
API ベースのコード ....................................................................................................................................................................... 48
4.4.2
ダイレクト・プログラミング........................................................................................................................................................ 50
4.5
コンパイルの手順 ..................................................................................................................................................................................... 51
4.5.1
従来のコンパイル手順 (ホストのみのアプリケーション) ............................................................................................. 51
4.5.2
SYCL* オフロードコードのコンパイル手順 ....................................................................................................................... 52
4.5.3
JIT のコンパイル手順 .................................................................................................................................................................. 52
4.5.4
AOT のコンパイル手順 ............................................................................................................................................................... 53
4.5.5
ファットバイナリー ......................................................................................................................................................................... 54
4.6
CPU 手順...................................................................................................................................................................................................... 55
4.6.1
従来の CPU 向け手順 .................................................................................................................................................................. 56
4.6.2
CPU オフロードの手順 ................................................................................................................................................................ 56
4.6.3
CPU へコードをオフロード ........................................................................................................................................................ 59
4.6.4
CPU コードの最適化 .................................................................................................................................................................... 60
4.6.5
CPU コマンドの例 ......................................................................................................................................................................... 60
4.6.6
CPU アーキテクチャー向けの事前 (AOT) コンパイル .................................................................................................. 61
4.6.7
複数の CPU コア上でバイナリーの実行をコントロール .............................................................................................. 61
4.7
GPU 手順 ..................................................................................................................................................................................................... 64
4.7.1
GPU オフロードの手順 ................................................................................................................................................................ 65
4.7.2
GPU コマンドの例 ......................................................................................................................................................................... 71
4.7.3
GPU アーキテクチャー向けの事前 (AOT) コンパイル .................................................................................................. 72
4.8
FPGA 手順 ................................................................................................................................................................................................... 72
4.8.1
FPGA 向けのコンパイルが特殊である理由 ....................................................................................................................... 73
4.8.2
SYCL* FPGA コンパイルの種別.............................................................................................................................................. 73
4.8.3
FPGA コンパイルオプション ..................................................................................................................................................... 77
4.8.4
設計のエミュレートとデバッグ ................................................................................................................................................ 81
4.8.5
シミュレーションによるカーネルの評価 ............................................................................................................................. 89
4.8.6
FPGA デバイスセレクター.......................................................................................................................................................... 96
4.8.7
FPGA IP オーサリング手順........................................................................................................................................................ 97
4.8.8
FPGA 高速再コンパイル ......................................................................................................................................................... 126
4.8.9
複数の FPGA イメージを作成 (Linux* のみ) .................................................................................................................. 130
4.8.10 FPGA BSP とボード ................................................................................................................................................................... 133
4.8.11複数の同種の FPGA デバイスをターゲットにする ................................................................................................. 137
4.8.12
複数のプラットフォームをターゲットにする.............................................................................................................. 138
4.8.13 FPGA-CPU インタラクション ................................................................................................................................................ 140
4.8.14 FPGA パフォーマンスの最適化 ............................................................................................................................................ 142
4.8.15 FPGA 向けの RTL ライブラリーを使用する .................................................................................................................... 142
4.8.16
サードパーティーのアプリケーションで SYCL* 共有ライブラリーを使用 ................................................... 154

3

インテル® oneAPI プログラミング・ガイド

4.8.17 IDE での FPGA ワークフロー ................................................................................................................................................ 159
5
API ベースのプログラミング ........................................................................................................................................................... 160
5.1
インテル® oneAPI DPC++ ライブラリー (インテル® oneDPL) ........................................................................................ 160
5.1.1
インテル® oneDPL ライブラリーの使い方 ...................................................................................................................... 161
5.1.2
インテル® oneDPL サンプルコード ................................................................................................................................... 161
5.2
インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL)............................................................................... 161
5.2.1
インテル® oneMKL の使い方 ................................................................................................................................................ 162
5.2.2
インテル® oneMKL サンプルコード................................................................................................................................... 163
5.3
インテル® oneAPI スレッディング・ビルディング・ブロック(インテル® oneTBB)...................................................... 166
5.3.1
インテル® oneTBB の使い方................................................................................................................................................. 167
5.3.2
インテル® oneTBB サンプルコード ................................................................................................................................... 167
5.4
インテル® oneAPI データ・アナリティクス・ライブラリー (インテル® oneDAL) ......................................................... 167
5.4.1
インテル® oneDAL の使い方 ................................................................................................................................................ 168
5.4.2
インテル® oneDAL サンプルコード ................................................................................................................................... 168
5.5
インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー (インテル® oneCCL)................................... 169
5.5.1
インテル® oneCCL の使い方 ................................................................................................................................................. 169
5.5.2
インテル® oneCCL サンプルコード.................................................................................................................................... 170
5.6
インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー(インテル® oneDNN) ................................ 170
5.6.1
インテル® oneDNN の使い方 ............................................................................................................................................... 170
5.6.2
インテル® oneDNN サンプルコード .................................................................................................................................. 172
5.7
インテル® oneAPI ビデオ・プロセシング・ライブラリー (インテル® oneVPL) ............................................................ 172
5.7.1
インテル® oneVPL の使い方 ................................................................................................................................................. 173
5.7.2
インテル® oneVPL サンプルコード.................................................................................................................................... 173
5.8
その他のライブラリー .......................................................................................................................................................................... 176
6
ソフトウェア開発プロセス ................................................................................................................................................................ 177
6.1
SYCL* と DPC++ へのコードの移行............................................................................................................................................. 177
6.1.1
C++ から SYCL* への移行 ...................................................................................................................................................... 177
6.1.2
DPC++ コンパイラーを使用した CUDA* から SYCL* への移行 ........................................................................... 177
6.1.3
OpenCL* コードから SYCL* への移行.............................................................................................................................. 178
6.1.4
CPU、GPU、および FPGA 間の移行 .................................................................................................................................... 178
6.2
コンポーザビリティー .......................................................................................................................................................................... 181
6.2.1
C/C++ OpenMP* および SYCL* のコンポーザビリティー ...................................................................................... 181
6.2.2
OpenCL* コードの相互運用性 ............................................................................................................................................. 183
6.3
DPC++ と OpenMP* オフロード処理のデバッグ .................................................................................................................. 183
6.3.1
SYCL* と OpenMP* 開発向けの oneAPI デバッグツール ...................................................................................... 184
6.3.2
オフロード処理のトレース ...................................................................................................................................................... 196
6.3.3
オフロード処理のデバッグ ...................................................................................................................................................... 198
6.3.4
オフロードのパフォーマンスを最適化 ............................................................................................................................... 215
6.4
パフォーマンス・チューニング・サイクル ...................................................................................................................................... 218
6.4.1
ベースラインの確定.................................................................................................................................................................... 218
6.4.2
オフロードするカーネルの特定 ............................................................................................................................................ 219
6.4.3
カーネルをオフロード ............................................................................................................................................................... 219
6.4.4
SYCL* アプリケーションの最適化 ...................................................................................................................................... 219
6.4.5
再コンパイル、実行、プロファイル、そして繰り返し...................................................................................................... 221
6.5
oneAPI ライブラリーの互換性 ........................................................................................................................................................ 222

4

インテル® oneAPI プログラミング・ガイド

6.6
7
8

SYCL* 拡張 .............................................................................................................................................................................................. 222
用語集 ......................................................................................................................................................................................................... 223
著作権と商標について ........................................................................................................................................................................ 226

5

インテル® oneAPI プログラミング・ガイド

このガイドでは次のことを学ぶことができます。


oneAPI プログラミングの概要: oneAPI、インテル® oneAPI ツールキット、および関連するリソースの基本を理
解します。



oneAPI プログラミング・モデル: C、C++、および Fortran の SYCL* および OpenMP* オフロード向けのoneAPI プログラミング・モデルについて紹介します。



oneAPI 開発環境の設定: oneAPI アプリケーションの開発環境の設定方法を説明します。



oneAPI プログラムのコンパイルと実行: 各種アクセラレーター (CPU、FPGA など) 向けのコードをコンパイルする詳細を説明します。

API ベースのプログラミング: 共通 API と関連ライブラリーの簡単な紹介、およびバッファーの使用法の詳細を説明します。



ソフトウェア開発プロセス: デバッガーやパフォーマンス・プロファイラーなど各種 oneAPI ツールを使用した
ソフトウェア開発手順の概要、および特定のアクセラレーター (CPU、FPGA など) 向けのコードの最適化を紹介します。

6

インテル® oneAPI プログラミング・ガイド

1

はじめに

現代のコンピューター・アーキテクチャーで高い計算パフォーマンスを達成するには、最適化され、電力効率に優れた、スケーラブルなコードが必要です。従来のハイパフォーマンス・コンピューティング (HPC) を始めとして AI、ビデオ解析、
データ解析においてハイパフォーマンスの需要は増え続けています。
中央処理装置 (CPU) とグラフィックス処理ユニット (GPU) は、計算エンジンの基本ですが、計算の需要が進化するにつれ、CPU と GPU の違いや、それぞれに最適なワークロードは必ずしも明確ではありません。
現代のワークロードの多様性から、単一のアーキテクチャーですべてのワークロードに対応するのは困難になっており、アーキテクチャーも多様化しています。必要とするパフォーマンスを達成するには、CPU、GPU、AI、および FPGA アクセ
ラレーターに配置されたスカラー、ベクトル、行列、および空間 (SVMS) アーキテクチャーの組み合わせが求められます。
今日、CPU とアクセラレーター (GPU など) 向けのコーディングには、異なる言語、ライブラリー、そしてツールを利用する必要があります。これは、それぞれのハードウェア・プラットフォームは個別のソフトウェア資産を必要とし、異なる
ターゲット・アーキテクチャー全体ではアプリケーション・コードの再利用が制限されることを意味します。
oneAPI プログラミング・モデルは、SYCL* と呼ばれるプログラミング言語と最新の C++ 機能を使用して並列処理を表現することにより、CPU とアクセラレーターのプログラミングを簡素化します。SYCL* は、単一のソース言語でホスト(CPU など) とアクセラレーター (GPU など) のコードの再利用を可能にし、実行とメモリーの依存関係を明確にします。
SYCL* コード内のマッピング機能により、ハードウェアまたはハードウェア・セットに最適化されたワークロードを実行するためアプリケーションが移行されます。アクセラレーターを使用できないプラットフォームでも、ホストを利用する
ことでデバイスコードの開発とデバッグを簡素化できます。
oneAPI は、既存の C/C++ または Fortran コードで OpenMP* オフロード機能を使用する CPU およびアクセラレー
ターのプログラミングもサポートします。
CPU と GPU のどちらを使用するか決定する方法については、「CPU と GPU: 両方を最大限に活用する」 (英語) を参照
してください。
oneAPI プログラミング・モデルを理解したら、『oneAPI GPU 最適化ガイド』でソフトウェアの最適化方法を理解してください。

注: すべてのプログラムにおいて、インテル® oneAPI が提供する単一プログラミング・モデルの恩恵を得られるわけではありません。プログラムに適しているかどうかは、設計、実装、およびプログ
ラムで使用する oneAPI プログラミング・モデルを理解する必要があります。

oneapi.com (英語) で oneAPI イニシアチブとプログラミング・モデルの詳細をご覧ください。このサイトでは、oneAPI仕様、SYCL* 言語ガイドと API リファレンスなど、その他のリソースが提供されます。

7

インテル® oneAPI プログラミング・ガイド

1.1 oneAPI プログラミングの概要
oneAPI プログラミング・モデルは、複数のワークロード・ドメインにまたがる広範囲のパフォーマンス・ライブラリーを含む、ハードウェア・ターゲット全体で利用できる開発者向けツールの包括的かつ統合された資源を提供します。ライブ
ラリーには、ターゲット・アーキテクチャーごとにカスタマイズされた関数が含まれているため、同じ関数呼び出しを使用して、サポートされるすべてのアーキテクチャーで最適なパフォーマンスを実現できます。
oneAPI プログラミング・モデル

上の図に示すように、oneAPI プログラミング・モデルを利用するアプリケーションは、CPU から FPGA まで複数のター
ゲット・ハードウェア・プラットフォームで実行できます。インテルは、一連のツールキットの一部として oneAPI 製品を提供しています。インテル® oneAPI ベース・ツールキットと、インテル® oneAPI HPC ツールキット、インテル® oneAPI
IoT ツールキット、およびその他のツールキットは、特定の開発者のワークロード要件を満たす補完的なツールを備えています。例えば、インテル® oneAPI ベース・ツールキットには、インテル® oneAPI DPC++/C++ コンパイラー、インテル® DPC++ 互換性ツール (インテル® DPCT)、ライブラリー、および解析ツールが含まれます。


既存の CUDA* コードを DPC++ コンパイラーでコンパイルするため SYCL* に移行しようとする開発者は、
インテル® DPCT を使用して既存のプロジェクトを DPC++ を使用した SYCL* に移行できます。

インテル® oneAPI DPC++/C++ コンパイラーは、アクセラレーターをターゲットとするコードのダイレクト・
プログラミングをサポートします。ダイレクト・プログラミングは、ユーザーコードで使用されるアルゴリズムでAPI が利用できない場合にパフォーマンスを向上するコーディング手法です。CPU と GPU ターゲット向けには
オンラインとオフラインコンパイルがサポートされ、FPGA ターゲット向けにはオフラインコンパイルのみがサポートされます。

8インテル® oneAPI プログラミング・ガイド

API ベースのプログラミングは、最適化済みのライブラリー・セットを介してサポートされます。oneAPI 製品で提供されるライブラリー関数は、サポートされるターゲット・アーキテクチャー向けに事前チューニングされているため、開発者の介在は必要ありません。例えば、インテル® oneMKL の BLAS ルーチンは、CPU ターゲットと同様に GPU ターゲットに最適化されています。



また、コンパイルされた SYCL* アプリケーションは、インテル® VTune™ プロファイラーやインテル® Advisorなどのツールを使用して、パフォーマンス、安定性、エネルギー効率の目標を達成するため、解析およびデバッグできます。

インテル® oneAPI ベース・ツールキットは、インテル® デベロッパー・ゾーン (英語) から無料でダウンロードできます。
インテル® Parallel Studio XE やインテル® System Studio を利用しているユーザーは、インテル® oneAPI HPC ツー
ルキット (英語) やインテル® oneAPI IoT ツールキット (英語) に興味を持つかもしれません。

1.2 インテル® oneAPI ツールキットの配布についてインテル® oneAPI ツールキットは、複数の配布経路から入手できます。


製品のローカル・インストール: インテル® デベロッパー・ゾーン (英語) からインテル® oneAPI ツールキットを
インストールします。特定のインストールに関する情報は、「インストール・ガイド」 (英語) を参照してください。



コンテナまたはリポジトリーからインストール: サポートされるコンテナまたはリポジトリーからインテル®
oneAPI ツールキットをインストールします。それぞれの手順については、「インストール・ガイド」 (英語) を参照
してください。



事前インストールされたインテル® デベロッパー・クラウド: 最新のインテル® ハードウェアにアクセスする無料の開発サンドボックスを使用して、インテル® oneAPI ツールを選択します。インテル® デベロッパー・クラウドの詳細 (英語) を確認して、無料アクセスにご登録ください。

9インテル® oneAPI プログラミング・ガイド

1.3 関連ドキュメント
次のドキュメントは、これから oneAPI プロジェクトを導入する開発者向けの入門資料として役立ちます。
インテル® oneAPI ツールキットの導入ガイド‐インテル® oneAPI ベース・ツールキット導入ガイド (Linux* | Windows* | MacOS*) (英語)‐インテル® oneAPI HPC ツールキット導入ガイド (Linux* | Windows* | MacOS*) (英語)‐インテル® oneAPI IoT ツールキット導入ガイド (Linux* | Windows*) (英語)インテル® oneAPI ツールキットのリリースノート‐インテル® oneAPI ベース・ツールキット (英語)‐インテル® oneAPI HPC ツールキット (英語)‐インテル® oneAPI IoT ツールキット (英語)

言語リファレンス

10‐

SYCL* 言語ガイドと API リファレンス (英語)‐SYCL* 仕様 PDF (バージョン 1.2.1) (英語)‐SYCL* 仕様 PDF (バージョン 2020) (英語 | 日本語)‐James Reinders, Ben Ashbaugh, James Broadman, Michael Kinsner, John Pennycook, and Xinmin
Tian 著 『Data Parallel C++：Mastering DPC++ for Programming of Heterogeneous Systems using
C++ and SYCL』 (英語) — 本書の一部は、Creative Commons のライセンス (英語) の下で再利用されています。

‐

LLVM/OpenMP* 関連のドキュメント (英語)‐

OpenMP* 仕様 (英語)インテル® oneAPI プログラミング・ガイド

2oneAPI プログラミング・モデル

ヘテロジニアス・コンピューティングでは、ホスト・プロセッサーはアクセラレーター・デバイスの利点を活用して、コードをより効率良く実行します。
oneAPI プログラミング・モデルは、データ並列 C++ (DPC++) および OpenMP* (Fortran、C、C++) の 2 つのヘテロジ
ニアス・コンピューティング方式をサポートします。
SYCL* はクロスプラットフォームの抽象化レイヤーで、アプリケーションのホストとカーネルのコードが同じソースファ
イルに含まれる、ヘテロジニアス・プロセッサー用のコードを標準的な ISO C++ を使用して記述することができます。
DPC++ オープンソース・プロジェクトは、LLVM C++ コンパイラーに SYCL* のサポートを追加しています。インテル®
oneAPI DPC++/C++ コンパイラーは、インテル® oneAPI ベース・ツールキットに含まれています。
OpenMP* は 20 年以上に渡り標準化されてきたプログラミング言語であり、インテルは OpenMP* 標準のバージョン
5 を実装しています。OpenMP* のオフロード機能をサポートするインテル® oneAPI DPC++/C++ コンパイラーは、インテル® oneAPI ベース・ツールキット、インテル® HPC ツールキット、そしてインテル® oneAPI IoT ツールキットに含まれます。OpenMP* オフロードをサポートするインテル® Fortran コンパイラー・クラシックとインテル® Fortran コン
パイラーは、インテル® oneAPI HPC ツールキットで提供されます。

注: OpenMP* は FPGA デバイスではサポートされません。

次のセクションでは、それぞれの言語について簡単に説明し詳細情報の参照先を示します。

2.1 SYCL* を使用した C++ のデータ並列処理
C++ で生産性の高いデータ並列プログラミングを行うオープンで、複数ベンダーによる、マルチアーキテクチャーのサポートは、SYCL* をサポートする標準 C++ によって実現されます。SYCL* (‘シクル’ と読みます) は、ロイヤルティー・
フリーのクロスプラットフォームの抽象化レイヤーで、アプリケーションのホストとカーネルのコードが同じソースファ
イルに含まれる、ヘテロジニアス・プロセッサー用のコードを標準的な ISO C++ を使用して記述することができます。
DPC++ オープンソース・プロジェクトは、LLVM C++ コンパイラーに SYCL* のサポートを追加しています。

2.1.1 キューラムダ参照を使用した簡単なサンプルコード
SYCL* の導入を示す最良の方法は、簡単なサンプルを使用することでしょう。SYCL* は最新の C++ をベースとしている
ため、この例ではラムダ式や一様初期化など近年 C++ に追加された、いくつかの機能を使用しています。開発者がこれらの機能に精通していなくても、それらの意味と機能はサンプルのコンテキストから明らかになります。SYCL* によるプ
ログラミングの経験を積んでいくと、これらの新しい C++機能は自然に受け入れられるでしょう。
次のサンプルコードは、a[0] = 0、a[1] = 1、... のように配列の各要素をそのインデックス値に設定します。

11インテル® oneAPI プログラミング・ガイド

1. #include <CL/sycl.hpp>
2. #include <iostream>3.
4. constexpr int num=16;
5. using namespace sycl;
6.
7. int main() {8.
auto r = range{num};
9.
buffer<int> a{r};10.
11.
queue{}.submit([&](handler& h) {12.
accessor out{a, h};13.
h.parallel_for(r, [=](item<1> idx) {14.
out[idx] = idx;
15.
});
16.
});
17.
18.
host_accessor result{a};19.
for (int i=0; i<num; ++i)20.
std::cout << result[i] << “\n”;
21. }最初に気付くことは、ソースファイルが 1 つしかないことです。つまり、ホストコードとオフロードされるアクセラレー
ター・コードの両方がこの単一のソースファイルから生成されます。次に注目すべき点は、構文が標準の C++ であるということです。並列処理を表現する新しいキーワードやプラグマは使用されていません。代わりに、並列処理は C++
クラスを介して表現されています。例えば、9 行目にある buffer クラスはデバイスにオフロードされるデータを表し、11 行目の queue クラスはホストからアクセラレーターへの接続を表します。
ロジックは次のように動作します。8 行目と 9 行目で、初期値を持たない 16 個の int 要素の buffer を作成します。
この buffer は配列のように作用します。11 行目でアクセラレーター・デバイスに接続するキュー (queue) を作成します。この簡単な例では、SYCL* ランタイムがデフォルトのアクセラレーター・デバイスを選択しますが、アプリケーション
によっては、システムのトポロジーを調査して特定のアクセラレーションを選択することもできます。キューが作成されると、この例では submit() メンバー関数を呼び出して、アクセラレーターにワークを送信します。この submit()
関数の引数はラムダ関数であり、ホスト上ですぐに実行されます。ラムダ関数は次の 2 つのことを行います。1 つは、
12 行目でアクセサーを作成します。アクセサーはバッファーの要素を書き込むことができます。次に、 13 行目でparallel_for() 関数を呼び出してコードをアクセラレーターで実行します。
parallel_for() の呼び出しには 2 つの引数があります。1 つはラムダ関数であり、もう 1 つはバッファー内の要素数を示す範囲オブジェクト r です。SYCL* は、ラムダ関数がレンジ内のインデックスごとに一度 (バッファー要素ごとに1 回)、アクセラレーターで呼び出されるように調整します。ラムダは、12 行目で作成された out アクセサーを使用してバッファー要素に値を割り当てるだけです。この簡単な例では、ラムダ呼び出し間に依存関係がないため、SYCL* はア
クセラレーターで最も効率良い方法で自由に並行して実行できます。
parallel_for() を呼び出した後、ホストのコードはアクセラレーターの完了を待たずに処理を続行します。ホストが次に行うことは、18 行目でバッファーの要素を読み取る host_accessor を作成することです。SYCL* は、このバッファーがアクセラレーターによって書き込まれたことを認識するため、host_accessor コンストラクター (18 行目)
は、parallel_for() によって送信されたワークが完了するまでブロックされます。アクセラレーターのワークが完了
すると、ホストコードは 18 行目以降を続行し、out アクセサーを使用してバッファーから値を読み取ります。

12インテル® oneAPI プログラミング・ガイド

2.1.2 関連情報
この SYCL* の概要は、完全なチュートリアルを目指すものではなく、言語機能の一部分を紹介するだけです。ローカル
メモリー、バリア、SIMD など一般にアクセラレーター・ハードウェアで使用するため学ぶべきことはほかにもたくさんあります。一度に複数のアクセラレーター・デバイスにワークを送信する機能もあり、1 つのアプリケーションが複数のデバイスで同時にワークを並行して実行することもできます。
以下のリソースは、DPC++ を使用して SYCL* を学習して習得するのに役立ちます。
「インテルのサンプルを使用した SYCL* の調査」 (英語) では、GitHub* から入手できるサンプル・アプリケー
ションの紹介とリンクを示しています。

「DPC++ 基礎サンプルコードのウォークスルー」 (英語) は、最初の一歩である「HelloWorld」アプリケーションに相当する DPC++ ベクトル加算のサンプルコードを詳しく見ていきます。



oneapi.com (英語) サイトでは、クラスとそれらのインターフェイスの説明が記載された『言語ガイドと API リ
ファレンス』 (英語) が公開されています。また、4 つのプログラミング・モデル (プラットフォーム、実行モデル、
メモリーモデル、およびカーネル・プログラミング・モデル) を詳しく説明しています。

「DPC++ エッセンシャル・トレーニング・コース」 (英語) は、インテル® デベロッパー・クラウドで Jupyter*
Notebook を使用するガイド付きの学習コースです。iSUS から日本語パッケージが提供されています。

『Data Parallel C++：Mastering DPC++ for Programming of Heterogeneous Systems using C++ andSYCL* (データ並列 C++：C++ と SYCL* を使用したヘテロジニアス・システムのプログラミング向けに DPC++を習得)』 (英語) は、SYCL* とヘテロジニアス・プログラミングに関連するプログラミングの概念と言語の詳細を紹介する書籍です。

2.2 C/C++ または Fortran と OpenMP* オフロード・プログラミング・
モデル
インテル® oneAPI DPC++/C++ コンパイラーおよびインテル® Fortran コンパイラーを使用すると、OpenMP* ディレク
ティブを使用してワークをインテルのアクセラレーター・デバイスにオフロードし、アプリケーションのパフォーマンスを向上できます。
このセクションでは、OpenMP* ディレクティブを使用して計算をアクセラレーター・デバイスにオフロードする方法について説明します。OpenMP* ディレクティブに慣れていない開発者は、『インテル® oneAPI DPC++/C++ コンパイラー・
デベロッパー・ガイドおよびリファレンス』 (英語) や『インテル® Fortran コンパイラー・デベロッパー・ガイドおよびリファレンス』 (英語) の OpenMP* サポートのセクションで基本的な使い方をご覧いただけます。

注: OpenMP* は FPGA デバイスではサポートされません。

13

インテル® oneAPI プログラミング・ガイド

2.2.1 基本的な 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,ndo i=1,ndo k=1,nc(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 節はオプションです。

2.2.2 map 変数
ホストとアクセラレーター間のデータ共有を最適化するため、target data ディレクティブは変数をアクセラレーターにマップし、変数はその領域の範囲内でターゲットのデータ領域に維持されます。この機能は、複数のターゲット領域にまたがって変数をマップするのに役立ちます。

14

インテル® oneAPI プログラミング・ガイド

C/C++#pragma omp target data [節[[,] 節],…]構造化ブロック

Fortran!$omp target data [節[[,] 節],…]構造化ブロック!$omp end target data

節の使用例
節には次の 1 つ以上を指定できます。詳細は、TARGET DATA (英語) を参照してください。


DEVICE (整数式)IF ([TARGET DATA :] スカラー論理式)



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

注: マップタイプには以下を複数指定できます。

‐

alloc

‐

to

‐

from

‐

tofrom‐delete‐release

SUBDEVICE ([整数定数,] 整数式[ : 整数式[ : 整数式]])

USE_DEVICE_ADDR (リスト) // ifx でのみ利用可能



USE_DEVICE_PTR (ポインターリスト)

DEVICE (整数式)
IF ([TARGET DATA :] スカラー論理式)
MAP ([[マップタイプ修飾子 [,]] マップタイプ: alloc | to | from | tofrom | delete | release] リスト)
SUBDEVICE ([整数定数,] 整数式[ : 整数式[ : 整数式]])USE_DEVICE_ADDR (リスト) // ifx でのみ利用可能
USE_DEVICE_PTR (ポインターリスト)

target update ディレクティブまたは、map 節で always マップ修飾子を使用して、ホストの変数をデバイスの対応する変数と同期することができます。
15

インテル® oneAPI プログラミング・ガイド

2.2.3 omp target を使用するコンパイル
次のコマンドは、OpenMP* target を使用するアプリケーションをコンパイルする例を示します。
C/C++Linux*:

$ icx -fiopenmp -fopenmp-targets=spir64 code.c

Windows* (icx または icpx を使用):

$ icx /Qiopenmp /Qopenmp-targets=spir64 code.c

FortranLinux*:

$ ifx -fiopenmp -fopenmp-targets=spir64 code.f90

Windows*:$ ifx /Qiopenmp /Qopenmp-targets=spir64 code.f90

2.2.4 OpenMP* オフロードの追加のリソース
インテルは、OpenMP* ディレクティブを使用してアクセラレーターをターゲットとする以下の具体的なサンプ
ルを、https://github.com/oneapi-src/oneAPI-samples/tree/master/DirectProgramming (英語) で提供しています。



具体的なサンプルには以下があります。

16‐

行列乗算 (英語) は、2 つの大きな行列を乗算して結果を検証する簡単なプログラムです。このプログラム
は、SYCL* または OpenMP* の 2 つの方法で実装されます。

‐

ISO3DFD (英語) サンプルは、等方性媒質における 3 次元有限差分波伝搬を参照しています。このサンプルは、3D 等方性媒質を伝搬する波形をシミュレートする 3 次元ステンシルであり、複雑なアプリケーショ
ンで OMP アクセラレーター・デバイスをターゲットとして高いパフォーマンスを実現する一般的な課題といくつかの手法を示しています。

‐

openmp_reduction (英語) は円周率を求める簡単なプログラムです。このプログラムは、インテル®
アーキテクチャー・ベースの CPU およびアクセラレーター向けの C++ および OpenMP* により実装されています。

インテル® oneAPI プログラミング・ガイド

OpenMP* オフロード機能の導入 (英語) では、サポートされるオプションやサンプルコードなど、インテル® コ
ンパイラーで OpenMP* オフロードを使用する方法の詳細については、インテル® コンパイラーのデベロッ
パー・ガイドおよびリファレンス』を参照してください。
‐

インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス (英語)‐インテル® Fortran コンパイラー・クラシックおよびインテル® Fortran コンパイラー・デベロッパー・ガイド
およびリファレンス (英語)

LLVM/OpenMP* ランタイム (英語) は、利用可能な各種タイプのランタイムについて説明しており、OpenMP*
オフロードをデバッグする際に役立ちます。



openmp.org の例題ドキュメントでは、第 4 章でアクセラレーターと target 構造に焦点を当てています。
https://www.openmp.org/wp-content/uploads/openmp-examples-4.5.0.pdf (英語)『Using OpenMP - the Next Step (OpenMP* を使用する - 次のステップ)』は、OpenMP* の優れた参考書籍です。第 6 章では、ヘテロジニアス・システムにおける OpenMP* のサポートについて説明しています。この書籍の追加情報については、https://www.openmp.org/tech/using-openmp-next-step (英語) をご覧ください。

2.3 デバイスの選択
デバイス (CPU、GPU または FPGA など) へのコードのオフロードは、DPC++ アプリケーションと OpenMP* アプリ
ケーションの両方で利用できます。

2.3.1 ホストコードでの DPC++ デバイス選択
ホストコードは明示的にデバイスタイプを選択できます。デバイスを選択には、キューを選択して次のいずれかのデバイスを初期化します。


default_selector

cpu_selector

gpu_selectoraccelerator_selector

default_selector が使用されると、カーネルは利用可能な計算デバイス (すべて、または SYCL_DEVICE_FILTER
環境変数の値に基づくサブセット) から選択するヒューリスティックに基づいて実行されます。

注: SYCL_DEVICE_FILTER は、インテル® oneAPI ツールキット 2023.1 で非推奨になりました。
代わりに、SYCL_DEVICE_SELECTOR を使用してください。

特定のデバイスタイプ (cpu_selector や gpu_selector) を使用する場合、指定されたデバイスタイプがプラットフォームで利用可能であるが、SYCL_DEVICE_FILTER で指定されるフィルターに含まれていなければなりません。
指定したデバイスが利用できない場合、ランタイムシステムはデバイスが利用できないことを示す例外をスローします。

17インテル® oneAPI プログラミング・ガイド

このエラーは、事前コンパイル (AOT) したバイナリーが、指定するデバイスタイプを含まないプラットフォームで実行される場合にスローされることがあります。

注: DPC++ アプリケーションは、サポートされる任意のターゲット・ハードウェアで実行できますが、特定のターゲット・ハードウェアで最高のパフォーマンスを引き出すにはチューニングが必要です。
例えば、CPU 向けにチューニングされたコードは、変更なしでは GPU アクセラレーターでは高速に実行できない可能性があります。

SYCL_DEVICE_FILTER は、DPC++ ランタイムで使用されるランタイム、計算デバイスタイプ、計算デバイス ID を利用可能なすべての組み合わせのサブセットに制御できる複雑な環境変数です。計算デバイス ID は、SYCL* API、
clinfo または sycl-ls (0 から始まる番号) によって返される ID に対応し、その ID を持つデバイスが特定のタイプであるか、特定のランタイムをサポートするかは関係ありません。プログラムが特定のセレクター (gpu_selectorなど) を使用して、SYCL_DEVICE_FILTER のフィルターで除外されたデバイスを要求すると、例外がスローされます。
使い方と設定可能な値の例については、GitHub* の環境変数の説明をご覧ください
https://github.com/intel/llvm/blob/sycl/sycl/doc/ EnvironmentVariables.md (英語)sycl-ls ツールを使用して、システムで利用可能なデバイスを確認できます。SYCL* や DPC++ プログラムを実行する前に、このツールでデバイスを確認することを推奨します 。sycl-ls は、SYCL_DEVICE_FILTER に設定されている文字列を各デバイスのプリフィクスとして出力します。sycl-ls の出力形式は、[SYCL_DEVICE_FILTER] プラット
フォーム名、デバイス名、デバイスのバージョン [ドライバーのバージョン] です。次の例で各行の先頭の角かっこ ([ ])で囲まれた文字列は、プログラムが実行される特定のデバイスを指定する SYCL_DEVICE_FILTER 文字列です。

2.3.2 デバイス選択の例$ sycl-ls[opencl:acc:0] Intel® FPGA Emulation Platform for OpenCL™, Intel® FPGA Emulation Device 1.2[2021.12.9.0.24_005321][opencl:gpu:1] Intel® OpenCL HD Graphics, Intel® UHD Graphics 630 [0x3e92] 3.0 [21.37.20939][opencl:cpu:2] Intel® OpenCL, Intel® Core™ i7-8700 CPU @ 3.20GHz 3.0 [2021.12.9.0.24_005321][level_zero:gpu:0] Intel® Level-Zero, Intel® UHD Graphics 630 [0x3e92] 1.1 [1.2.20939][host:host:0] SYCL host platform, SYCL host device 1.2 [1.2]

デバイス選択に関する詳しい情報は、『DPC++ 言語ガイドと API リファレンス』 (英語) で入手できます。

18

インテル® oneAPI プログラミング・ガイド

2.3.3 ホストコードでの OpenMP* デバイスの確認と選択
OpenMP* では、開発者がデバイス上でコードを実行できるか確認および設定する API が用意されています。ホスト
コードはデバイス番号を明示的に選択および設定できます。開発者は、オフロード領域ごとに device 句を使用して、オフロード領域を実行するターゲットデバイスを指定できます。


int omp_get_num_procs (void) API は、デバイスで使用可能なプロセッサー数を返します。

void omp_set_default_device(int device_num) API は、デフォルトのターゲットデバイスを設定します。

int omp_get_default_device(void) API は、デフォルトのターゲットデバイスを返します。



int omp_get_num_devices(void) API は、コードまたはデータをオフロードできるホスト以外のデバイスの数を返します。



int omp_get_device_num(void) API は、呼び出したスレッドが実行されているデバイスのデバイス番号を返します。



int omp_is_initial_device(int device_num) API は、現在のタスクがホストデバイスで実行されている場合は true を返し、それ以外は false を返します。



int omp_get_initial_device(void) API は、ホストデバイスを表すデバイス番号を返します。

開発者は、環境変数 LIBOMPTARGET_DEVICETYPE = [ CPU | GPU ] で実行するデバイスタイプを選択できます。
CPU や GPU のように特定のデバイスが指定される場合、そのデバイスがプラットフォームで利用可能であることが求められます。指定するデバイスが利用できない場合、ランタイムシステムは環境変数 OMP_TARGET_OFFLOAD に従って動作します。OMP_TARGET_OFFLOAD=mandatory の場合、要求されたデバイスが利用できないという意味のメッ
セージを出力します。それ以外の場合はベースデバイス (通常は CPU) でフォールバック実行されます。デバイスの選択に関する追加機能は、OpenMP* 5.1 仕様:で確認できます。
環境変数に関する詳細は、以下の GitHub* ページから入手できます。
https://github.com/intel/llvm/blob/sycl/sycl/doc/ EnvironmentVariables.md. (英語)
関連情報FPGA デバイスセレクター

2.4 SYCL* スレッドとメモリー階層
2.4.1 スレッド階層
SYCL* 実行モデルでは、GPU 実行の抽象化されたビューを提供します。SYCL* スレッド階層は、ワーク項目の 1 次元、
2 次元、または 3 次元のグリッドで構成され、work-group と呼ばれる同じサイズのスレッドグループにグループ化されます。work-group 内のスレッドはさらに、sub-group と呼ばれる同じサイズのベクトルグループに分割されます。

19インテル® oneAPI プログラミング・ガイド

この階層が GPU またはインテル® グラフィックスを搭載する CPU でどのように機能するかは、『oneAPI GPU 最適化ガイド』の「SYCL* スレッドのマッピングと GPU 占有率」を参照してください。

2.4.2 メモリー階層
汎用 GPU (GPGPU) 計算モデルは、1 つ以上の計算デバイスに接続されたホストで構成されます。それぞれの計算デバ
イスは、実行ユニット (EU) または Xe ベクトルエンジン (XVE) と呼ばれる多数の GPU 計算エンジン (CE) で構成されます。次の図に示すように、計算デバイスには、キャッシュ、共有ローカルメモリー (SLM)、高帯域幅メモリー (HBM) などが含まれることもあります。アプリケーションは、ホストのソフトウェア (ホスト・フレームワークごと) と、事前定義されたデカップリング・ポイントで VE で実行するためにホストから送信されたカーネルの組み合わせとして構築されます。

20

インテル® oneAPI プログラミング・ガイド

汎用 GPU (GPGPU) 計算モデル内のメモリー階層の詳細は、『oneAPI GPU 最適化ガイド』の「GPU 実行モデル概要」
を参照してください。

21

インテル® oneAPI プログラミング・ガイド

3oneAPI 開発環境の設定

インテル® oneAPI ツールは、このドキュメントの最初にある「インテル® oneAPI ツールキットの配布について」で説明するように、いくつかの形式で利用できます。『インテル® oneAPI インストール・ガイド』 (英語) の指示に従って、ツールを入手してインストールします。

3.1 インストール・ディレクトリー
Windows* システムでは、インテル® oneAPI 開発ツールは C:\Program Files (x86)\Intel\oneAPI\ ディレ
クトリーにインストールされます (デフォルト)。
Linux* と macOS* システムでは、インテル® oneAPI 開発ツールは /opt/intel/oneapi/ ディレクトリーにインストールされます (デフォルト)。

デフォルトのインストール先はインストール中に変更できます。
oneAPI インストール・ディレクトリー内には、開発システムにインストールされているコンパイラー、ライブラリー、解析
ツール、およびそのほかのツールを含むフォルダーが含まれます。正確なファイルは、インストールされるツールキットとインストール中に選択されるオプションによって異なります。oneAPI インストール・ディレクトリー内のほとんどのフォ
ルダーは、コンポーネント名に直結する分かりやすい名前が付いています。例えば、mkl フォルダーにはインテル®
oneMKL が含まれ、ipp フォルダーにはインテル® IPP ライブラリーが含まれます。

3.2 環境変数
インテル® oneAPI ツールキットの一部のツールは、次の環境変数に影響されます。


コンパイルとリンク処理の制御 (PATH、CPATH、INCLUDE など)

デバッガー、解析ツール、およびローカルヘルプの場所 (PATH、MANPATH など)



ツール固有のパラメーターと動的 (共有) リンク・ライブラリーの特定 (LD_LIBRARY_PATH、CONDA_* など)

3.3 setvars と vars ファイル
インストールされるすべてのインテル® oneAPI ツールキットには、親スクリプト setvars と、ツール固有のスクリプト
vars が含まれます (setvars.sh と vars.sh は Linux* と macOS*。setvars.bat と vars.bat は Windows*)。
これらのスクリプトが実行 (または source) されると、各インテル® oneAPI 開発ツールに必要なローカル環境変数が設定されます。

22

インテル® oneAPI プログラミング・ガイド

次のセクションでは、インテル® oneAPI の setvars と vars スクリプトを使用して、インテル® oneAPI 開発環境を初期化する方法を詳しく説明します。
Windows* で setvars スクリプトを使用

Linux* または macOS* で setvars スクリプトを使用

3.4 modulefile (Linux* のみ)
環境モジュール (英語) を利用するユーザーは、インテル® oneAPI ツールキットのインストール・パッケージに含まれる
modulefile ファイルを使用して、開発環境を初期化することがあります。インテル® oneAPI の modulefile スクリ
プトは Linux* 環境でのみサポートされており、setvars と vars スクリプトの代わりに使用することができます。
modulefile ファイルと setvars 環境スクリプトを混在して使用しないでください。
インテル® oneAPI の modulefile を使用して、インテル® oneAPI 開発環境を初期化する方法の詳細については、「Linux* で modulefile を使用」をご覧ください。

3.5 Windows* で setvars スクリプトを使用
ほとんどのインテル® oneAPI コンポーネントのフォルダーには、それぞれのコンポーネントに必要な環境変数を設定する vars.bat スクリプトが含まれています。例えば、デフォルトのインストールでは、Windows* のインテル® IPP のvars スクリプトは、C:\Program Files (x86)\Intel\oneAPI\ipp\latest\env\vars.bat に配置されます。このパスは、vars 環境変数設定スクリプトを含むすべてのインテル® oneAPI コンポーネントで共有されます。
これらの各コンポーネント向けの vars スクリプトは、直接またはまとめて呼び出すことができます。oneAPI インス
トール・ディレクトリーにある setvars.bat スクリプトを使用します。例えば、Windows* マシンのデフォルトのインス
トールでは、C:\Program Files (x86)\Intel\oneAPI\setvars.bat にあります。
引数なしで setvars.bat スクリプトを実行すると、システムにインストールされているすべての <コンポーネン
ト>\latest\env\vars.bat スクリプトが実行されます 。これらの環境変数設定スクリプトを実行した後、Windows* の set コマンドを使用して環境変数を確認できます。
Visual Studio* Code 開発者は、oneAPI 環境拡張機能をインストールして、Visual Studio* Code で setvars.bat
を実行できます。詳細については、「Visual Studio* Code でインテル® oneAPI ツールキットを使用する」 (英語) をご覧ください。

注: setvars.bat スクリプト (または個別の vars.bat スクリプト) により変更された環境は永続的ではありません。これらの変更は、setvars.bat スクリプトが実行された cmd.exe セッションでのみ有効です。

23

インテル® oneAPI プログラミング・ガイド

3.5.1 コマンドライン引数
setvars.bat スクリプトはいくつかのコマンドライン引数をサポートしており、--help オプションで引数の一覧を表示できます。

例:$ "C:\Program Files (x86)\Intel\oneAPI\setvars.bat" --help--config=file 引数と setvars.bat スクリプトから呼び出される vars.bat スクリプトへの追加引数をインクルードする機能を使用して、環境設定をカスタマイズできます。
--config=file 引数は、特定のインテル® oneAPI コンポーネントの環境の初期化機能を提供するとともに、特定のバージョンの環境を初期化することもできます。例えば、インテル® IPP ライブラリーとインテル® oneMKL の環境のみを設定するには、これら 2 つのインテル® oneAPI コンポーネントの vars.bat 環境スクリプトのみを呼び出すように
setvars.bat スクリプトに指示する設定ファイルを渡します。詳細と利用例については、「Windows* で setvars.batの設定ファイルを使用」をご覧ください。
setvars.bat のヘルプメッセージに記載されていないコマンドライン引数は、そのまま vars.bat スクリプトに渡されます。つまり、setvars.bat スクリプトが認識できない引数は、コンポーネントの vars.bat スクリプトで使用されるものと見なし、それらの引数をすべてのコンポーネントの vars.bat スクリプトに渡します。最もよく使用される追加の引数は、ia32 と intel64 です。これらは、インテル® コンパイラー、インテル® IPP、インテル® oneMKL、およびインテル® oneTBB ライブラリーでアプリケーションのターゲット・アーキテクチャーを指示するために使用されます。
システムに複数バージョンの Microsoft* Visual Studio* がインストールされている場合、vs2017、vs2019 またはvs2022 引数を setvars.bat コマンドラインに追加することで、Visual Studio* 環境のいずれかをインテル® oneAPI
環境の初期化に使用するかを指定できます。デフォルトでは、Visual Studio* の最新バージョンが使用されます。

注: Microsoft* Visual Studio* 2017 のサポートはインテル® oneAPI 2022.1 では非推奨となり、将来のリリースで削除される予定です。

個々の vars.bat スクリプトを調べて、受け入れるコマンドライン引数があればそれを決定します。

3.5.2 実行方法
<install-dir>\setvars.bat

PowerShell ウィンドウで setvars.bat または vars.bat スクリプトを実行するには、以下を使用します。
$ cmd.exe "/K" '"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" && powershell'

24インテル® oneAPI プログラミング・ガイド

3.5.3 確認方法
setvars.bat を実行した後、SETVARS_COMPLETED 環境変数で設定の成功を確認できます。setvars.bat が成功すると、SETVARS_COMPLETED には 1 が設定されます。
$ set | find "SETVARS_COMPLETED"戻り値
SETVARS_COMPLETED=1SETVARS_COMPLETED=1 以外の場合、setvars.bat は設定に失敗したことを意味します。

3.5.4 複数の実行
各コンポーネントの env\vars.bat スクリプトの多くは、PATH、CPATH、およびそのほかの環境変数に変更を加える
ため、最上位の setvars.bat スクリプトは同じセッションで同じ vars.bat を複数回呼び出すことはできません。
これは、特に %PATH% 環境変数が原因で環境変数の文字数が長くなりすぎないようにします。設定可能な文字数を超えると、ターミナルセッションで予期しない動作を招くことがあるため回避する必要があります。
これを強制するには、setvars.bat に --force オプションを指定します。この例では、ユーザーが setvars.bat
を 2 度実行しています。setvars.bat がすでに実行されているため、2 回目の実行は停止します。
$ <install-dir>\setvars.bat
initializing environment ...
(SNIP: lot of output)
oneAPI environment initialized$ <install-dir>\setvars.bat.. code-block:: WARNING: setvars.bat has already been run.Skipping re-execution.
To force a re-execution of setvars.bat, use the '--force' option.
Using '--force' can result in excessive use of your environment variables.

次は、ユーザーが <install-dir>\setvars.bat --force を実行し、初期化が成功した例です。
$ <install-dir>\setvars.bat –force
initializing environment ...
(SNIP: lot of output)
oneAPI environment initialized25インテル® oneAPI プログラミング・ガイド

3.5.5 ONEAPI_ROOT 環境変数
ONEAPI_ROOT 環境変数は、スクリプトが実行されるときに最上位の setvars.bat によって設定されます。
ONEAPI_ROOT 環境変数がすでに設定されている場合、setvars.bat はスクリプトを実行した cmd.exe セッション
を一時的に上書きします。この変数は、oneapi-cli サンプルブラウザーと Microsoft* Visual Studio* および Visual
Studio* Code サンプルブラウザーによって使用され、インテル® oneAPI ツールとコンポーネントの検出、および
SETVARS_CONFIG 機 能 が 有 効 で あ る 場 合 に setvars.bat ス ク リ プ ト を 検 出 す る の に 役 立 ち ま す 。
SETVARS_CONFIG 機能の詳細については、「Microsoft* Visual Studio* で setvars.bat スクリプトを自動化」をご覧ください。
Windows* システムでは、インストーラーは ONEAPI_ROOT 変数を環境に追加します。

3.5.6 Windows* で setvars.bat 設定ファイルを使用
setvars.bat スクリプトは、それぞれの oneAPI ディレクトリーにある <install-dir>\latest\env\vars.bat ス
クリプトを実行することで、インテル® oneAPI ツールキットの環境変数を設定します。setvars.bat スクリプトを自動実行しないように Windows* システムを設定しない限り、新しいターミナルウィンドウを開くか Visual Studio*、
Sublime Text*、またはそのほかの C/C++ エディターを起動するたびに setvars.bat スクリプトが実行されます。詳細は、「システムの設定」 (英語) を参照してください。
次に設定ファイルを使用して環境変数を管理する方法を説明します。

3.5.6.1.

バージョンと構成

一部のインテル® oneAPI ツールは複数バージョンのインストールがサポートされます。複数バージョンをサポートする
ツールのディレクトリー構造は次のようになります (デフォルトのインストールを想定し、例としてコンパイラーを使用します)。
\Program Files (x86)\Intel\oneAPI\compiler\|-- 2021.1.1|-- 2021.2.0`-- latest -> 2021.2.0

26

インテル® oneAPI プログラミング・ガイド

例:

すべてのツールには、そのコンポーネントの最新バージョンのインストール先を示す latest という名前のショート
カットがあります。latest\env\ ディレクトリーにある vars.bat スクリプトは、setvars.bat によって実行されます (デフォルト)。
必要に応じて、設定ファイルを使用して特定のディレクトリーを示すよう setvars.bat をカスタマイズできます。

3.5.6.2.

--config パラメーター

最上位の setvars.bat スクリプトは、カスタム config.txt ファイルを指定する --config パラメーターを受け入れます。
$ <install-dir>\setvars.bat --config="path\to\your\config.txt"

設定ファイルは任意の名前にすることができます。複数の設定ファイルを作成して、さまざまな開発環境やテスト環境を設定できます。例えば、最新バージョンのライブラリーを古いバージョンのコンパイラーでテストしたいこともあります。
そのような場合に、setvars 設定ファイルを使用して環境を管理できます。

3.5.6.3.

設定ファイルの例

以下に簡単な設定ファイルの例を示します。
最新のコンポーネントをすべてロード
mkl=1.1
dldt=exclude

ただし以下のコンポーネントは除外
default=exclude
mkl=1.0
ipp=latest

27

インテル® oneAPI プログラミング・ガイド

設定テキストファイルは次の要件に従う必要があります。


改行で区切られたテキストファイル

各行は、key=value のペアで構成されます

key には、oneAPI ディレクトリーの最上位 (%ONEAPI_ROOT% ディレクトリーにあるフォルダー) のコンポーネ
ント名を指定します。同じ key が設定ファイルに複数定義されると、最後の key が優先されそれ以外は無視
されます。



value には、コンポーネント・ディレクトリーの最上位にあるバージョン・ディレクトリー名を指定します。これには、コンポーネント・ディレクトリーのレベルに存在する可能性があるショートカット (latest など) が含まれます。
‐

また、value は exclude にすることもできます。これは、指定された key の vars.bat スクリプトを
setvars.bat スクリプトで実行しないことを意味します。

key=value を default=exclude にすると特別な意味を持ちます。これは、設定ファイルに定義されているものを除き、それ以外のすべての env\vars.bat スクリプトの実行を除外します。以下に例を示します。

3.5.6.4.

設定ファイルのカスタマイズ

設定ファイルを使用して、特定のコンポーネントを除外したり、特定のバージョンを含めたり、特定のコンポーネントのバージョンのみを含めることができます。これには、設定ファイルの default=exclude 行を変更します。
デフォルトでは、setvars.bat は最新 (latest) のバージョンに対応する env\vars.bat スクリプトを処理します。
例えば、2 つのバージョン (2021.1.1 と 2021.2.0) のインテル® oneMKL がインストールされていると仮定します。最新のバージョンを示すショートカットは 2021.2.0 であるため、デフォルトでは setvars.bat は mkl ディレクトリーの 2021.2.0 の vars.bat スクリプトを実行します。
2 つのバージョンのインテル® oneMKL と設定ファイル28

インテル® oneAPI プログラミング・ガイド

特定のバージョンを指定
setvars.bat に <install-dir>\mkl\2021.1.1\env\vars.bat スクリプトを実行するように直接記述するには、設定ファイルに mkl=2021.1.1 を追加します。
これにより、setvars.bat は、mkl ディレクトリー内の 2021.1.1 フォルダーにある env\vars.bat スクリプトを実行するようになります。インストールされている mkl 以外のコンポーネントでは、setvars.bat は最新バージョンのフォ
ルダーにある env\vars.bat スクリプトを実行します。
特定のコンポーネントを除外
コンポーネントを除外する構文は次のようになります。
<key>=exclude

例えば、インテル® IPP を除外して、2021.1.1 の インテル® oneMKL を含めるには次のようになります。
mkl=2021.1.1
ipp=exclude

この例は次のように作用します。


setvars.bat は、インテル® oneMKL 2021.1.1 の env\vars.bat スクリプトを実行します。

setvars.bat は、インテル® IPP の env\vars.bat スクリプトを実行しません。

setvars.bat は、そのほかのコンポーネントの最新バージョンの env\vars.bat スクリプトを実行します。

特定のコンポーネントを含める
特 定 の コ ン ポ ー ネ ン ト の env\vars.bat ス ク リ プ ト を 実 行 す る に は 、 最 初 に す べ て の コ ン ポ ー ネ ン ト の
env\vars.bat スクリプトを除外する必要があります。その後、setvars.bat で実行するコンポーネントを追加し直します。次の行を定義して、すべてのコンポーネントの env\vars.bat スクリプトを実行から除外します。
default=exclude

そして、setvars.bat がインテル® oneMKL とインテル® IPP の env/vars.bat スクリプトのみを 実行するには、次の行を追加します。
default=exclude
mkl=2021.1.1
ipp=latest

この例は次のように作用します。


setvars.bat は、インテル® oneMKL 2021.1.1 の env\vars.bat スクリプトを実行します

setvars.bat は、インテル® IPP の最新バージョンの env\vars.bat スクリプトを実行します。

29

インテル® oneAPI プログラミング・ガイド

setvars.bat は、そのほかのコンポーネントの env\vars.bat スクリプトを実行しません。

3.5.7 Microsoft* Visual Studio* で setvars.bat スクリプトを自動化
注: Microsoft* Visual Studio* 2017 のサポートはインテル® oneAPI 2022.1 では非推奨となり、将来のリリースで削除される予定です。

setvars.bat スクリプトは、インテル® oneAPI ツールキットを使用するために必要な環境変数を設定します。このス
クリプトは、コマンドライン開発向けに新しいターミナルウィンドウを開くたびに実行する必要があります。
setvars.bat スクリ プト はま た、 Microsoft* Visual Studio* の 起 動時に自 動 的に実行 す るこ とも できます 。
SETVARS_CONFIG 環境変数を使用して setvars.bat スクリプトにインテル® oneAPI ツール固有の設定を行うよ
うに指示できます。

3.5.7.1.

SETVARS_CONFIG 環境変数の状態

SETVARS_CONFIG 環境変数を使用して、Microsoft* Visual Studio* のインスタンスを起動したときにインテル®
oneAPI 開発環境を自動的に設定できます。環境変数には 3 つの条件と状態があります。


未定義 (SETVARS_CONFIG 環境変数が存在しない)

定義されているが空 (値を含まないか空白である)

setvars.bat 設定ファイルを示すように定義

SETVARS_CONFIG が定義されていないと、Visual Studio* 起動時に setvars.bat スクリプトは自動実行されません。SETVARS_CONFIG 環境変数は、インテル® oneAPI インストーラーによって定義されないため、これがデフォルト
動作です。
SETVARS_CONFIG に値が設定されず空白のみが含まれる場合、Visual Studio* の起動時に setvars.bat スクリプ
トは自動的に実行されます。この場合、setvars.bat スクリプトはシステムにインストールされているすべての
oneAPI ツールの環境を初期化します。setvars.bat スクリプトの実行の詳細については、「Visual Studio* コマン
ドラインを使用したサンプル・プロジェクトのビルドと実行」 (英語) を参照してください。
SETVARS_CONFIG に setvars 設定ファイルへの絶対パスが定義されている場合、Visual Studio* の起動時にsetvars.bat スクリプトは自動的に実行されます。この場合、setvars.bat スクリプトは、setvars 設定ファイルで定義されるインテル® oneAPI ツールのみの環境を初期化します。setvars 設定ファイルを作成する方法の詳細は、「setvars.bat の設定ファイルを使用」をご覧ください。
setvars 設定ファイルは任意のファイル名にでき、Visual Studio* がその場所とファイルにアクセスして読み取り可能である限り、ハードディスク上の任意の場所に保存できます (Windows* システムにインテル® oneAPI ツールをインストールする際に、Visual Studio* に追加されるプラグインは SETVARS_CONFIG のアクションを実行します。そのため、Visual Studio* は setvars 設定ファイルの場所にアクセスできる必要があります)。

30

インテル® oneAPI プログラミング・ガイド

setvars 設定ファイルを空のままにすると、setvars.bat スクリプトはシステムにインストールされているすべてのインテル® oneAPI ツールの環境を初期化します。これは、SETVARS_CONFIG 変数に空の文字列を定義するのと同じです。setvars 設定ファイルの定義の詳細については、「setvars.bat の設定ファイルを使用」を参照してください。

3.5.7.2.

SETVARS_CONFIG 環境変数の定義

SETVARS_CONFIG 環境変数は、インストール中に自動的に定義されないため、Visual Studio* を起動する前に(上記の規則に従って) 手動で環境変数を定義する必要があります)。SETVARS_CONFIG 環境変数は、Windows* のSETX コマンド、または Windows* GUI ツールで Win + R キーを押して表示されるダイアログに rundll32.exe
sysdm.cpl,EditEnvironmentVariables と入力して定義できます。

3.6 Linux* または macOS* で setvars スクリプトを使用
ほとんどのインテル® oneAPI コンポーネントのフォルダーには、それぞれのコンポーネントに必要な環境変数を設定する vars.sh スクリプトが含まれています。例えば、デフォルトのインストールでは、Linux* または macOS* のインテル® IPP の vars スクリプトは、/opt/intel/oneapi/ipp/latest/env/vars.sh に配置されます。このパスは、vars スクリプトを含むすべてのインテル® oneAPI コンポーネントで共有されます。
これらの各コンポーネント向けの vars スクリプトは、直接またはまとめて呼び出すことができます。まとめて呼び出すには、インテル® oneAPI インストール・ディレクトリーにある setvars.sh スクリプトを使用します。例えば、Linux* やmacOS* マシンのデフォルトのインストール先は、/opt/intel/oneapi/setvars.sh になります。
引数なしで setvars.sh スクリプトを実行すると、システムにインストールされているすべての <コンポーネン
ト>/latest/env/vars.sh スクリプトが source されます。これらのスクリプトを source した後、env コマ
ンドを使用して環境変数を確認できます。

注: setvars.sh スクリプト (または個別の vars.sh スクリプト) により変更された環境は永続的ではありません。これらの変更は、setvars.sh 環境スクリプトが source されたターミナル
セッションでのみ有効です。

3.6.1 コマンドライン引数
setvars.sh スクリプトはいくつかのコマンドライン引数をサポートしており、--help オプションで引数の一覧を表示できます。

例:$ source /opt/intel/oneapi/setvars.sh --help

31

インテル® oneAPI プログラミング・ガイド--config=file 引数と setvars.sh スクリプトから呼び出される vars.sh スクリプトへの追加引数をインクルードする機能を使用して、環境設定をカスタマイズできます。
--config=file 引数は、特定のインテル® oneAPI コンポーネントの環境の初期化機能を提供するとともに、特定のバージョンの環境を初期化することもできます。例えば、インテル® IPP とインテル® oneMKL の環境のみを設定するには、これら 2 つのインテル® oneAPI コンポーネントの vars.sh 環境スクリプトのみを呼び出すように setvars.sh
スクリプトに指示する設定ファイルを渡します。詳細と利用例については、「Linux* または macOS* で setvars.sh 設定
ファイルを使用」をご覧ください。
setvars.sh のヘルプメッセージに記載されていないコマンドライン引数は、vars.sh スクリプトに渡されます。
つまり、setvars.sh スクリプトが認識できない引数は、コンポーネントの vars.sh スクリプトで使用されるものと見なし、それらの引数をすべてのコンポーネントの vars.sh スクリプトに渡します。最もよく使用される追加の引数は、ia32 と intel64 です。これらは、インテル® コンパイラー、インテル® IPP、インテル® oneMKL、およびインテル®
oneTBB ライブラリーでアプリケーションのターゲット・アーキテクチャーを指示するために使用されます。
個々の vars.sh スクリプトを調べて、受け入れるコマンドライン引数があればそれを決定します。

3.6.2 実行方法
$ source <install-dir>/setvars.sh

注:
csh など非 POSIX* シェルを使用する場合、次のコマンドを使用します。
$ bash -c 'source <install-dir>/setvars.sh ; exec csh'
または、modulefile スクリプトを使用して開発環境を設定します。modulefile スクリプトは、
すべての Linux* シェルで機能します。
コンポーネントのリストとコンポーネントのバージョンを調整するには、setvars (英語) 設定ファイルを使用して開発環境を設定します。

3.6.3 確認方法
setvars.sh を source した後、SETVARS_COMPLETED 環境変数で source の成功を確認できます。setvars.shが成功すると、SETVARS_COMPLETED には 1 が設定されます。
$ env | grep SETVARS_COMPLETED

戻り値
SETVARS_COMPLETED=132

インテル® oneAPI プログラミング・ガイド

SETVARS_COMPLETED=1 以外の場合、setvars.sh は設定に失敗したことを意味します。

3.6.4 複数の実行
各コンポーネントの env/vars.sh スクリプトの多くは、PATH、CPATH、およびそのほかの環境変数に変更を加えるた
め、最上位の setvars.sh スクリプトは同じセッションで同じ vars.sh を複数回呼び出すことはできません。これは、
特に $PATH 環境変数が原因で環境変数の文字数が長くなりすぎないようにします。
これを強制するには、setvars.sh に --force オプションを指定します。この例では、ユーザーが setvars.sh を
2 回実行しています。setvars.sh がすでに実行されているため、2 回目の実行は停止します。
$ source <install-dir>/setvars.sh.. code-block:: initializing environment ...
(SNIP: lot of output).. code-block:: oneAPI environment initialized ::$ source <install-dir>/setvars.sh.. code-block:: WARNING: setvars.sh has already been run.Skipping re-execution.
To force a re-execution of setvars.sh, use the '--force' option.
Using '--force' can result in excessive use of your environment variables

次は、ユーザーが setvars.sh --force を実行し、初期化が成功した例です。
$ source <install-dir>/setvars.sh --force.. code-block:: initializing environment ...(SNIP: lot of output).. code-block:: oneAPI environment initialized ::3.6.5 ONEAPI_ROOT 環境変数
ONEAPI_ROOT 環 境 変 数は 、 スク リ プト が 実 行 され ると き に最 上 位 の setvars.sh に よ って 設定 され ます 。
ONEAPI_ROOT 環境変数がすでに設定されている場合、setvars.sh スクリプトはそれを上書きします。この変数は、
oneapi-cli サンプルブラウザーと Eclipse* および Visual Studio* Code サンプルブラウザーによって使用され、
イ ン テ ル ® oneAPI ツ ー ル と コ ン ポ ー ネ ン ト の 検 出 、 お よ び SETVARS_CONFIG 機 能 が 有 効 で あ る 場 合 にsetvars.sh スクリプトを検出するのに役立ちます。SETVARS_CONFIG 機能の詳細については、「Eclipse* で
setvars.sh スクリプトを自動化」をご覧ください。
Linux* と macOS* システムでは、インストーラーは ONEAPI_ROOT 環境変数を追加しません。これをデフォルト環境に追加するには、ローカルシェルの初期化ファイル (.bashrc など) または /etc/environment ファイルでONEAPI_ROOT 変数を定義します。

33

インテル® oneAPI プログラミング・ガイド

3.6.6 Linux* または macOS* で setvars.sh 設定ファイルを使用
Linux* で環境を設定するには、次の 2 つの方法があります。


このページで示すように、setvars.sh 設定ファイルを使用します。



modulefile を使用します。

setvars.sh スクリプトは、それぞれの oneAPI ディレクトリーにある <install-dir>/latest/env/vars.sh
スクリプトを source することで、インテル® oneAPI ツールキットで使用する環境変数を設定します。setvars.sh
スクリプトを自動的に source するように Linux* システムを設定しない限り、新しいターミナルウィンドウを開くか
Eclipse* またはそのほかの C/C++ IDE やエディターを起動する前に source する必要があります。詳細は、「システムの設定」 (英語) を参照してください。
次に設定ファイルを使用して環境変数を管理する方法を説明します。

3.6.6.1.

バージョンと構成

一部のインテル® oneAPI ツールは複数バージョンのインストールがサポートされます。複数バージョンのサポートする
ツールのディレクトリー構造は次のようになります。
intel/oneapi/compiler/ |-- 2021.1.1|-- 2021.2.0`-- latest -> 2021.2.0

例: 複数バージョンと環境変数

すべてのツールには、そのコンポーネントの最新バージョンのインストール先を示す latest という名前のシンボリッ
ク・リンクがあります。latest/env/ ディレクトリーにある vars.sh スクリプトは、setvars.sh によって source
されます (デフォルト)。
必要に応じて、設定ファイルを使用して特定のディレクトリーを示すよう setvars.sh をカスタマイズできます。

3.6.6.2.

--config パラメーター

最上位の setvars.sh スクリプトは、カスタム config.txt ファイルを指定する --config パラメーターを受け入れます。
$ source <install-dir>/setvars.sh --config="full/path/to/your/config.txt"
34

インテル® oneAPI プログラミング・ガイド

設定ファイルは任意の名前にすることができます。複数の設定ファイルを作成して、さまざまな開発環境やテスト環境を設定できます。例えば、最新バージョンのライブラリーを古いバージョンのコンパイラーでテストしたいこともあります。
そのような場合に、setvars 設定ファイルを使用して環境を管理できます。

3.6.6.3.

設定ファイルの例

以下に簡単な設定ファイルの例を示します。
最新のコンポーネントをすべてロード
mkl=1.1
dldt=exclude

ただし以下のコンポーネントは除外
default=exclude
mkl=1.0
ipp=latest

設定テキストファイルは次の要件に従う必要があります。


改行で区切られたテキストファイル

各行は、key=value のペアで構成されます

key には、oneAPI ディレクトリーの最上位 ($ONEAPI_ROOT ディレクトリーにあるフォルダー) のコンポーネ
ント名を指定します。同じ key が設定ファイルに複数定義されると、最後の key が優先されそれ以外は無視
されます。



value には、コンポーネント・ディレクトリーの最上位にあるバージョン・ディレクトリー名を指定します。これには、コンポーネント・ディレクトリーのレベルに存在する可能性があるショートカット (latest など) が含まれます。
‐

また、value は exclude にすることもできます。これは、指定された key の 環境変数 スクリプトを
setvars.sh スクリプトで source しないことを意味します。

key=value を default=exclude にすると特別な意味を持ちます。これは、設定ファイルに定義されているものを除き、それ以外のすべての env/vars.sh スクリプトの source を除外します。以下に例を示します。

3.6.6.4.

設定ファイルのカスタマイズ

設定ファイルを使用して、特定のコンポーネントを除外したり、特定のバージョンを含めたり、特定のコンポーネントのバージョンのみを含めることができます。これには、設定ファイルの default=exclude 行を変更します。
デフォルトでは、setvars.sh は最新 (latest) のバージョンに対応する env/vars.sh スクリプトを処理します。

35インテル® oneAPI プログラミング・ガイド

例えば、2 つのバージョン 2021.1.1 と 2021.2.0) のインテル® oneMKL がインストールされていると仮定します。最新のバージョンを示す symlink は 2021.2.0 であるため、デフォルトでは setvars.sh は mkl ディレクトリーの2021.2.0 の vars.sh スクリプトを実行します。
2 つのバージョンのインテル® oneMKL がインストールされている場合

特定のバージョンを指定
setvars.sh に <install-dir>/mkl/2021.1.1/env スクリプトを source するように直接記述するには、設定ファイルに mkl=2021.1.1 を追加します。
これにより、setvars.sh は、mkl ディレクトリー内の 2021.1.1 フォルダー にある env/vars.sh スクリプトを
source するようになります。インストールされている mkl 以外のコンポーネントでは、setvars.sh は最新バージョンのフォルダーにある env/vars.sh スクリプトを source します。
特定のコンポーネントを除外
コンポーネントを除外する構文は次のようになります。
<key>=exclude

36

インテル® oneAPI プログラミング・ガイド

例えば、インテル® IPP を除外して、2021.1.1 の インテル® oneMKL を含めるには次のようにします。
mkl=2021.1.1
ipp=exclude

この例は次のように作用します。


setvars.sh は、インテル® oneMKL 2021.1.1 の env/vars.sh スクリプトを source します。

setvars.sh は、インテル® IPP の env/vars.sh スクリプトを source しません。

setvars.sh は、そのほかのコンポーネントの最新バージョンの env/vars.sh スクリプトを source します。

特定のコンポーネントを含める
特定のコンポーネントの env/vars.sh スクリプトを source するには、最初にすべてのコンポーネントのenv/vars.sh スクリプトを除外する必要があります。その後、setvars.sh で source するコンポーネントを追加し直します。次の行を定義して、すべてのコンポーネントの env/vars.sh スクリプトを source から除外します。
default=exclude

例えば、setvars.sh がインテル® oneMKL とインテル® IPP コンポーネントの env/vars.sh スクリプトのみを
source するようにするには、次の設定ファイルを使用します。
default=exclude
mkl=2021.1.1
ipp=latest

この例は次のように作用します。


setvars.sh は、インテル® oneMKL 2021.1.1 の env/vars.sh スクリプトを source します。

setvars.sh は、インテル® IPP の最新バージョンの env/vars.sh スクリプト source します。

setvars.sh は、そのほかのコンポーネントの env/vars.sh スクリプトを source しません。

3.6.7 Eclipse* で servars.sh スクリプトを自動化
setvars.sh スクリプトは、インテル® oneAPI ツールキットを使用するために必要な環境変数を設定します。このスクリプトは、コマンドライン開発向けに新しいターミナルウィンドウを開くたびに実行する必要があります。setvars.sh
スクリプトは、Eclipse* の起動時に自動的に実行することもできます。SETVARS_CONFIG 環境変数を使用して、setvars.sh スクリプトにインテル® oneAPI ツール固有の設定を行うように指示できます。

37

インテル® oneAPI プログラミング・ガイド

3.6.8 SETVARS_CONFIG 環境変数の状態
SETVARS_CONFIG 環境変数を使用して、C/C++ 開発者向けの Eclipse* IDE インスタンスを起動したときにインテル®
oneAPI 開発環境を自動的に設定できます。環境変数には 3 つの条件と状態があります。


未定義 (SETVARS_CONFIG 環境変数が存在しない)

定義されているが空 (値を含まないか空白である)

setvars.sh 設定ファイルを示すように定義

SETVARS_CONFIG に値が設定されていない (空白のみが含まれる) 場合、Eclipse* の起動時に setvars.sh スクリ
プトは自動的に実行されます。この場合、setvars.sh スクリプトはシステムにインストールされているすべての
oneAPI ツールの環境を初期化します。setvars.sh スクリプト実行の詳細については、「Eclipse* 使用したサンプル・
プロジェクトのビルドと実行」 (英語) を参照してください。
SETVARS_CONFIG に setvars 設 定 フ ァ イ ル へ の 絶 対 パ ス が 定 義 さ れ て い る 場 合 、 Eclipse* の 起 動 時 に
setvars.sh スクリプトは自動的に実行されます。この場合、setvars.sh スクリプトは、setvars 設定ファイルで定義されるインテル® oneAPI ツールのみの環境を初期化します。setvars 設定ファイルを作成する方法の詳細は、「Linux* または macOS* で setvars.sh 設定ファイルを使用」をご覧ください。

注: Eclipse* でのデフォルトの SETVARS_CONFIG の動作は、Windows* の Visual Studio* で説明されている動作とは異なります。Eclipse* を起動すると、setvars.sh スクリプトは常に自動的に実行されます。Windows* で Visual Studio* を起動すると、SETVARS_CONFIG 環境変数が定義されている場合にのみ setvars.bat スクリプトは自動的に実行されます。

setvars 設定ファイルは任意の名前で作成でき、そのファイルが Eclipse* からアクセスおよび読み取り可能である限
りハードディスク上のどこにでも保存できます (Linux* システムにインテル® oneAPI ツールをインストールしたときにEclipse* に追加されたプラグインが SETVARS_CONFIG のアクションを実行するため、Eclipse* は setvars 設定ファ
イルにアクセスできる必要があります)。
setvars 設定ファイルを空のままにすると、setvars.sh スクリプトはシステムにインストールされているすべてのインテル® oneAPI ツールの環境を初期化します。これは、SETVARS_CONFIG 変数に空の文字列を定義するのと同じです。setvars 設定ファイルの作成方法については、「Linux* または macOS* で setvars.sh 設定ファイルを使用」を参照してください。

3.6.9 SETVARS_CONFIG 環境変数の定義
SETVARS_CONFIG 環境変数はインストール中に自動的に定義されないため、Eclipse* を起動する前に (前述の方法で)環境変数を追加する必要があります。SETVARS_CONFIG 環境変数には、以下を含むさまざまな場所を定義できます。


/etc/environment/etc/profile~/.bashrc

38

インテル® oneAPI プログラミング・ガイド

上記の例は、Linux* システムで環境変数を定義する一般的な場所です。SETVARS_CONFIG 環境変数に定義する場所
は、システムとニーズによって異なります。

3.7 Linux* で modulefile を使用
Linux* で環境を設定するには、次の 2 つの方法があります。


このページで説明されているように modulefile を使用します。



setvars.sh 設定ファイルを使用します。

ほとんどのインテル® oneAPI コンポーネントのフォルダーには、それぞれのコンポーネントに必要な環境変数を設定する modulefile のスクリプトが含まれています。modulefile を使用して、setvars.sh スクリプトに代わって開発環境を設定できます。modulefile では引数がサポートされていないため、複数の設定 (32 ビットや 64 ビットの設定など) をサポートするインテル® oneAPI ツールおよびライブラリーでは複数の modulefile を使用します。

注:インテル® oneAPI ツールキットで提供される modulefile は、Tcl 環境モジュール (Tmod) お
よび Lua 環境モジュール (Lmod) と互換性があり、次のバージョンがサポートされます。
Tmod 3.2.10 (コンパイラーの modulefile には 4.1 が必要です。以下を参照してください)
Tcl バージョン 8.4
Lmod バージョン 8.2.10

次のコマンドを使用して、システムにインストールされているバージョンを確認します。
$ module --version
各 modulefile は、実行時にシステムの Tcl バージョンが適切であるか自動的に確認します。
modulefile のバージョンがサポートされていない場合、回避策があります。詳細については、「インテル開発ツールにおける環境モジュールの利用」 (英語) を参照してください。
インテル® oneAPI 2021.4 のリリース以降、バージョン 3.2.10 の Tcl モジュールを使用する場合、icc の modulefile を使用して icc および ifort コンパイラーを設定できます。今後のインテル® oneAPI リリースでは、コンパイラーの modulefile のサポートが解決される予定です。
インテル® oneAPI の modulefile スクリプトは、それぞれのコンポーネント・ディレクトリーにある modulefiles
フォルダーにあります (個々の vars スクリプトの配置方法と同様)。例えば、デフォルトのインストールでは、ipp のmodulefile スクリプトは、/opt/intel/oneapi/ipp/latest/modulefiles/ ディレクトリーにあります。

39

インテル® oneAPI プログラミング・ガイド

インテル® oneAPI コンポーネントのフォルダーがどのように展開されているかにより、 インテル® oneAPI の
modulefile をインストール先で直接使用することが難しい場合があります。そのため、oneAPI インストール・フォル
ダーには特殊な modulefiles-setup.sh スクリプトが用意されており、インテル® oneAPI の modulefile を簡
単に操作できます。デフォルトのインストールでは、設定スクリプトは /opt/intel/oneapi/modulefilessetup.sh に配置されます。
modulefiles-setup.sh スクリプトは、インテル® oneAPI のインストールに含まれるすべての modulefile スク
リプトを検索し、それらのフォルダーを単一ディレクトリーに保存します。
これらのバージョン管理された modulefile スクリプトは、それぞれ modulefiles-setup.sh スクリプトで配置された modulefile を指すシンボリック・リンクです。各コンポーネント・フォルダーには、少なくとも latest (最新)バージョンの modulefile が含まれ、バージョンを指定しなくてもデフォルトで最新のコンポーネントをロードできます。modulefiles-setup.sh スクリプトの実行時に --ignore-latest オプションを使用すると、module_load
コマンドでバージョンが指定されていない場合、最も高い semver バージョンの modulefile がロードされます。

3.7.1.1.

modulefiles ディレクトリーの作成

modulefiles-setup.sh スクリプトを実行します。

注: デフォルトでは、modulefiles-setup.sh スクリプトは、インテル® oneAPI ツールキットのインストール・フォルダーに modulefiles という名前のフォルダーを作成します。インストール・
フォルダーが書き込み可能でない場合、--outputdir=<フォルダーのパス> オプションを使用して、書き込み可能な場所に modulefiles フォルダーを作成します。modulefiles-setup.sh
スクリプトの詳細については、modulefiles-setup.sh –help を入力して確認できます。

modulefiles-setup.sh スクリプトが実行されると、次のような階層が最上位の modulefiles フォルダーに作成されます (modulefiles の正確なリストはインストールによって異なります)。この例では、インテル® Advisor 環境を設定する 1 つの modulefile と、コンパイラー環境を設定する 2 つの modulefile があります (コンパイラーのmodulefile は、すべてのインテル® コンパイラーの環境を設定します)。最新のシンボリック・リンクをたどると、
semver の規則に従って最上位バージョンの modulefile を指します。

40

インテル® oneAPI プログラミング・ガイド

ここで、MODULEFILESPATH を更新して、modulefiles-setup.sh スクリプトで作成された新しい modulefiles
フォルダーに含めるか、moduleuse <folder_name> コマンドを実行します。

3.7.1.2.

システムに Tcl modulefile 環境をインストール

次の手順は、Ubuntu* で環境モジュール・ユーティリティーを実行する例を示しています。モジュール・ユーティリティー
のインストールと設定の詳細については、http://modules.sourceforge.net/ (英語) を参照してください。
$ sudo apt update$ sudo apt install tcl$ sudo apt install environment-modules

tclsh のローカルコピーが新しいものであることを確認します (サポートされているバージョンについては、このページの最初を参照してください)。
$ echo 'puts [info patchlevel] ; exit 0' | tclsh 8.6.8

module のインストールをテストするには、module エイリアスを初期化します。
$ source /usr/share/modules/init/sh$ module

41

インテル® oneAPI プログラミング・ガイド

注: POSIX* 互換シェルの初期化は、上記の source コマンドで機能するはずです。それ以外のシェ
ル固有の init スクリプトは、/usr/share/modules/init/ フォルダーにあります。詳細については、各フォルダーと man module の初期化セクションをご覧ください。

init スクリプト (.../modules/init/sh) で module エイリアスを source して、module コマンドが利用できる
ようにします。これにより、システムは次のセクションに示す module コマンドを使用できます。

3.7.1.3.

modulefiles-setup.sh スクリプトの使用

次のことが前提とされています。
Linux* 開発システムに tclsh がインストールされている



システムに環境モジュール・ユーティリティー (module など) がインストールされている

init コマンドで .../modules/init/sh (または等価なシェル) が source されている

oneAPI 開発に必要なインテル® oneAPI ツールキットがインストールされている$ cd <oneapi-root-folder> # oneapi_root インストール・ディレクトリーに移動する$ ./modulefiles-setup.sh# modulefile 設定スクリプトを実行する$ module use modulefiles# 上記で作成した modulefiles フォルダーを使用する$ module avail# tbb/X.Y などが表示される$ module load tbb# tbb/X.Y モジュールをロード$ module list

# ロードした tbb/X.Y モジュールをリスト$ module unload tbb# 環境から tbb/X.Y の変更を削除$ module list

# tbb/X.Y 環境変数モジュールがリストされなくなる

アンロードの前に、env コマンドを使用して環境を検証し、ロードした modulefile で変更された部分を探します。
例えば、次のコマンドを実行すると、ロードした tbb modulefile で変更された環境の一部分が表示されます(modulefile を調べてすべての変更を確認します)。
$ env | grep -i "intel"

注: modulefile はスクリプトですが、ユーザーがインストールおよび保守する module インタープリターによってロードおよび解釈されるため、x (実行可能) 権限を設定する必要はありません。
インテル® oneAPI ツールキットのインストールには、modulefile インタープリターは含まれていないため、個別にインストールする必要があります。同様に、modulefile には w 権限は必要ありませんが、読み取り可能である必要があります (r 権限をすべてのユーザーに設定します)。

42インテル® oneAPI プログラミング・ガイド

3.7.1.4.

バージョン管理インテル® oneAPI ツールキットのインストーラーは、バージョンフォルダーを使用して、インテル® oneAPI ツールとライブラリーの共存を可能にしています。modulefiles-setup.sh スクリプトはバージョン管理されたコンポーネン
ト・フォルダーを使用して、バージョン管理された modulefile を作成します。modulefiles 出力フォルダーに[<modulefile 名>/バージョン] としてシンボリック・リンクが作成されるため、module コマンドの使用時にそれぞれの modulefile をバージョン別に参照できます。
$ module avail---------------- modulefiles ----------------ipp/1.1 ipp/1.2 compiler/1.0 compiler32/1.0

3.7.1.5.

複数の modulefile

ツールやライブラリーは、modulefiles フォルダー内に複数の modulefile を持つ場合があります。それぞれがロード可能モジュールになります。展開されたコンポーネント・フォルダーごとにバージョンが割り当てられます。

3.7.1.6.

oneAPI で使用する modulefile の記述法を理解する

modulefiles-setup.sh スクリプトはシンボリック・リンクを使用して、すべての modulefile を modulefiles フォル
ダーに集約します。実際の modulefile は移動または変更されません。そのため、${ModulesCurrentModulefile} 変数には、それぞれのインストール・フォルダーにある実際の modulefile ではなく、各 modulefile への symlink が格納されます。各 modulefile は、次のような形式を使用して、それぞれのインストール・ディレクトリーにある元の modulefile
への参照を取得します。
[ file readlink ${ModulesCurrentModulefile} ]これは、実際のインストール場所はカスタマイズできるため、実行時に不明であり推測する必要があるためです。実際のmodulefile はインストールされた場所以外に移動することはできません。そうしないと、構成に必要なライブラリー
やアプリケーションへの絶対パスを検出できなくなります。
さらに詳しく理解するには、インストールに含まれる modulefile を確認してください。ほとんどの場合、実際のファイルへの symlink を解決する方法のコメントと、バージョン番号（およびバージョン・ディレクトリー）の解析が含まれます。
また、インストールされた TCL が適切なバージョンであることを確認するチェックも含まれています。

3.7.1.7.

modulefiles による module load コマンドの使用

modulefile のいくつかは、依存関係のあるモジュールがロードされるように module load コマンドを使用します。依存関係のある modulefile のバージョンチェックは行われません。これは、モジュールをロードする前に、その依存関係モジュールを手動で事前ロードできることを意味します。依存関係モジュールを事前ロードしない場合、最新バージョンがロードされます。
これは、環境を柔軟にコントロールできるようにするための設計です。例えば、以前のバージョンのコンパイラーで更新されたバージョンのライブラリーをテストするためインストールすると仮定します。更新されたライブラリーにはバグ修

43インテル® oneAPI プログラミング・ガイド

正があり、更新されたライブラリー内の他のモジュールには興味がないという可能性もあります。依存する
modulefile が、ライブラリーの特定のバージョンを使用するようにハードコーディングされている場合、このテストは機能しません。

注: 依存関係の module load 条件を満たせない場合、モジュールのロードは終了し環境は変更されません。

3.7.1.8.

関連情報

modulefile の詳細については、以下をご覧ください。


http://www.admin-magazine.com/HPC/Articles/Environment-Modules (英語)https://www.chpc.utah.edu/documentation/software/modules-advanced.php (英語)https://modules.readthedocs.io/en/latest/ (英語)https://lmod.readthedocs.io/en/latest/ (英語)

3.8 oneAPI アプリケーションで CMake* を使用
インテル® oneAPI 製品で提供される CMake* パッケージを使用すると、CMake* プロジェクトで Windows* またはLinux* 上の oneAPI ライブラリーを簡単に利用できます。このパッケージを使用することで、ほかのシステム・ライブラ
リーが CMake* プロジェクトと統合する場合と同様の体験ができます。CMake* プロジェクトのターゲットに応じて、依存関係が生じたり、ほかのビルド変数が必要になることがあります。
次のコンポーネントが CMake* をサポートします。
インテル® oneAPI DPC++ コンパイラー - Linux*、Windows*

インテル® IPP およびインテル® IPP Cryptgraphy - Linux*、Windows*

インテル® MPI ライブラリー - Linux*、Windows*

インテル® oneCCL - Linux*、Windows*

インテル® oneDAL - Linux*、Windows*

インテル® oneDNN - Linux*、Windows*

インテル® oneDPL - Linux*、Windows*

インテル® oneMKL - Linux*、Windows*、macOS*



インテル® oneTBB - Linux*、Windows*、macOS*



インテル® oneVPL - Linux*、Windows*

44

インテル® oneAPI プログラミング・ガイド

すべてのインテル® oneAPI コンポーネント製品が、CMake* をサポートするわけではありません。
CMake* 設定を提供するライブラリーは、以下で識別できます。

Linux* または macOS*:
システム: /usr/local/lib/cmake
ユーザー: ~/lib/cmakeWindows*: HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\

CMake* パッケージを使用するには、ほかのシステム・ライブラリーと同様にインテル® oneAPI ライブラリーを使用します。例えば、find_package(tbb) を使用すると、アプリケーションの CMake* パッケージはインテル® oneTBB パッ
ケージを使用します。

45

インテル® oneAPI プログラミング・ガイド

4oneAPI プログラムのコンパイルと実行

この章では、CPU、GPU、および FPGA を対象とするダイレクト・プログラミングと API ベースのプログラミングにおける oneAPI のコンパイル手順について詳しく説明します。また、コンパイルの各ステージで使用されるツールについても詳しく説明します。

4.1 単一ソースのコンパイル
oneAPI プログラミング・モデルは、単一ソースのコンパイルをサポートします。単一ソースのコンパイルには、ホストとデバイスコードを個別にコンパイルする場合と比較して多くの利点があります。oneAPI プログラミング・モデルは、一部のユーザーの要望に答え、ホストコードとデバイスコードの個別コンパイルもサポートすることを覚えておいてください。
利用可能な単一ソースのコンパイルには次のモデルがあります:

利便性 - 開発者は作成するファイル数を最小限に抑え、ホストコードの呼び出し元の直後にデバイスコードを定義できます。

安全性 - 単一ソースでは、単独のコンパイラーがホストとデバイス間の境界にあるコードを判断することができ、ホスト・コンパイラーによって生成される仮引数がデバイス・コンパイラーによって生成されるカーネルの実引数と一致します。



最適化 - デバイス・コンパイラーは、カーネルが起動されるコンテキストを知ることができるため、さらなる最適化を行うことができます。例えば、コンパイラーはいくつかの定数を伝搬したり、関数呼び出し全体でポインターのエイリアシング情報を推測することができます。

4.2 コンパイラーの起動
インテル® oneAPI DPC++/C++ コンパイラーは、コマンドラインでコンパイラーを起動する複数のコンパイラー・ドライ
バーを提供します。次の例は、C++ および SYCL* のオプションを示します。ドライバーオプションの詳細については、「各種コンパイラーと ドライバーの一覧」 (英語) を参照してください。
コンパイラーの起動に関する詳細は、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』の「コンパイラーの起動」 (英語) を参照してください。
C++ アプリケーションをコンパイルする際に OpenMP* を有効にするには、次のコマンドでコンパイラーを起動します。
$ icpx -fiopenmp -fopenmp-targets=<arch> (Linux*)$ icx /Qiopenmp /Qopenmp-targets:<arch> (Windows*)

46

インテル® oneAPI プログラミング・ガイド

SYCL* アプリケーションをコンパイルする際に OpenMP* を有効にするには、次のコマンドでコンパイラーを起動します。
$ icpx -fsycl -fiopenmp -fopenmp-targets=<arch> (Linux*)$ icx-cl -fsycl /Qiopenmp /Qopenmp-targets:<arch> (Windows*)

オプションの詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリ
ファレンス』の「コンパイラー・オプション」 (英語) を参照してください。
コンパイラー・ドライバーは、OS ホストごとに互換性が異なります。Linux* では、GCC スタイルの icpx -fsycl コマ
ンドライン・オプションが提供され、Windows* では Microsoft* Visual Studio* の Microsoft Visual C++* 互換のicx-cl が提供されます。


GCC 形式のコマンドライン・オプション ("-" で始まる) を認識し、複数のオペレーティング・システムでビルドシス
テムを共有するプロジェクトに役立ちます。

Windows* コマンドライン・オプション ("/" で始まる) を認識し、Microsoft* Visual Studio* ベースのプロジェク
トで使用できます。

4.3 インテル® oneAPI DPC++/C++ コンパイラーの標準オプション
インテル® oneAPI DPC++/C++ コンパイラーの完全なオプションリストは、『インテル® oneAPI DPC++/C++ コンパイ
ラー・デベロッパー・ガイドおよびリファレンス』に記載されています。
「オフロード向けのコンパイルオプションと OpenMP* オプションおよび並列処理オプション」 (英語) には、
SYCL* と OpenMP* オフロードに固有のオプションが示されています。



利用可能なすべてのオプションと簡単な説明は、「コンパイラー・オプションのリスト (アルファベット順)」 (英語) にあります。

4.4 コンパイル例
oneAPI アプリケーションは、ダイレクト・プログラミング、利用可能な oneAPI ライブラリーを使用する API ベース、およびそれらを組み合わせて記述することができます。API ベースのプログラミングでは、ライブラリーの機能を使用してデバイスへのオフロードを行います。これにより、開発者はアプリケーションを開発する時間を節約できます。一般に、
API ベースのプログラミングから始め、ニーズに対応できない場合に SYCL* または OpenMP* オフロード機能を導入するのが最も容易であると考えられます。
次のセクションでは、API ベースのコードと SYCL* を使用したダイレクト・プログラミングの例を紹介します。

47

インテル® oneAPI プログラミング・ガイド

4.4.1 API ベースのコード
次のコードは、インテル® oneMKL の oneapi::mkl::blas::axpy 関数を使用して、浮動小数点数のベクトル全体
に対して a と x を乗算して y を加算する API 呼び出し (a * x + y) の使用法を示しています。このサンプルコード
は、oneAPI プログラミング・モデルを利用して、アクセラレーターで加算を実行します。
1. #include <vector> // std::vector()
2. #include <cstdlib> // std::rand()3. #include <CL/sycl.hpp>
4. #include "oneapi/mkl/blas.hpp"
5.
6. int main(int argc, char* argv[]) {7.
8.
double alpha = 2.0;
9.
int n_elements = 1024;
10.
11.
12.
int incx = 1;
13.
std::vector<double> x;
14.
x.resize(incx * n_elements);15.
for (int i=0; i<n_elements; i++)16.
x[i*incx] = 4.0 * double(std::rand()) / RAND_MAX - 2.0;
17.
// -2.0 から 2.0 の範囲の rand 値
18.
19.
int incy = 3;20.
std::vector<double> y;21.
y.resize(incy * n_elements);22.
for (int i=0; i<n_elements; i++)23.
y[i*incy] = 4.0 * double(std::rand()) / RAND_MAX - 2.0;
24.
// -2.0 から 2.0 の範囲の rand 値
25.
26.
cl::sycl::device my_dev;
27.
try {
28.
my_dev = cl::sycl::device(cl::sycl::gpu_selector());
29.
} catch (...){
30.
std::cout << "Warning, failed at selecting gpu device.Continuing on default(host)device.\n";
31.
}
32.
33.
// 非同期例外をキャッチ
34.
auto exception_handler = [] (cl::sycl::exception_list
35.
exceptions) {36.
for (std::exception_ptr const& e : exceptions) {
37.
try {
38.
std::rethrow_exception(e);39.
} catch(cl::sycl::exception const& e) {40.
std::cout << "Caught asynchronous SYCL exception:\n";41.
std::cout << e.what() << std::endl;
42.
}
43.
}
44.
};
45.
46.
cl::sycl::queue my_queue(my_dev, exception_handler);
47.
48.
49.
cl::sycl::buffer<double, 1> x_buffer(x.data(), x.size());
50.
cl::sycl::buffer<double, 1> y_buffer(y.data(), y.size());
51.

48

インテル® oneAPI プログラミング・ガイド

52.
// y = alpha*x + y を計算
53.
try {
54.
oneapi::mkl::blas::axpy(my_queue, n_elements, alpha, x_buffer,55.
incx, y_buffer, incy);
56.
}
57.
58.
catch(cl::sycl::exception const& e) {59.
std::cout << "\t\tCaught synchronous SYCL exception:\n"60.
<< e.what() << std::endl;
61.
}
62.
63.
std::cout << "The axpy (y = alpha * x + y) computation is complete!"<< std::endl;
64.
65.
66.
// y_buffer をプリント
67.
auto y_accessor = y_buffer.template68.
get_access<cl::sycl::access::mode::read>();69.
std::cout << std::endl;
70.
std::cout << "y" << " = [ " << y_accessor[0] << " ]\n";71.
std::cout << "[ " << y_accessor[1*incy] << " ]\n";72.
std::cout << "[ " << "... ]\n";73.
std::cout << std::endl;
74.
75.
return 0;
76. }アプリケーション (axpy.cpp として保存) をコンパイルするには、次の操作を行います。
1.

MKLROOT 環境変数が適切に設定されていることを確認します。
Linux*: echo ${MKLROOT}
Windows*: echo %MKLROOT%
正しく設定されていない場合、setvars.sh (Linux*) または setvars.bat (Windows*) スクリプトを実行する
か、lib および include サブディレクトリーを含むディレクトリー・パスを変数に設定します。
setvars スクリプトの詳細については、「oneAPI 開発環境の設定」を参照してください。

2.

次のコマンドでアプリケーションをビルドします。
Linux*:$ icpx -fsycl -I${MKLROOT}/include -c axpy.cpp -o axpy.o

Windows*:$ icpx -fsycl -I${MKLROOT}/include /EHsc -c axpy.cpp /Foaxpy.obj

49

インテル® oneAPI プログラミング・ガイド

3.

次のコマンドでアプリケーションをリンクします。
Linux*:$ icpx -fsycl axpy.o -fsycl-device-code-split=per_kernel \"${MKLROOT}/lib/intel64"/libmkl_sycl.a -Wl,-export-dynamic -Wl,--start-group\"${MKLROOT}/lib/intel64"/libmkl_intel_ilp64.a \"${MKLROOT}/lib/intel64"/libmkl_sequential.a \"${MKLROOT}/lib/intel64"/libmkl_core.a -Wl,--end-group -lsycl -lOpenCL \-lpthread -lm -ldl -o axpy.out

Windows*:$ icpx -fsycl axpy.obj -fsycl-device-code-split=per_kernel ^"${MKLROOT}/lib/intel64"/libmkl_sycl.lib ^"${MKLROOT}/lib/intel64"/libmkl_intel_ilp64.lib ^"${MKLROOT}/lib/intel64"/libmkl_sequential.lib ^"${MKLROOT}/lib/intel64"/libmkl_core.lib ^sycl.lib OpenCL.lib -o axpy.exe

4.

次のコマンドでアプリケーションを実行します。
Linux*:$ ./axpy.out

Windows*:$ axpy.exe

4.4.2 ダイレクト・プログラミング
ここでは、「ベクトル加算のサンプルコード」 (英語) を使用します。このサンプルコードは、oneAPI プログラミング・モデ
ルを利用して、アクセラレーターで加算を実行します。
次のコマンドで、実行形式をコンパイルしてリンクします。
$ icpx -fsycl vector_add.cpp

コマンドとオプションのコンポーネントと関数は、「API ベースのコード」セクションで説明したものと類似しています。
このコマンドを実行すると、実行時にベクトルの加算を実行する実行ファイルが作成されます。

50

インテル® oneAPI プログラミング・ガイド

4.5 コンパイルの手順
オフロードを行うプログラムを作成する場合、コンパイラーはホストとデバイス向けの両方のコードを生成する必要があります。oneAPI は、この複雑な作業を開発者から見えないようにします。開発者は、DPC++ コンパイラー(icpx -fsycl) を使用して SYCL* アプリケーションをコンパイルするだけで (一度のコンパイルコマンドで)、ホストとデバイス向けのコードを生成できます。
デバイスコードの実行には、Just-in-Time (JIT) コンパイルと Ahead-of-Time (AOT) コンパイルの 2 つのオプションがありますが、JIT がデフォルトです。このセクションでは、ホストコードのコンパイル方法と、デバイスコードを生成する
2 つの方法を説明します。詳しくは、『Data Parallel C++』 (英語) 書籍の 13 章をご覧ください。

4.5.1 従来のコンパイル手順 (ホストのみのアプリケーション)
従来のコンパイル手順は、C、C++、またはそのほかの言語で利用される標準のコンパイル方法です。デバイスへのオフ
ロードがない場合に使用されます。コンパイル手順を図に示します。
従来のコンパイル手順1.

フロントエンドは、ソースを中間表現に変換し、バックエンドに渡します。

2.

バックエンドは、中間表現をオブジェクト・コードに変換してオブジェクト・ファイル (Windows* では .obj、Linux* では .o) を出力します。

3.

1 つ以上のオブジェクト・ファイルがリンカーに渡されます。

4.

リンカーは実行ファイルを生成します。

5.

これで、アプリケーションを実行できます。

51

インテル® oneAPI プログラミング・ガイド

4.5.2 SYCL* オフロードコードのコンパイル手順
SYCL* オフロードコードのコンパイル手順には、従来のコンパイル手順にデバイスコードの JIT および AOT オプションを追加します。この手順では、開発者は icpx -fsycl を使用して、SYCL* アプリケーションをコンパイルし、出力としてホストコードとデバイスコードの両方を含む実行可能ファイルを作成します。
SYCL* オフロードコードの基本コンパイル手順を次に示します。
SYCL* オフロードコードの基本コンパイル手順

1.

ホストコードは、バックエンドでオブジェクト・コードに変換されます。

2.

デバイスコードは SPIR-V* 形式またはデバイスバイナリーに変換されます。

3.

リンカーは、ホスト・オブジェクト・コードとデバイスコード (SPIR-V* またはデバイスバイナリー) を組み合わせた、(デバイスコードが埋め込まれた) ホスト実行コードを含むファットバイナリーを生成します。

4.

バイナリーが起動されると、オペレーティング・システムはホスト・アプリケーションを実行します。オフロードが行われる場合、ランタイムはデバイスコードをロードします (必要に応じて SPIR-V* をデバイスバイナリーに変換します)。

5.

アプリケーションは、ホストと利用可能なデバイスで実行されます。

4.5.3 JIT のコンパイル手順
JIT コンパイルの手順では、デバイスコードはバックエンドで SPIR-V* 形式の中間コードに変換され、SPIR-V* としてファットバイナリーに組み込まれ、ランタイムによって SPIR-V* からデバイスバイナリーに変換されます。アプリケー
ションが起動されると、ランタイムは利用可能なデバイスを判別してそのデバイス固有のコードを生成します。これにより、AOT (事前) コンパイル手順よりも、アプリケーションの実行環境とパフォーマンスの柔軟性が高まります。しかし、
アプリケーションの実行時にコンパイル (JIT) が行われるため、アプリケーションの実行時間が増加する可能性があります。大量のデバイスコードを持つ大規模なアプリケーションでは、パフォーマンスへの影響が顕著に表れることがあ
ります。

52

インテル® oneAPI プログラミング・ガイド

ヒント: JIT コンパイル手順は、ターゲットデバイスが不明である場合に役立ちます。

注: JIT コンパイラーは、FPGA デバイスではサポートされません。

コンパイル手順を次の図に示します。
JIT コンパイル手順

1.

ホストコードは、バックエンドでオブジェクト・コードに変換されます。

2.

デバイスコードは SPIR-V* 形式に変換されます。

3.

リンカーは、ホスト・オブジェクト・コードとデバイス SPIR-V* を組み合わせた (SPIR-V* が埋め込まれた)、ホスト
実行コードを含むファットバイナリーを生成します。

4.

実行されると次のように処理されます。

5.

ホスト上のデバイスランタイムは、デバイスの SPIR-V* をデバイスのバイナリーに変換します。

6.

変換されたデバイスバイナリーはデバイスへロードされます。

7.

アプリケーションは、実行時に利用可能なホストとデバイスで実行されます。

4.5.4 AOT のコンパイル手順
AOT (事前) コンパイルでは、デバイスコードが SPIR-V* に変換されてから、ホスト・バックエンドのデバイスコードに変換され、最終的に生成されたデバイスコードがファットバイナリーに組み込まれます。しかし、実行ファイルの起動時間
は JIT 手順よりも短くなります。

53インテル® oneAPI プログラミング・ガイド

ヒント: AOT 手順は、ターゲットとするデバイスが明確に判明している場合に適しています。AOT
手順では、デバッグサイクルが高速化されるため、アプリケーションをデバッグする際の利用が推奨されます。

コンパイル手順を次の図に示します。
AOT コンパイル手順

1.

ホストコードは、バックエンドでオブジェクト・コードに変換されます。

2.

デバイスコードは SPIR-V* 形式に変換されます。

3.

デバイスの SPIR-V* は、コマンドラインでユーザーが指定したデバイス向けのデバイス・コード・オブジェクトに変換されます。

4.

リンカーは、ホスト・オブジェクト・コードとデバイス・オブジェクト・コードを組み合わせた、デバイスバイナリーが埋め込まれたホスト実行コードを含むファットバイナリーを生成します。

5.

実行時に、デバイスバイナリーはデバイスへロードされます。

6.

アプリケーションは、ホストと指定されたデバイスで実行されます。

4.5.5 ファットバイナリー
ファットバイナリーは、JIT と AOT コンパイル手順から生成されます。デバイスコードが埋め込まれたホストバイナリーです。デバイスコード自体は、コンパイル手順によって異なります。

54インテル® oneAPI プログラミング・ガイド

ファットバイナリー

ホストコードは、ELF (Linux*) または PE (Windows*) 形式の実行ファイルです。



デバイスコードは、JIT 手順では SPIR-V*、AOT 手順ではデバイスバイナリー (実行可能) です。実行ファイルは
次のいずれかの形式です。
‐

CPU: ELF (Linux*)、PE (Windows*)‐

GPU: ELF (Windows*、Linux*)‐

FPGA: ELF (Linux*)、PE (Windows*)

4.6 CPU 手順
CPU はコンピューターの頭脳とも呼ばれ、分岐予測、メモリーの仮想化、命令のスケジュールなどを含む複雑な回路/ア
ルゴリズムで構成されています。このような複雑性を考慮し、CPU は幅広いタスクを処理するように設計されています。
SYCL* および OpenMP* オフロードを利用するプログラミング・モデルにより、異種 CPU および GPU システムでのア
プリケーションの実装が可能になります。SYCL* および OpenMP* オフロードにおける「デバイス」は、CPU と GPU の両方を指す場合があります。
最新の CPU は、並列計算に利用可能なハイパースレッディングと広い SIMD 幅を備えた複数のコアを搭載しています。
ワークロードに計算集約型で並列実行可能な領域が存在する場合、そのような領域は GPU や FPGA などのコプロセッ
サーではなく CPU へオフロードすることを推奨します。これはまた、データを PCIe* を介してオフロードする必要がない
ため (コプロセッサーや GPU とは異なり)、データ転送のオーバーヘッドを最小限に抑えてレイテンシーを軽減します。
CPU でアプリケーションを実行するには、CPU で直接実行される従来型の CPU フローと、CPU デバイスで実行される
CPU オフロードの 2 つのオプションがあります。CPU オフロードは、SYCL* または OpenMP* オフロード・アプリケー
ションで使用できます。OpenMP* オフロード・アプリケーションと SYCL* オフロード・アプリケーションは、どちらもOpenCL* ランタイムとインテル® oneTBB を使用して、CPU デバイスで実行できます。

ヒント: ワークロードが CPU、GPU、または FPGA に最適であるか不明な場合は、「各種 oneAPI
ワークロードに対する CPU、GPU、および FPGA の利点の比較」 (英語) を参照してください。

55

インテル® oneAPI プログラミング・ガイド

4.6.1 従来の CPU 向け手順
従来の CPU ワークフローは、ランタイムなしで CPU 上で動作します。コンパイルフローは、C、C++ またはほかの言語
で使用されるようなデバイスへのオフロードを行わない標準的なコンパイルです。
従来のワークロードでは、コンパイルフローの概要で説明されているように、従来のコンパイルフロー (ホスト専用アプ
リケーション) 手順を使用して、ホスト上でコンパイルおよび実行されます。
コンパイルコマンドの例:$ icpx -g -o matrix_mul_omp src/matrix_mul_omp.cpp

4.6.2 CPU オフロードの手順
デフォルトでは、CPU デバイスへオフロードする場合、OpenCL* ランタイムを使用します。OpenCL* ランタイムは、並列処理にインテル® oneTBB も活用します。
CPU にオフロードする場合、ワークグループは異なる論理コアに割り当てられ、これらのワークグループは並列に実行できます。ワークグループ内のワーク項目は、CPU の SIMD レーンにマップできます。ワーク項目 (サブグループ) は、
SIMD 方式で同時に実行されます。
CPU ワークグループ

CPU 実行の詳細については、「各種 oneAPI コンピューティング・ワークロードに対する CPU、GPU、および FPGA の利点の比較」 (英語) を参照してください。

56

インテル® oneAPI プログラミング・ガイド

4.6.2.1.

CPU オフロード向けの設定

1.

setvars スクリプトの実行を含む、「oneAPI 開発環境の設定」セクションのすべての手順を実行したことを確
認します。

2.

sycl-ls コマンドを実行して、必要な OpenCL* ランタイムが CPU に関連付けられていることを確認します。
例:$ sycl-ls
CPU : OpenCL 2.1 (Build 0)[ 2020.11.12.0.14_160000 ]GPU : OpenCL 3.0 NEO [ 21.33.20678 ]GPU : 1.1[ 1.2.20939 ]3.

次のサンプルコードを使用して、コードが CPU で実行されていることを確認します。サンプルコードは、整数の大きなベクトルにスカラーを加算し、結果を検証します。

SYCL*
SYCL* では CPU で実行するための組込みデバイスセレクターが用意されています。これは、device_selector 基本
クラスを使用し cpu_selector で CPU デバイスを選択できます。
または、default_selector を使用して、実装で定義されたヒューリスティックに従って次の環境変数によって実行時にデバイスを選択することもできます。
$ export SYCL_DEVICE_FILTER=cpu

SYCL* サンプルコード:
1. #include <CL/sycl.hpp>
2. #include <array>
3. #include <iostream>4.
5. using namespace sycl;
6. using namespace std;
7. constexpr size_t array_size = 10000;
8. int main(){9.
constexpr int value = 100000;
10.
try{
11.
cpu_selector d_selector;
12.
queue q(d_selector);13.
int *sequential = malloc_shared<int>(array_size, q);
14.
int *parallel = malloc_shared<int>(array_size, q);
15.
// シーケンシャル iota
16.
for (size_t i = 0; i < array_size; i++) sequential[i] = value + i;
17.
18.
// SYCL* の並列 iota
19.
auto e = q.parallel_for(range{array_size}, [=](auto i) {20.
parallel[i] = value + i;
21.
});
22.
e.wait();23.
// 2 つの結果が等しいか検証
24.
for (size_t i = 0; i < array_size; i++) {57

インテル® oneAPI プログラミング・ガイド

25.
if (parallel[i] != sequential[i]) {26.
cout << "Failed on device.\n";27.
return -1;
28.
}
29.
}
30.
free(sequential, q);31.
free(parallel, q);32.
}catch (std::exception const &e) {33.
cout << "An exception is caught while computing on device.\n";34.
terminate();
35.
}
36.
cout << "Successfully completed on device.\n";37.
return 0;
38. }次のコマンドでサンプルコードをコンパイルします。
$ icpx -ｆｓｙｃｌ simple-iota-dp.cpp -o simple-iota.

追加のコマンドはサンプルの CPU コマンドから取得できます。
生成したバイナリーを実行します。
$ ./simple-iota
Running on device: Intel® Core™ i7-8700 CPU @ 3.20GHz Successfully completed on device.

OpenMP*
OpenMP* のサンプルコード:
1. #include<iostream>
2. #include<omp.h>
3. #define N 1024
4. int main(){5.
float *a = (float *)malloc(sizeof(float)*N);
6.
7.
for(int i = 0; i < N; i++)8.
a[i] = i;9.
#pragma omp target teams distribute parallel for simd map(tofrom: a[:N])10.
for(int i = 0; i < 1024; i++)11.
a[i]++;
12.
13.
std::cout<<a[100]<<"\n";14.
return 0;
15. }次の環境変数を使用して、CPU での実行向けにサンプルコードをコンパイルします。
$ export LIBOMPTARGET_DEVICETYPE=cpu

次のコマンドでサンプルコードをコンパイルします。
$ icpx simple-ompoffload.cpp -fiopenmp -fopenmp-targets=spir64 -o simple-ompoffload

58

インテル® oneAPI プログラミング・ガイド

生成したバイナリーを実行します。
$ ./simple-ompoffload Successfully completed on device

4.6.3 CPU へコードをオフロード
アプリケーションをオフロードする場合、ボトルネックとオフロードの利点が得られるコード領域を特定することが重要です。計算集約型、または高度なデータ並列カーネルコードがある場合、そのコード領域をオフロードすることを検討してください。
オフロードするコード領域を特定するには、

4.6.3.1.

(英語) が役立ちます。

オフロードされたコードのデバッグ

以下のリストには、オフロードされるコードの基本的なデバッグのヒントが示されています。


ホストターゲットをチェックしてコードが正しいことを確認します。

printf を使用して、アプリケーションをデバッグします。SYCL* と OpenMP* オフロードでは、どちらもカーネルコードで printf がサポートされます。環境変数を設定して詳細なログ情報を取得します。
‐

SYCL* では、次のデバッグ環境変数を利用できます。すべての環境変数については GitHub* (英語) から入手できます。

SYCL* で推奨されるデバッグ環境変数
環境変数
SYCL_DEVICE_FILTER

値
backend:device_type:device_num

SYCL_PI_TRACE

1|2|-1

説明
GitHub* (英語) の説明を参照してください。
1: SYCL*/DPC++ ランタイムプ
ラグインの基本トレースログを出力します
2: SYCL*/DPC++ ランタイムプラ
グインのすべての API トレースを出力します-1: 2 のすべてと追加のデバッグ
情報を出力します。

59

インテル® oneAPI プログラミング・ガイド‐

OpenMP* では、次のデバッグ環境変数が推奨されます。利用可能なすべての環境変数については、「LLVM/OpenMP* ドキュメント」 (英語) を参照してください。

OpenMP* で推奨されるデバッグ環境変数
環境変数
LIBOMPTARGET_DEVICETYPE
LIBOMPTARGET_DEBUG
LIBOMPTARGET_INFO

値
cpu|gpu|host1
LLVM/OpenMP* のドキュメントで利用可能な値 (英語)

説明
デバイスを選択します。
詳細なデバッグ情報を出力します。
ユーザーがさまざまなタイプのランタイム情報を libomptarget から取得できるようにします。

事前 (AOT) コンパイルを使用して、ジャストインタイム (JIT) コンパイルを AOT コンパイルに移行します。詳細
については、「CPU アーキテクチャー向けの事前コンパイル」を参照してください。



oneAPI で利用可能なデバッグ手法とデバッグツールの詳細については、「SYCL* および OpenMP* オフロード処理のデバッグ」を参照してください。

4.6.4 CPU コードの最適化
CPU オフロードコードのパフォーマンスに影響する可能性がある多くの要因があります。ワーク項目、ワークグループ、および実行されるワーク量は、CPU コア数によって異なります。


コアで実行されるワーク量が計算集約型でない場合、パフォーマンスが低下する可能性があります。これは、スケジュールのオーバーヘッドとスレッドのコンテキスト切り替えが原因です。

CPU では、PCIe* を介したデータ転送が不要であり、オフロード領域がデータを長時間待機する必要がないため、レイテンシーが低くなります。



アプリケーションの性質に基づいて、スレッド・アフィニティーは CPU のパフォーマンスに影響を与える可能性があります。詳細については、「マルチコアにおけるバイナリーの実行制御」を参照してください。



デフォルトでは JIT コンパイルが使用されますが、代わりに AOT コンパイル (オフラインコンパイル) を使用して、特定の CPU アーキテクチャーをターゲットにしてコードをコンパイルします。詳細については、「CPU アーキ
テクチャー向けの最適化オプション」を参照してください。

「オフロード・パフォーマンスの最適化」で追加の推奨事項が提供されています。

4.6.5 CPU コマンドの例
次のコマンドは、デバイスコードの一部が静的ライブラリーにある実装を想定しています。

注: 動的ライブラリーとのリンクはサポートされていません。

60

インテル® oneAPI プログラミング・ガイド

デバイスコードを使用してファット・オブジェクトを生成します。
$ icpx -fsycl -c static_lib.cpp

ar ツールを使用して、静的ファット・ライブラリーを作成します。
$ ar rc r libstlib.a static_lib.o

アプリケーションのソースをコンパイルします。
$ icpx -fsycl -c a.cpp

静的ライブラリーとアプリケーションをリンクします。
$ icpx -fsycl -foffload-static-lib=libstlib.a a.o -o a.exe

4.6.6 CPU アーキテクチャー向けの事前 (AOT) コンパイル
事前 (AOT) コンパイルモードでは、最適化オプションを使用して、特定の CPU アーキテクチャーでの実行を改善する
コードを生成できます。
$ icpx -fsycl -fsycl-targets=spir64_x86_64 -Xs “-device <CPU 最適化フラグ>” a.cpp b.cpp -o
app.out

次の CPU 最適化オプションがサポートされます。
-march=<instruction_set_arch> ターゲットの命令セット・アーキテクチャーを設定:'sse42' インテル® ストリーミング SIMD 拡張命令 4.2'avx2' インテル® アドバンスト・ベクトル・エクステンション 2'avx512' インテル® アドバンスト・ベクトル・エクステンション 512

注: サポートされる最適化オプションは、将来のリリースで変更される可能性があります。

4.6.7 複数の CPU コア上でバイナリーの実行をコントロール
4.6.7.1.

環境変数

次の環境変数は、プログラムの実行中に複数の CPU コアへ SYCL* または OpenMP* スレッドの配置をコントロール
します。OpenCL* ランタイム CPU デバイスを使用して CPU にオフロードする場合、これらの変数を使用します。

61

インテル® oneAPI プログラミング・ガイド

SYCL* または OpenMP* 環境変数
環境変数
DPCPP_CPU_CU_AFFINITY

説明
CPU へスレッド・アフィニティーを設定します。以下を指定できます。


close - スレッドは利用可能な CPU コアに連続して配置されます。
spread - スレッドは利用可能なコアに分散されます。
master - ス レ ッ ド は プ ラ イ マ リ ー ・ ス レ ッ ド と 同 じ コ ア に 配 置 さ れ ま す 。
DPCPP_CPU_CU_AFFINITY が設定されているとプライマリー・スレッドも固定されます (未設定では固定されません)。

この環境変数は、OpenMP* の OMP_PROC_BIND 環境変数に似ています。

DPCPP_CPU_SCHEDULE

デフォルト: 未設定
スケジューラーが work-group をスケジュールするアルゴリズムを指定します。現在、
SYCL* ランタイムはインテル® oneTBB のスケジューラーを使用しています。この値は、インテル® oneTBB スケジューラーが使用するパーティショナーを選択します。以下を指定
できます。





DPCPP_CPU_NUM_CUS

dynamic - インテル® oneTBB の auto_partitioner。負荷を分散するため適切な分割を行います。
affinity - インテル® oneTBB の affinity_partitioner。subrange をワーカースレッ
ドにマッピングすることで、auto_partitioner のキャッシュ・アフィニティーを向上させます。
static - インテル® oneTBB の static_partitioner。range の反復をワーカースレッ
ド間でできるだけ均等に分散します。インテル® oneTBB のパーティショナーは、
grainsize を使用してチャンクの大きさを制御します。デフォルトの grainsize は 1 であり、すべての work-group を独立して実行できることを示します。

デフォルト: dynamic
カーネルの実行に使用するスレッド数を設定します。
オーバーサブスクリプション状態を回避するには、DPCPP_CPU_NUM_CUS の最大値をハード
ウェア・スレッド数にする必要があります。DPCPP_CPU_NUM_CUS が 1 である場合、すべてのwork-group は単一のスレッドで順番に実行されます。これはデバッグ時に役立ちます。
この環境変数は、OpenMP* の OMP_NUM_THREADS に似ています。
デフォルト: 未設定。インテル® oneTBB によって決定されます。

62

インテル® oneAPI プログラミング・ガイド

環境変数
DPCPP_CPU_PLACES

説明
アフィニティーを設定する場所を指定します。
値は、{ sockets | numa_domains | cores | threads } のいずれかです。
この環境変数は、OpenMP* の OMP_PLACES 環境変数に似ています。
numa_domains が選択されると、インテル® oneTBB の NUMA API が使用されます。これは、OpenMP* 5.1 の OMP_PLACES=numa_domains に似ています。インテル® oneTBB のtask arena は numa ノードにバインドされ、SYCL* nd-range は task arena に均一に分散されます。
DPCPP_CPU_PLACES は、DPCPP_CPU_CU_AFFINITY とともに使用することを推奨します。
デフォルト: cores

サポートされる環境変数の詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』 (英語) をご覧ください。

4.6.7.2.

例 1: インテル® ハイパースレッディング・テクノロジー有効

2 ソケットで、ソケットごとに 4 つの物理コアがあり、それぞれの物理コアには 2 つのハイパースレッドがあるマシンを想定します。
S<num> は、リストで指定される 8 つのコアを持つソケット番号を示します

T<num> は、インテル® oneTBB のスレッド番号を示します。

"-" は未使用のコアを意味します。

DPCPP_CPU_NUM_CUS=16
export DPCPP_CPU_PLACES=sockets
DPCPP_CPU_CU_AFFINITY=close:S 0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[T8 T9 T10 T11 T12 T13 T14
T15]
DPCPP_CPU_CU_AFFINITY=spread: S0:[T0 T2 T4 T6 T8 T10 T12 T14] S1:[T1 T3 T5 T7 T9 T11 T13
T15]
DPCPP_CPU_CU_AFFINITY=master: S0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[T8 T9 T10 T11 T12 T13 T14
T15]
export DPCPP_CPU_PLACES=cores
DPCPP_CPU_CU_AFFINITY=close: S0:[T0 T8 T1 T9 T2 T10 T3 T11] S1:[T4 T12 T5 T13 T6 T14 T7
T15]
DPCPP_CPU_CU_AFFINITY=spread: S0:[T0 T8 T2 T10 T4 T12 T6 T14] S1:[T1 T9 T3 T11 T5 T13 T7
T15]
DPCPP_CPU_CU_AFFINITY=master: S0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[T8 T9 T10 T11 T12 T13 T14
T15]
export DPCPP_CPU_PLACES=threads

63インテル® oneAPI プログラミング・ガイド

DPCPP_CPU_CU_AFFINITY=close: S0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[T8 T9 T10 T11 T12 T13 T14
T15]
DPCPP_CPU_CU_AFFINITY=spread: S0:[T0 T2 T4 T6 T8 T10 T12 T14] S1:[T1 T3 T5 T7 T9 T11 T13
T15]
DPCPP_CPU_CU_AFFINITY=master: S0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[T8 T9 T10 T11 T12 T13 T14
T15]
export DPCPP_CPU_NUM_CUS=8DPCPP_CPU_PLACES=sockets, cores and threads have the same bindings:
DPCPP_CPU_CU_AFFINITY=close close: S0:[T0 - T1 - T2 - T3 -] S1:[T4 - T5 - T6 - T7 -]DPCPP_CPU_CU_AFFINITY=close spread: S0:[T0 - T2 - T4 - T6 -] S1:[T1 - T3 - T5 - T7 -]DPCPP_CPU_CU_AFFINITY=close master: S0:[T0 T1 T2 T3 T4 T5 T6 T7] S1:[]

4.6.7.3.

例 2: インテル® ハイパースレッディング・テクノロジー無効

2 ソケットで、ソケットごとに 4 つの物理コアがあり、それぞれの物理コアには 2 つのハイパースレッドがあるマシンを想定します。
S<num> は、リストで指定される 8 つのコアを持つソケット番号を示します。

T<num> は、インテル® oneTBB のスレッド番号を示します。

"-" は未使用のコアを意味します。

export DPCPP_CPU_NUM_CUS=8DPCPP_CPU_PLACES=sockets, cores and threads have the same bindings:
DPCPP_CPU_CU_AFFINITY=close:
S0:[T0 T1 T2 T3]
S1:[T4 T5 T6 T7]DPCPP_CPU_CU_AFFINITY=spread: S0:[T0 T2 T4 T6]
S1:[T1 T3 T5 T7]
DPCPP_CPU_CU_AFFINITY=master: S0:[T0 T1 T2 T3]
S1:[T4 T5 T6 T7]export DPCPP_CPU_NUM_CUS=4DPCPP_CPU_PLACES=sockets, cores and threads have the same bindings:
DPCPP_CPU_CU_AFFINITY=close:
S0:[T0 - T1 - ]S1:[T2 - T3 - ]DPCPP_CPU_CU_AFFINITY=spread: S0:[T0 - T2 - ]S1:[T1 - T3 - ]DPCPP_CPU_CU_AFFINITY=master: S0:[T0 T1 T2 T3]
S1:[ - - - - ]4.7 GPU 手順
GPU は、アプリケーションの計算集約型領域の負荷を軽減する用途で使用できる特殊な計算デバイスです。通常、GPUは多数の小規模なコアで構成され、大量のスループットをもたらします。タスクには、CPU に適したものと GPU に適したものがあります。

ヒント: ワークロードが CPU、GPU、または FPGA に最適であるか不明な場合は、「各種 oneAPI
ワークロードに対する CPU、GPU、および FPGA の利点の比較」 (英語) を参照してください。

64

インテル® oneAPI プログラミング・ガイド

4.7.1 GPU オフロードの手順
プログラムを GPU にオフロードすると、デフォルトでレベルゼロのランタイムが利用されます。OpenCL* ランタイムに切り替えるオプションも用意されています。SYCL* および OpenMP* オフロードでは、各ワーク項目は SIMD レーンにマップされます。サブグループは並列に実行されるワーク項目で形成される SIMD 幅に分割され、サブグループは
GPU の EU スレッドにマップされます。ローカルデータを同期または共有するワーク項目を含むワークグループは、計算ユニット (ストリーミング・マルチプロセッサーまたは Xe コア – サブスライスとも呼ばれます) での実行に割り当てられます。最後に、ワーク項目のグローバル ND-Range 全体が GPU 全体にマップされます。
RPG インターフェイスの GPU ワークグループ

GPU 実行の詳細については、「各種 oneAPI コンピューティング・ワークロードに対する CPU、GPU、および FPGA の利点の比較」 (英語) を参照してください。

4.7.1.1.

GPU オフロード向けの設定

1.

setvars スクリプトの実行を含む、「oneAPI 開発環境の設定」セクションのすべての手順を実行したことを確
認します。

2.

ドライバーをインストールして GPU システムを構成し、ユーザーを video グループに追加します。詳細について
は、導入ガイドを参照してください。
‐

インテル® oneAPI ベース・ツールキット導入ガイド (Linux* | Windows* | MacOS*) (英語)‐インテル® oneAPI HPC ツールキット導入ガイド (Linux* | Windows* | MacOS*) (英語)‐インテル® oneAPI IoT ツールキット導入ガイド (Linux* | Windows*) (英語)65インテル® oneAPI プログラミング・ガイド

3.

sycl-ls コマンドを使用して、サポートされている GPU と必要なドライバーがインストールされていることを確認します。次の例では、OpenCL* およびレベルゼロドライバーがインストールされている場合、GPU に関連付けられたランタイムごとに 2 つのエントリーが表示されています。

CPU : OpenCL 2.1 (Build 0)[ 2020.11.12.0.14_160000 ]GPU : OpenCL 3.0 NEO [ 21.33.20678 ]GPU : 1.1[ 1.2.20939 ]4.

次のサンプルコードを使用して、コードが GPU で実行されていることを確認します。サンプルコードは、整数の大きなベクトルにスカラーを加算し、結果を検証します。

SYCL*
SYCL* では GPU で実行するための組込みデ スセレクターが用意されています。これは、device_selector 基本クラスを使用し gpu_selector で GPU デバイスを選択できます。独自のカスタムセレクターを作成することもできます。
詳細については、『Data Parallel C++』書籍の「Choosing Devices (デバイスの選択)」 (英語) を参照してください。
SYCL* サンプルコード:
1. #include <CL/sycl.hpp>
2. #include <array>
3. #include <iostream>4.
5. using namespace sycl;
6. using namespace std;
7. constexpr size_t array_size = 10000;
8. int main(){9.
constexpr int value = 100000;
10.
try{
11.
//
12.
// デフォルトのデバイスセレクターは、最もパフォーマンスが高いデバイスを選択します13.
default_selector d_selector;
14.
queue q(d_selector);
15.
16.
// USM を使用した共有メモリー割り当て17.
int *sequential = malloc_shared<int>(array_size, q);
18.
int *parallel = malloc_shared<int>(array_size, q);
19.
// シーケンシャル iota20.
for (size_t i = 0; i < array_size; i++) sequential[i] = value + i;
21.
22.
// SYCL* の並列 iota
23.
auto e = q.parallel_for(range{array_size}, [=](auto i) { parallel[i] = value + i; });24.
e.wait();25.
// 2 つの結果が等しいか検証
26.
for (size_t i = 0; i < array_size; i++) {27.
if (parallel[i] != sequential[i]) {28.
cout << "Failed on device.\n";29.
return -1;
30.
}
31.
}
32.
free(sequential, q);33.
free(parallel, q);34.
}catch (std::exception const &e) {35.
cout << "An exception is caught while computing on device.\n";36.
terminate();66

インテル® oneAPI プログラミング・ガイド

37.
}
38.
cout << "Successfully completed on device.\n";39.
return 0;
40. }次のコマンドでサンプルコードをコンパイルします。
$ icpx -fsycl simple-iota-dp.cpp -o simple-iota

生成したバイナリーを実行します。
$ ./simple-iota
Running on device: Intel® UHD Graphics 630 [0x3e92]
Successfully completed on device.

OpenMP*
OpenMP* のサンプルコード:
1. #include <stdlib.h>
2. #include <omp.h>
3. #include <iostream>
4. constexpr size_t array_size = 10000;
5.
6. #pragma omp requires unified_shared_memory
7. int main(){8.
constexpr int value = 100000;
9.
// デフォルトのターゲットデバイスを返します10.
int deviceId = (omp_get_num_devices() > 0) ? omp_get_default_device() :omp_get_initial_device();11.
int *sequential = (int *)omp_target_alloc_host(array_size, deviceId);
12.
int *parallel = (int *)omp_target_alloc(array_size, deviceId);13.
14.
for (size_t i = 0; i < array_size; i++)15.
sequential[i] = value + i;
16.
17.
#pragma omp target parallel for18.
for (size_t i = 0; i < array_size; i++)19.
parallel[i] = value + i;
20.
21.
for (size_t i = 0; i < array_size; i++) {22.
if (parallel[i] != sequential[i]) {23.
std::cout << "Failed on device.\n";24.
return -1;
25.
}
26.
}
27.
28.
omp_target_free(sequential, deviceId);29.
omp_target_free(parallel, deviceId);30.
31.
std::cout << "Successfully completed on device.\n";32.
return 0;
33. }

67

インテル® oneAPI プログラミング・ガイド

次のコマンドでサンプルコードをコンパイルします。
$ icpx -fsyclsimple-iota-omp.cpp -fiopenmp -fopenmp-targets=spir64 -o simple-iota

生成したバイナリーを実行します。
$ ./simple-iota
Successfully completed on device.

注 : オ フ ロ ー ド 領 域 が 存 在 し 、 ア ク セ ラ レ ー タ ー が な い 場 合 、 OMP_TARGET_OFFLOAD=
mandatory 環境変数が指定されない限り、カーネルは従来のホストコンパイル (OpenCL* ラン
タイムなし) にフォールバックします。

4.7.1.2.

GPU へコードをオフロード

どの GPU ハードウェアで、どのコード領域をオフロードするか決定するには、「GPU 最適化ワークフロー・ガイド」 (英語)を参照してください。
オフロードするコード領域を特定するには、インテル® Advisor のオフロードのモデル化 (英語) が役立ちます。
4.7.1.2.1.

GPU コードのデバッグ

以下のリストには、オフロードされるコードの基本的なデバッグのヒントが示されています。
CPU またはホスト/ターゲットをチェック、またはランタイムを OpenCL* に切り替えてコードが正しいことを確
認します。



printf を使用して、アプリケーションをデバッグします。SYCL* と OpenMP* オフロードでは、どちらもカーネルコードで printf がサポートされます。



環境変数を設定して詳細なログ情報を取得します。

68インテル® oneAPI プログラミング・ガイド

SYCL では、次のデバッグ環境変数を利用できます。すべての環境変数については GitHub* (英語) をご覧ください。
オフロードコードのデバッグのヒント
環境変数
SYCL_DEVICE_FILTERSYCL_PI_TRACE

値
backend:device_type:device_num
1|2|-1

説明
GitHub* の説明を参照してください。
1: DPC++ ランタイムプラグインの基本トレースロ
グを出力します。
2: DPC++ ランタイムプラグインのすべての API ト
レースを出力します。

ZE_DEBUG

任意の値で定義された変数 (有効)-1: 2 のすべてと追加のデバッグ情報を出力します。
この環境変数は、DPC++ ランタイムが使用された
際にレベルゼロ・バックエンドからのデバッグ出力を有効にします。以下が報告されます。


レベルゼロ API の呼び出し
レベルゼロイベント情報

OpenMP* では、次のデバッグ環境変数が推奨されます。利用可能なすべての環境変数については、「LLVM/OpenMP*
ドキュメント」 (英語) を参照してください。
OpenMP* デバッグで推奨される環境変数
環境変数
LIBOMPTARGET_DEVICETYPE
LIBOMPTARGET_DEBUG
LIBOMPTARGET_INFO

値
cpu | gpu
1
LLVM/OpenMP* のドキュメントで利用可能な値 (英語)

説明
デバイスを選択します。
詳細なデバッグ情報を出力します。
ユーザーがさまざまなタイプのランタイム情報を libomptarget から取得できるようにします。

事前 (AOT) コンパイルを使用して、ジャストインタイム (JIT) コンパイルを AOT コンパイルに移行します。
4.7.1.2.2.

CL_OUT_OF_RESOURCES エラー

CL_OUT_OF_RESOURCES エラーは、エミュレーターがデフォルトでサポートする __private メモリーもしくは__local メモリーよりも多くのメモリーをカーネルが使用すると発生する可能性があります。

69

インテル® oneAPI プログラミング・ガイド

このエラーが発生すると、次のようなメッセージが表示されます。
$ ./myapp: Problem size: c(150,600) = a(150,300) * b(300,600)
terminate called after throwing an instance of 'cl::sycl::runtime_error'
what(): Native API failed. Native API returns: -5 (CL_OUT_OF_RESOURCES) -5(CL_OUT_OF_RESOURCES)
Aborted (core dumped)$

または、onetrace を使用する場合は、次のようなメッセージが表示されます。
$ onetrace -c ./myapp: >>>> [6254070891] zeKernelSuggestGroupSize: hKernel = 0x263b7a0 globalSizeX = 163850
globalSizeY = 1 globalSizeZ = 1 groupSizeX = 0x7fff94e239f0 groupSizeY = 0x7fff94e239f4
groupSizeZ = 0x7fff94e239f8<<<< [6254082074] zeKernelSuggestGroupSize [922 ns] ->ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY(0x1879048195)
terminate called after throwing an instance of 'cl::sycl::runtime_error'
what(): Native API failed. Native API returns: -5 (CL_OUT_OF_RESOURCES)-5 (CL_OUT_OF_RESOURCES)
Aborted (core dumped)$

共有ローカルメモリーにコピーされたメモリー量とハードウェアの制限を確認するには、デバッグキーを設定します。
export PrintDebugMessages=1
export NEOReadDebugKeys=1

これにより、出力は次のようになります。
$ ./myapp:Size of SLM (656384) larger than available (131072)
terminate called after throwing an instance of 'cl::sycl::runtime_error'
what(): Native API failed. Native API returns: -5 (CL_OUT_OF_RESOURCES) -5(CL_OUT_OF_RESOURCES)
Aborted (core dumped)$

または、onetrace を使用する場合は、次のようになります。
$ onetrace -c ./myapp:>>>> [317651739] zeKernelSuggestGroupSize: hKernel = 0x2175ae0 globalSizeX = 163850
globalSizeY = 1 globalSizeZ = 1 groupSizeX = 0x7ffd9caf0950 groupSizeY = 0x7ffd9caf0954
groupSizeZ = 0x7ffd9caf0958
Size of SLM (656384) larger than available (131072)<<<< [317672417] zeKernelSuggestGroupSize [10325 ns] ->ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY(0x1879048195)
terminate called after throwing an instance of 'cl::sycl::runtime_error'
what(): Native API failed. Native API returns: -5 (CL_OUT_OF_RESOURCES) -5(CL_OUT_OF_RESOURCES)
Aborted (core dumped)$

70

インテル® oneAPI プログラミング・ガイド

oneAPI で利用可能なデバッグ手法とデバッグツールの詳細については、「DPC++ および OpenMP* オフロード処理のデバッグ」を参照してください。

4.7.1.3.

GPU コードの最適化

オフロードコードを最適化するにはいくつかの方法があります。次の表には、最適化のヒントが示されています。詳細については、「oneAPI GPU 最適化ガイド」を参照してください。


ホストとデバイス間のメモリー転送のオーバーヘッドを削減します。



コアをビジー状態に維持し、データ転送のオーバーヘッドのコストを軽減するため十分な量のワークを実行します。

GPU キャッシュ、共有ローカルメモリーなど GPU メモリー階層を活用して、メモリーアクセスを高速化します。

JIT コンパイルの代わりに AOT コンパイル (オフラインコンパイル) を使用します。事前コンパイルでは、コードを特定の GPU アーキテクチャーをターゲットにできます。詳細については、「GPU 向けの事前 (AOT) コンパイ
ル」を参照してください。

インテル® GPU Occupancy Calculator (英語) を使用すると、特定のカーネルおよびワークグループのパラメー
ターに対するインテル® GPU の占有率を計算できます。

「オフロード・パフォーマンスの最適化」で追加の推奨事項が提供されています。

4.7.2 GPU コマンドの例
次の例は、Linux* でデバイスコードを使用して静的ライブラリーを作成し、使用する方法を示します。

注: 動的ライブラリーとのリンクはサポートされていません。

デバイスコードを使用してファット・オブジェクトを生成します。
$ icpx -fsycl -c static_lib.cpp

ar ツールを使用して、静的ファット・ライブラリーを作成します。
$ ar cr libstlib.a static_lib.o

アプリケーションのソースをコンパイルします。
$ icpx -fsycl -c a.cpp

静的ライブラリーとアプリケーションをリンクします。
$ icpx -fsycl -foffload-static-lib=libstlib.a a.o -o a.exe

71インテル® oneAPI プログラミング・ガイド

4.7.3 GPU アーキテクチャー向けの事前 (AOT) コンパイル
次のコマンドは、特定の GPU ターゲット向けに app.out を生成します。
DPC++:$ icpx -fsycl-targets=spir64_gen -Xs "-device <device name>" a.cpp b.cpp -o app.out

OpenMP* オフロード:$ icpx -fiopenmp -fopenmp-targets=spir64_gen -Xopenmp-target-backend "-device <device name>"a.cpp b.cpp -o app.out

デバイス名に利用できる値の一覧は、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』 (英語) から入手できます。

4.8 FPGA 手順
フィールド・プログラマブル・ゲートアレイ (FPGA) は、任意の機能を実行するように繰り返しプログラム可能な集積回路です。FPGA は、空間コンピューティング・アーキテクチャーとして分類され、CPU や GPU のような固定命令セット・アーキテクチャー (ISA) デバイスとは異なり、従来のアクセラレーター・デバイスとは異なる最適化のトレードオフが求められます。
CPU、GPU、または FPGA 向けに SYCL* コードをコンパイルできますが、FPGA 開発用のコンパイル手順は、CPU や
GPU 開発におけるコンパイル手順とは多少異なります。
次の表に FPGA 手順の説明で使用される用語をまとめています。
FPGA 手順固有の用語
用語
デバイスコード
ホストコードデバイスイメージ

FPGA エミュレーター・イメージ
FPGA 初期イメージ
FPGA ハードウェア・イメージ72

定義
ホストではなくデバイスで実行される SYCL ソースコード。デバイスコードは、ラムダ式、ファンクター、またはカーネルクラスを介して指定されます。
ホスト・コンパイラーによってコンパイルされ、デバイスではなくホストで実行される
SYCL ソースコード。
デバイスコードをバイナリー (または中間形式) 表現にコンパイルした結果のファイル。
デバイスイメージは、(ファット) オブジェクトまたは実行ファイル内でホスト・オブジェ
クトと結合されます。「コンパイル手順」を参照してください。
FPGA エミュレーター向けにコンパイルされたデバイスイメージ。「FPGA エミュレー
ター」を参照してください。
初期コンパイルステージによるデバイスイメージ。「FPGA 最適化レポート」を参照してください。
ハードウェア・イメージのコンパイルステージによるデバイスイメージ。「FPGA 最適化
レポート」と「FPGA ハードウェア」を参照してください。

インテル® oneAPI プログラミング・ガイド

ヒント: FPGA プログラミングの詳細は、https://link.springer.com/chapter/10.1007/978-14842-5574-2_17 (英語) から入手できる『Data Parallel C++』書籍からも学ぶことができます。

4.8.1 FPGA 向けのコンパイルが特殊である理由
FPGA はいくつかの点で CPU や GPU とは異なります。CPU や GPU と比較した大きな違いは、FPGA ハードウェア専用のデバイスバイナリーが必要なことです。これはほとんどの場合、計算集約型で時間がかかる処理です。FPGA のコン
パイルが完了するまで数時間かかるのは通常の動作です。そのため、FPGA 開発向けに事前 (オフライン) カーネル・コン
パイル・モードのみがサポートされます。FPGA ハードウェアのコンパイルには時間がかかるため、ジャストインタイム(オンライン) コンパイルは実用的ではありません。
コンパイル時間が長くなるほど、開発者の生産性は悪化します。インテル® oneAPI DPC++/C++ コンパイラーは、
FPGA をターゲットとする開発設計を素早く反復できるメカニズムを提供します。可能な限り完全な FPGA コンパイルにかかる手順を回避することで、CPU および GPU 開発に近い感覚で高速コンパイル時間の恩恵を受けられます。

4.8.2 SYCL* FPGA コンパイルの種別
SYCL* はアクセラレーター全般をサポートします。インテル® oneAPI DPC++/C++ コンパイラーは、FPGA コードの開発を支援するため、FPGA 固有のサポートを提供します。このドキュメントでは、インテル® oneAPI ベース・ツールキット
がサポートするさまざまな FPGA コンパイル手順について説明します。
以下の表に、FPGA コンパイルの要約を示します。
FPGA コンパイルの種別
デバイス・イメージ・タイプ
FPGA エミュレーター

コンパイル時間
数秒

最適化レポート

数分

FPGA シミュレーター

数分

説明
FPGA デ バ イ ス コ ー ド は CPU 向 け に コ ン パ イ ル さ れ ま す 。
OpenCL* ソフトウェア向けインテル® FPGA エミュレーション・プ
ラットフォームを使用して、SYCL* コードが正しく機能することを確認します。
FPGA デバイスコードは部分的にハードウェア向けにコンパイルされます。コンパイラーは、FPGA で生成される構造とパフォーマ
ンスのボトルネックを特定し、リソース利用率を推測して最適化レ
ポートを生成します。コンパイルで FPGA デバイスファミリーまたは製品番号をターゲットにする場合、このステージでコード内のIP コンポーネントの RTL ファイルも作成されます。その後、
インテル® Quartus® Prime 開発ソフトウェアを使用して、IP コン
ポーネントをさらに大きな設計に統合できます。
FPGA デバイスコードは CPU にコンパイルされます。Questa*インテル® FPGA Edition Software のシミュレーターを使用して、コードをデバッグします。

73インテル® oneAPI プログラミング・ガイド

デバイス・イメージ・タイプ
FPGA ハードウェア・イメージ

コンパイル時間
数時間

説明
ターゲットの FPGA プラットフォームで実行する FPGA ビットス
トリームを生成します。コンパイルで FPGA デバイスファミリーまたは製品番号をターゲットにする場合、このステージでコード内の IP コンポーネントの RTL ファイルも作成されます。その後、
インテル® Quartus® Prime 開発ソフトウェアを使用して、IP コン
ポーネントをさらに大きな設計に統合できます。

一般的な FPGA 開発ワークフローでは、エミュレーション、最適化レポート、およびシミュレーション・ステージを繰り返して、それぞれのステージからもたらされるフィードバックを反映してコードを改良します。可能な限りエミュレーションと FPGA 最適化レポートを活用することを推奨します。
IP コンポーネントの開発時にこれらのステージがどのように適用されるかは、「FPGA IP オーサリング手順」を参照して
ください。

ヒント:
FPGA エミュレー ション向けに コンパイルし たり、 FPGA 最適化レポートを生成するに は 、インテル® oneAPI ベース・ツールキットのインテル® oneAPI DPC++/C++ コンパイラーのみが必要です。
FPGA ハードウェアのコンパイルには、インテル® Quartus® Prime 開発ソフトウェアを別途インストールする必要があります。ボードをターゲットにする場合、ボード用の BSP をインストールする必
要があります。
詳細については、『インテル® oneAPI ツールキット・インストール・ガイド』（英語）とインテル®
FPGA 開発手順のページ（英語）をご覧ください。
また、IP コンポーネントの RTL コードを生成するには、インテル® oneAPI ベース・ツールキットに含まれる、インテル® oneAPI DPC++/C++ コンパイラーのみが必要です。ただし、IP コンポーネン
トをハードウェア設計でシミュレーションまたは統合するには、インテル® Quartus® Prime 開発ソ
フトウェア・プロ・エディションをインストールする必要があります。

4.8.2.1.

FPGA エミュレーターFPGA エミュレーター (OpenCL* ソフトウェア向けインテル® FPGA エミュレーション・プラットフォーム) は、コードの正当性を検証する最速の手法です。CPU 上で SYCL* デバイスコードを実行します。FPGA エミュレーターは、SYCL* ホ
ストデバイスに似ていますが、ホストデバイスとは異なり、FPGA パイプや fpga_reg など FPGA 拡張機能がサポートされます。詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「パイプ拡張」 (英語) と「カーネル変数」 (英語) を参照してください。
次に FPGA エミュレーターを使用する際に覚えておくべき重要事項を示します。

74インテル® oneAPI プログラミング・ガイド

パフォーマンスは典型的なものではない。
FPGA エミュレーターは、FPGA デバイスの動作そのものを再現するものではないため、パフォーマンスの評価に使用しないでください。例えば、FPGA で 100 倍のパフォーマンス向上をもたらす最適化は、エミュレーターのパ
フォーマンスには影響しないか、多少の増減を示すことがあります。



未定義の動作は異なる可能性があります。
FPGA エミュレーターと FPGA ハードウェア向けにコンパイルしたコードの結果が異なる場合、コードに未定義の動作が含まれる可能性があります。未定義の動作は言語仕様では指定されておらず、ターゲットごとに振る舞いが異なる可能性があります。

フルスタック・アクセラレーション・カーネルのエミュレーションの詳細については、「カーネルのエミュレート」を参照してください。
IP コンポーネントのエミュレーションの詳細については、「IP コンポーネントのエミュレーションとデバッグ」を参照してください。

4.8.2.2.

FPGA 最適化レポート

完全な FPGA コンパイルは次のステージで行われ、最適化レポートは両方のステージの後に出力されます。
FPGA 最適化レポート
ステージ
FPGA 初期イメージ(コンパイルには数分かかります)説明SYCL* デ バ イ ス コ ー ド は 最 適 化 さ れ 、Verilog レ ジ ス タ ー 転 送 レ ベ ル (RTL)(FPGA の低レベルの設計入力言語) で指定される FPGA 設計に変換されます。これにより、実行形式ファイではない FPGA 初期イメージが生成されます。
このステージでは静的な最適化レポートが生成されます。

FPGA ハードウェア・イメージ(コンパイルには数時間かかります)

設計回路のトポロジーを指定する Verilog
RTL は、インテル® Quartus® Prime 開発ソ
フトウェア・プロ・エディションソフトウェア
によって FPGA のプリミティブ・ハードウェ
ア・リソースにマッピングされます。結果は、FPGA ハードウェア・バイナリー (ビットスト
リーム) です。

最適化レポートの情報
これには、コンパイラーが SYCL* デバイス
コードから FPGA 設計に変換した手法に関する重要な情報が含まれています。レポートには次の情報が含まれます。


FPGA で生成された構造の可視化情報
パフォーマンスと予期されるパフォー
マンスのボトルネックに関する情報
リソースの利用状況を推測

FPGA の 最 適 化 レ ポ ー ト に つ い て は 、『インテル® oneAPI ツールキット向け FPGA
最適化ガイド』 (英語) を参照してください。
リソースと fMAX 数に関する正確な情報が含まれます。レポートの解析に関する詳細は、『インテル® oneAPI ツールキット向け FPGA
最適化ガイド』の「設計の解析」 (英語) を参照してください。
FPGA の 最 適 化 レ ポ ー ト に つ い て は 、『インテル® oneAPI ツールキット向け FPGA
最適化ガイド』 (英語) を参照してください。

75インテル® oneAPI プログラミング・ガイド

コンパイルで FPGA デバイスまたは製品番号をターゲットにする場合、このステージでコード内の IP コンポーネントのRTL ファイルも作成されます。その後、インテル® Quartus® Prime 開発ソフトウェアを使用して、IP コンポーネントをさらに大きな設計に統合できます。

4.8.2.3.

FPGA シミュレーター

シミュレーション手順では、Questa*-インテル® FPGA Edition Software のシミュレーターを使用して、合成されたカーネルの正確な動作をシミュレートできます。エミュレーションと同様に、ターゲットの FPGA ボードが装着されていないシステムでシミュレーションを実行できます。シミュレーターは、エミュレーションよりも正確にカーネルをモデル化できますが、エミュレーターよりもかなり低速です。
シミュレーション手順は、サイクル精度とビット精度を目的とし、カーネルのデータパスの動作と浮動小数点データ型の操作結果を正確にモデル化します。ただし、シミュレーションでは、可変レイテンシー・メモリーやその他の外部インターフェイスを正確にモデル化することはできません。シミュレーションは FPGA ハードウェアやエミュレーターよりもかな
り低速であるため、小規模な入力データセットで設計をシミュレーションすることを推奨します。
シミュレーション手順をプロファイルと組み合わせて利用することで、設計に関する追加情報を取得できます。プロファ
イルの詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「DPC++ 向けインテル® FPGA
ダイナミック・プロファイラー」 (英語) を参照してください。

注: GNU* Project Debugger (GDB)、Microsoft* Visual Studio* または通常のソフトウェア・デバッガーを使用して、シミュレーション向けにコンパイルされたカーネルコードをデバッグすることはできません。

シミュレーション手順の詳細については、以下を参照してください。
シミュレーションによるカーネルの評価



シミュレーションによる IP コンポーネントの評価

4.8.2.4.

FPGA ハードウェア

FPGA ハードウェアのコンパイルには、インテル® Quartus® Prime 開発ソフトウェア (英語) を別途インストールする必要があります。これは、次のいずれかをターゲットにする FPGA ハードウェア・イメージの完全なコンパイルステージです。
インテル® FPGA デバイスファミリー

特定のインテル® FPGA デバイスの製品番号



サポートされる BSP を持つカスタムボード

インテル® FPGA プログラマブル・アクセラレーション・カード (インテル® FPGA PAC) 非推奨

76インテル® oneAPI プログラミング・ガイド

ターゲットの詳細については、「インテル® oneAPI DPC++/C++ コンパイラーのシステム要件」 (英語) を参照してください。インテル® FPGA PAC またはカスタムボードの使用に関する詳細は、「FPGA BSP とボード」の節と、『インテル®
oneAPI ツールキット・インストール・ガイド (Linux*)』 (英語) を参照してください。

4.8.3 FPGA コンパイルオプション
FPGA コンパイルオプションは、インテル® oneAPI DPC++/C++ コンパイラーがターゲットとする FPGA イメージタイ
プをコントロールします。
以下は、3 つの FPGA イメージタイプをターゲットとするインテル® oneAPI DPC++/C++ コンパイラーのコマンド例です。
# FPGA エミュレーター・イメージ$ icpx -fsycl -fintelfpga fpga_compile.cpp -o fpga_compile.fpga_emu# FPGA シミュレーター・イメージ: FPGA デバイスファミリー# このリリースでは、次のいずれかの形式のインテル® Agilex® 7 デバイスをターゲットにできます# -Xstarget=Agilex | -Xstarget=Agilex7 | -Xstarget="Agilex 7" |# -Xstarget=agilex7 | -Xstarget="agilex 7" |# 次のコマンドは、サポートされる形式の一例です$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xssimulation -Xstarget=Agilex7 -Xsghdl -o
fpga_compile.fpga_sim# FPGA シミュレーター・イメージ: FPGA 製品番号
$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xssimulation -Xstarget=AGFB014R24A3EV -Xsghdl -o
fpga_compile.fpga_sim# FPGA シミュレーター・イメージ: ボードを明示$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xssimulation -Xstarget=intel_s10sx_pac:pac_s10 -o
fpga_compile.fpga_sim# FPGA 初期イメージ (最適化レポートも生成): FPGA デバイスファミリー$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -fsycl-link=early -Xstarget=Stratix10-o fpga_compile_report.a# FPGA 初期イメージ (最適化レポートも生成): FPGA 製品番号
$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -fsycl-link=early Xstarget=1SG280LU3FS0E3VG -o fpga_compile_report.a# FPGA 初期イメージ (最適化レポートも生成): デフォルトボード$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -fsycl-link=early -o
fpga_compile_report.a# FPGA 初期イメージ (最適化レポートも生成): ボードを明示$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -fsycl-link=early Xstarget=intel_s10sx_pac:pac_s10 -o fpga_compile_report.a# FPGA ハードウェア・イメージ: FPGA デバイスファミリー$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -Xstarget=Arria10 -o fpga_compile.fpga# FPGA ハードウェア・イメージ: FPGA 製品番号77

インテル® oneAPI プログラミング・ガイド$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -Xstarget=10AX115S2F45I1SG -o
fpga_compile.fpga# FPGA ハードウェア・イメージ: デフォルトのボード$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -o fpga_compile.fpga# FPGA ハードウェア・イメージ： ボードを明示$ icpx -fsycl -fintelfpga fpga_compile.cpp -Xshardware -Xstarget=intel_s10sx_pac:pac_s10 -o
fpga_compile.fpga

次の表は上記のコマンド例で使用するオプションを説明しています。

注: -o オプションを指定すると、出力ディレクトリーの名前は -o で指定した内容で決定されます。
例えば、-o fpga_compile.fpga を指定すると、出力ディレクトリーは fpga_compile.prjになります。-o オプションを省略すると、出力ディレクトリーは常に a.prj になります。

FPGA コンパイルオプション
オプション-fintelfpga-Xshardware

説明
FPGA 向けに AOT (オフライン) コンパイルします。
FPGA ハードウェアをターゲットにすることをコンパイラーに指示します。
このオプションが省略されると、コンパイラーは FPGA エミュレーターをターゲットにします。
注: プリフィクス -Xs を使用して、引数を FPGA
バックエンドに渡します。

-Xsemulator-Xssimulation-fsycl-link=early-Xstarget=<FPGA デバイスファミリー>-Xstarget=<FPGA 製品番号>-Xsboard=<bsp:variant>

エミュレーション・デバイス・イメージを生成します。これは、デフォルトの動作です。
エミュレーション・デバイス・イメージを生成します。
FPGA 初期イメージ (および関連する最適化レポート) を作成して停止する
ようコンパイラーに指示します。
[オプション] FPGA デバイスファミリー、FPGA 製品番号、または FPGA
ボードをターゲットにするようコンパイラーに指示します。
-Xstarget=<FPGA デバイスファミリー> で FPGA のデバイスファ
ミリーを指定します。このターゲットを使用して初期開発を容易にします。
さらに正確なレポートを取得するには、-Xstarget=<FPGA 製品番
号 > ま た は -Xstarget=<bsp:variant> を 使 用 し て 、特 定 のFPGA デバイスやアクセラレーション・プラットフォームをターゲットにします。
有効な値は、CycloneV、Cyclone10GX、Agilex7、Arria10、および Stratix10 です。

78インテル® oneAPI プログラミング・ガイド

オプション

説明
これらの値は、次の FPGA デバイスの製品番号 (OPN) を対象にします。
‐

CycloneV：5CGXFC7C7F23C8‐

Cyclone10GX：10CX220YF780I5G‐

Agilex7：AGFB014R24A2E2V-R0‐

Arria10：10AX115U1F45I1SG‐Stratix10：1SG280LU3F50I2VG

注:
このリリースでは、次のいずれかの形式のインテル®
Agilex® 7 デバイスをターゲットにできます。









-Xstarget=Agilex-Xstarget=Agilex7-Xstarget="Agilex 7"-Xstarget=agilex7-Xstarget="agilex 7"-Xstarget=<FPGA 製品番号> は、ターゲットの FPGA 製品番
号 （OPN） を指定します。有効な Cyclone® V、インテル® Cyclone®
10 GX、インテル® Agilex® 7、インテル® Arria® 10、またはインテル®
Stratix® 10 製品番号を指定できます。
-Xstarget=<bsp:variant> は 、FPGA ボード のバリアントと
BSP を指定します。詳細については、「FPGA BSP とボード」を参照してください。

-Xstarget オプションを省略すると、コンパイラーは intel_a10gx_pac
BSP から、デフォルトの FPGA ボードバリアント pac_a10 を選択します（-Xstarget=intel_a10gx_pac:pac_a10 と同等)。

警告: icpx コンパイルコマンドの出力は、同じ出力名を持つ以前のコンパイル出力を上書きします。そのため、一意の出力名 (-o で指定) を使用することを推奨します。失ったハードウェア・イメー
ジの再生成には数時間を要することがあるため、FPGA コンパイルでは注意する必要があります。

上記のコンパイルオプションに加えて、icpx コマンドの出力詳細レベルやコンパイルで使用するスレッド数をコントロールするオプションも用意されています。次のセクションでは、これらのオプションについて簡単に説明します。

4.8.3.1.

コンパイラーでサポートされるその他の SYCL* FPGA オプション

インテル® oneAPI DPC++/C++ コンパイラーには、カーネルのコンパイルプロセスをカスタマイズするオプションが用意されています。次の表にコンパイラーがサポートするその他のオプションをまとめています。

79インテル® oneAPI プログラミング・ガイド

その他の FPGA オプション
オプション名-fsycl-help=fpga-fsycl-link=early-fsycl-link=image-reuse-exe=<exe_file>-Xsv-Xsghdl[=<depth>]-Xsparallel=<num_threads>-Xsseed=<value>-Xsfast-compile

説明
icpx の FPGA 固有のオプションを出力します。
-fsycl-link=early と -fsycl-link は同じ意味です。どちらも、FPGA 初期
イメージ (および関連する最適化レポート) を作成して停止するようコンパイラーに指示します。
-fsycl-link=image は、デバイスリンクのコンパイル手順で使用され、FPGA
ハードウェア・イメージを生成するようにコンパイラーに指示します。詳細について
は、「FPGA 高速再コンパイル」を参照してください。
既存の実行形式ファイルから FPGA ハードウェア・シミュレーション・イメージを抽出して、新しい実行形式ファイルにパッケージするようにコンパイラーに指示します。
これにより、デバイスコンパイルの時間を節約します。このオプションは、エミュレー
ション向けにコンパイルする場合は適用されません。詳細については、「FPGA 高速
再コンパイル」を参照してください。
FPGA バックエンドは、コンパイルの進行状況を示すレポートを生成します。
シミュレーション手順で信号を Siemens EDA (以前の Mentor Graphics) Questa*
波形ファイルに記録します。
オプションの <depth> 属性を使用して、ログに記録される階層レベルを指定できます。<denpth> 属性が省略されると、階層レベルは 1 になります。
FPGA ビットストリーム・コンパイルで使用される並列レベルを設定します。
<num_threads> 値には使用する並列スレッドの数を指定します。推奨される最大値は利用可能なコア数です。このオプションは任意です。デフォルトでは、インテル®
Quartus® Prime 開発ソフトウェアは利用可能なすべてのコアを使用して並列コンパイルを行います。
FPGA ビットストリームを生成する際にインテル® Quartus® Prime 開発ソフトウェ
アが使用するシードを設定します。<value> 値、は符号なし整数で、デフォルト値は1 です。
最短時間で FPGA ビットストリームのコンパイルを実行します。このオプションを指定すると、コンパイル時間が短縮されますが、コンパイルされた FPGA ハードウェア・
イメージのパフォーマンスは低下します。このオプションは、開発時間を短縮したい
場合にのみ使用してください。製品レベルの品質は期待できません。
-Xsfast-compile オプションは、インテル® Quartus® Prime 開発ソフトウェア・
プロ・エディションを「高速機能テスト」 (英語) によって限定されるコンパイルモードに設定します。
警告: -Xsfast-compile オプションを使用して SYCL*
カーネルをコンパイルすると、設計のタイミング違反が原因で機能障害が発生する可能性があります。その場合、-Xsfastcompile オプションを使用しないか、カーネルを別のシード
でコンパイルします。

FPGA 最適化オプションの詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「最適化オプション」 (英語) を参照してください。

80

インテル® oneAPI プログラミング・ガイド

4.8.4 設計のエミュレートとデバッグ
OpenCL* ソフトウェア向けインテル® FPGA エミュレーション・プラットフォーム (エミュレーターまたは FPGA エミュ
レーターとも呼ばれます) は、インテル® oneAPI ベース・ツールキット (英語) の一部としてインストールされ、カーネルの機能を評価します。エミュレーターは、64 ビット Windows* および Linux* オペレーティング・システムをサポートします。Linux* システムでは、GNU* C ライブラリー (glibc) バージョン 2.15 以降が必要です。

注:

エミュレートされた設計の実行時間から、FPGA での実行時間を予測することはできません。
また、エミュレートされた設計を実行しても、機能的に同等な C/C++ 実装を x86-64 ホスト
上でネイティブ実行する代わりにはなりません。



エミュレーションは、ARM* プロセッサーのクロスコンパイルはサポートしていません。ARM*
SoC デバイスをターゲットとする設計でエミュレーションを実行するには、非 SoC ボード(intel_a10gx_pac または intel_s10sx_pac など) でエミュレーションしてください。
エミュレーションの結果を確認できたら、SoC ボード上の設計をターゲットにして、以降の最適化ステップに進むことができます。



カーネルコードのデバッグを有効にするため、FPGA エミュレーターの最適化はデフォルトで無効になっています。これにより、カーネルコードをエミュレートする際に実行速度が低下する可能性があります。-g0 オプションを icpx コンパイルコマンドで指定して、デバッグを無効にし、最適化を有効にできます。これによりエミュレーターの実行が高速化されます。



FPGA エミュレーター・デバイスをターゲットにする場合、-O2 コンパイルオプションを使用して最適化を有効にしてエミュレーターを高速化します。(例えばデバッグを容易にするため) 最
適化をオフにするには -O0 オプションを指定します。Windows* Visual C++* デバッガーでは /Od を指定します。

インテル® ディストリビューションの GDB を使用したデバッグについては以下を参照してくだ
さい。
‐
‐
‐

Linux* ホストでのインテル® ディストリビューションの GDB によるデバッグ (英語)Linux* ホストでのインテル® ディストリビューションの GDB の導入ガイド (英語)Windows* ホストでのインテル® ディストリビューションの GDB の導入ガイド (英語)

追加情報については次のトピックを参照してください。


エミュレーターの環境変数



パイプの深度をエミュレートI/O パイプの読み取りまたは書き込みを行うパイプを使用してアプリケーションをエミュレート



設計のコンパイルとエミュレートエミュレーターの制限

ハードウェアとエミュレーターの結果の不一致

81インテル® oneAPI プログラミング・ガイド

エミュレーターの既知の問題

4.8.4.1.

エミュレーターの環境変数

次の表に、エミュレーターの動作制御に利用できる環境変数を示します。
エミュレーターの環境変数
環境変数
CL_CONFIG_CPU_EMULATE_DEVICES

CL_CONFIG_CPU_FORCE_LOCAL_MEM_SIZE

説明
エミュレーター・プラットフォームによって提供される同一エミュレーター・
デバイスの数を制御します。省略されると、単一エミュレーター・デバイスを使用できます。この変数は、複数のデバイスをエミュレートする場合にのみ設定します。
エミュレーターが使用できる最大スレッド数を指定します。デフォルトは
32 で、最大値は 255 です。各スレッドは単一のカーネルを実行できます。
アプリケーションが複数のカーネルを同時に実行する場合、
DPCPP_CPU_NUM_CUS 環境変数を使用するカーネル数以上に設定する必要があります。
使用可能なローカル・メモリー・サイズをユニット単位で指定します。

CL_CONFIG_CPU_FORCE_PRIVATE_MEM_SIZE

例: 8MB、256KB、または 1024B。
使用可能なプライベート・メモリー・サイズをユニット単位で指定します。

DPCPP_CPU_NUM_CUS

例: 8MB、256KB、または 1024B。

注: Windows* では、FPGA エミュレーターがメモ
リー不足で警告なく失敗することがあります。この問題を回避するには、エラーをキャッチするため
try-catch 構文を使用してカーネルコードを記述します。

CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE

4.8.4.2.

カーネルをエミュレーション用にコンパイルする場合、パイプの深度はカー
ネルをハードウェア向けにコンパイルする際のパイプ深度とは異なります。
この動作は、環境変数 CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE
を設定して変更できます。詳細については「パイプの深度をエミュレート」を参照してください。

パイプの深度をエミュレート

カーネルをコンパイルする際に適用されるデフォルトのパイプの深さは、エミュレーション用とハードウェア用のコンパイルでは異なります。環境変数 CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE を設定して、エミュレーション用にカーネルをコンパイルする際の動作を変更できます。

82インテル® oneAPI プログラミング・ガイド

重要: パイプでは、ホストプログラムを実行する前に CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE
環境変数を設定する必要があります。

CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE 環境変数には次の値を設定できます。
CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE 値
環境変数
ignoredepth
default
strict4.8.4.3.

説明
すべてのパイプにカーネル・エミュレーションの実行時間を最速にするパイプの深度が選択されます。
明示的に設定されたパイプ深度属性は無視されます。
明示的な深度属性を持つパイプには深度が指定されます。深度が指定されていないパイプには、カーネル・エミュレーションの実行時間を最速にするデフォルトのパイプ深度が選択されます。
エミュレーションのすべてのパイプ深度に、FPGA コンパイルで指定される深度と同じ深さが設定されます。
深度が指定されない場合、デフォルトの深度は 1 です。CL_CONFIG_CHANNEL_DEPTH_EMULATION_MODE
環境変数が設定されていない場合、これがデフォルトになります。

I/O パイプの読み取りまたは書き込みを行うパイプを使用してアプリケーションをエミュレート

OpenCL* ソフトウェア向けインテル® FPGA エミュレーション・プラットフォームは、カーネル間のパイプをエミュレー
トします。ただし、ターゲットボード上のハードウェア I/O パイプとの直接対話はサポートされていません。次の手順により、I/O パイプの動作をエミュレートできます。
4.8.4.3.1.
1.

入力 I/O パイプ向け

パイプに転送される入力データをパイプの id 特殊化と一致する名前のファイルに保存します。次を考えてみます。

// パイプタイプの特殊化
struct read_io_pipe {static constexpr unsigned id = 0;};
using read_iopipe = sycl::ext::intel::kernel_readable_io_pipe<read_io_pipe, unsigned, 4>;2.

名前 0 のファイルを作成します。

3.

名前 0 のファイルにテスト入力データを保存します。

4.8.4.3.2.

出力 I/O パイプ向け

出力データは、出力パイプの id 特殊化と一致する名前のファイルに自動的に書き込まれます。

4.8.4.4.

設計のコンパイルとエミュレート

FPGA のカーネル設計をコンパイルおよびエミュレートするには、次の手順を実行します。

83インテル® oneAPI プログラミング・ガイド

1.

プログラムのホスト部分を変更して、sycl::ext::intel::fpga_emulator_selector_v デバイスセレ
クターを宣言します。FPGA デバイスカーネルをエンキューするためデバイスキューをインスタンス化する際に、この セレクターを使用します。詳細については、「FPGA のデバイスセレクター」を参照してください。

2.

icpx コマンドに -fintelfpga オプションを追加して設計をコンパイルし、実行可能ファイルを生成します。

3.

生成された実行可能ファイルを実行します。
‐

Windows*:a.

次のコマンドを実行し、エミュレートされるデバイス数を定義します。

$ set CL_CONFIG_CPU_EMULATE_DEVICES=<デバイス数>b.

実行可能ファイルを実行します。

c.

次のコマンドを実行して設定を解除します。

$ set CL_CONFIG_CPU_EMULATE_DEVICES=‐Linux*: 次のコマンドを実行します。

$ env CL_CONFIG_CPU_EMULATE_DEVICES=<デバイス数> <実行可能ファイル>

このコマンドは、エミュレーターが提供する必要がある同一エミュレーター・デバイス数を指定します。

ヒント: 単一のエミュレーター・デバイスを使用する場合、この設定は必要ありません。
CL_CONFIG_CPU_EMULATE_DEVICES 環境変数を設定します。

84インテル® oneAPI プログラミング・ガイド

注:
エミュレーターは、インテル® oneAPI DPC++/C++ コンパイラーに含まれる GCC 7.4.0 でビルド
され ま す。 その ため、 エ ミュ レ ート さ れる FPGA デバ イ スの 実行 フ ァイル を実 行 す るには 、
libstdc++.so が GCC 7.4.0 のものである必要があります。つまり、LD_LIBRARY_PATH 環境変数は、正しいバージョンの libstdc++.so の場所を示す必要があります。
正しいバージョンの libstdc++.so が見つからない場合、clGetPlatformIDs 関数の呼び出しは FPGA エミュレーター・プラットフォームのロードに失敗し、CL_PLATFORM_NOT_FOUND_KHR(エラーコード -1001) を返します。検出される libstdc++.so のバージョンによっては、
clGetPlatformIDs 関数の呼び出しが成功することもありますが、後で clCreateContext 関
数を呼び出すと CL_DEVICE_NOT_AVAILABLE (エラーコード -2) で失敗する可能性があります。
LD_LIBRARY_PATH 環境変数が互換性のある libstdc++.so を指していない場合、次のコマンドでホストプログラムを起動します。
env LD_LIBRARY_PATH=<path to compatible libstdc++.so>:$LD_LIBRARY_PATH<executable> [executable arguments]

4.8.4.5.

エミュレーターの制限

OpenCL* ソフトウェア向けインテル® FPGA エミュレーター・プラットフォームには、次の制限があります。


同時実行
カーネルの同時実行のモデル化には制限があります。実行中、エミュレーターは相互に作用するワーク項目を並列実行することを保証していません。したがって、同期バリアなしにグローバルメモリーにアクセスする異なるカー
ネルなど、一部の同時実行において一貫性のないエミュレーション結果が生成される可能性があります。



同一アドレス空間の実行
エミュレーターは、同一アドレス空間でホストのランタイムとカーネルを実行します。特定のポインターや配列を使用すると、カーネルプログラムが実行に失敗することも成功することもあります。一例として、外部割り当てのメモ
リー・インデックスの作成やランダムポインターへの書き込みがあります。
Valgrind などのメモリーリーク検出ツールを使用して、プログラムの動作を解析できます。カーネルが境界外への書き込みが原因でホストが致命的なエラーを生じる可能性がありますが、その逆も考えられます。



条件付きパイプ操作
パイプ動作のエミュレーションには制限があります。特に、カーネルがループ反復ごとにパイプ操作を呼び出さない条件付きパイプ操作がそれに該当します。この場合、エミュレーターはハードウェアとは異なる順番でパイプ操作を実行する可能性があります。

85インテル® oneAPI プログラミング・ガイド

GCC のバージョン

エミュレーターのホストプログラムは、GCC 7.4.0 以降の libstdc++.so を搭載する Linux* システム上で実行する必要があります。GCC 7.4.0 以降をシステムにインストールするか、LD_LIBRARY_PATH 環境変数に互換性のある libstdc++.so を識別できるようにパスを設定します。

4.8.4.6.

ハードウェアとエミュレーターの結果の不一致

カーネルをエミュレートすると、カーネルがハードウェア向けにコンパイルされたカーネルとは異なる結果を生成することがあります。ハードウェア向けにコンパイルする前に、カーネルをシミュレーションすることでデバッグを行うことができます。

警告: このような結果の不一致は、多くの場合 OpenCL* 向けインテル® FPGA エミュレーション・プラットフォームがハードウェアの計算を正確にモデル化できない、またはプログラムが未定義の動作に依存する場合に発生します。

エミュレーターとハードウェアの結果が異なる原因は、次のものがあります。


カーネルコードに ivdep 属性 (英語) が使用されています。ivdep 属性によって依存関係が無視されると、エミュレーターはカーネルをモデル化できません。ハードウェア向けの完全なコンパイルでは、誤った結果になります。

カーネルコード初期化されていないデータに依存しています。初期化されていないデータには、初期化されていない変数、初期化されていないまたは部分的に初期されたグローバルバッファー、ローカル配列、プライベート
配列などがあります。



カーネルコードの動作は、浮動小数点演算の結果によって異なります。エミュレーターは CPU の浮動小数点
演算ハードウェアを使用しますが、ハードウェア実行では FPGA コアとして実装された浮動小数点コアを使用します。

注: SYCL* 標準では、浮動小数点演算の最下位ビットが複数のプラットフォーム間で異なっていても、それぞれのプラットフォームでは正しいと見なされるように定義されています。



カーネルコードの動作は、それぞれのカーネルのパイプアクセスの順序によって異なります。チャネル動作のエ
ミュレーションには制限があり、カーネルがループ反復ごとにチャネル操作を呼び出さない条件付き操作がそれに該当します。この場合、エミュレーターはハードウェアとは異なる順番でチャネル操作を行う可能性があります。例えば、パイプで接続された 2 つのカーネルに、それぞれ read() 関数または write() 関数を含む
ループがあり、ループ反復ごとに一定にそれらが実行されない場合 (if 文の条件判定があるなど)、エミュレー
ターはハードウェアとは異なる方法で read() または write() 呼び出しをインターリーブすることがあります。

カーネルまたはホストコードが範囲外のグローバル・メモリー・バッファーにアクセスしています。

86インテル® oneAPI プログラミング・ガイド

注:
初期化されていないメモリーの読み書きの動作は、プラットフォームに依存します。カーネル内のすべてのアドレス空間を使用する場合、グローバル・メモリー・バッファーのサイズを確認してください。
エミュレートされたカーネルでは、Valgrind などのメモリーリーク検出ツールを使用してメモリーに関連する問題を解析できます。ツールが警告を示さない場合でも問題がないわけではありません。これは、ツールが問題を検出できなかっただけであり、カーネルまたはホストコードを手動で検証することを推奨します。


カーネルコードがローカル変数の範囲外をアクセスします。このような例として、範囲外のローカル配列にアクセスしたり、スコープから出た場合の変数アクセスが挙げられます。

注: 通常、境界外の変数へのアクセスは、ソフトウェア・スタック上でアクセスされる変数に隣接する
関連のない変数に影響を与えるため、ソフトウェアにおける用語ではこれはスタック破壊の問題と呼ばれます。エミュレート・カーネルは通常 CPU 関数として実装されるため、スタックが破損する可能性があります。ハードウェアをターゲットとするケースではスタックは存在しません。そのため、スタック破損の問題は、異なる形で明らかになります。スタック破損が疑われる場合、Valgrind のようなメモリー・リーク・アナライザーを使用しますが、スタック関連の問題は特定することが困難です。
インテルでは、スタック関連の問題をデバッグする際に、カーネルコードを手動で検証することを推奨しています。



カーネルコードが、シフトされるデータ型よりも大きなシフトを行っています。例えば、64 ビット整数を 65 ビット・シフトしています。SYCL* 仕様のバージョン 1.0 では、このようなシフトの動作は未定義とされています。



エミュレーション向けにカーネルをコンパイルする場合、デフォルトのパイプ深度はハードウェア向けにコンパイルされる際のデフォルトのパイプライン深度とは異なります。このパイプラインの深度の違いにより、カーネ
ル・エミュレーションでは問題なく動作していても、ハードウェアの実行でハングする可能性があります。パイプ
深度の違いを修正する方法は、「パイプの深度をエミュレート」を参照してください。



エミュレーターとハードウェアでは、cout stream 関数で出力される順番が異なる場合があります。これは、ハードウェアでは cout stream のデータがグローバル・メモリー・バッファーに格納され、カーネルの実行が完了した、またはバッファーが一杯になったときにのみバッファーからスラッシュされるのに対し、エミュレー
ターでは cout stream 関数は x86 の stdout を使用するためです。



タイプのアップキャストにより、アライメントされていないロード/ストアを実行すると、ハードウェアとエミュ
レーターでは異なる結果が生じることがあります。このタイプのロード/ストアは、C99 仕様では未定義です。



エミュレーションとシミュレーション/ハードウェア間で異なる未知の動作をデバッグする場合、エミュレーショ
ンに -Weverything 診断コマンドオプションを使用することを推奨します。-Weverything オプションを使用すると、すべての警告がオンになり、利用可能な診断を利用して、設計で誤って使用している可能性のある危険なコーディング・パターンを明らかにできるようになります。

87インテル® oneAPI プログラミング・ガイド

4.8.4.7.

エミュレーターの既知の問題

既知の問題にはエミュレーターの動作に影響するものがあります。これらの問題を確認して、エミュレーターで発生する可能性がある問題を回避してください。
4.8.4.7.1.

タスクシーケンス関数の結果の不一致

最初の get() 呼び出しの前に複数の async() 呼び出しがあるタスクシーケンス関数では、get() 呼び出しが結果を返す順番が async() 呼び出しの順番とは異なる場合があります。この問題を解決するには、シミュレーターを使用して、このシナリオで正しい結果が返されることを確認します。
4.8.4.7.2.

コンパイラーの診断

一部のコンパイラーの診断は、エミュレーターにはまだ実装されていません。
4.8.4.7.3.

カーネル起動時の CL_OUT_OF_RESOURCES エラー

エミュレーターがデフォルトでサポートするよりも多くのプライベート・メモリーやローカルメモリーをカーネルが使用
すると、このエラーが発生する可能性があります。
「エ ミュレーター 環境変数 」 の説明に従 って、 C L _C O N FI G _CP U _ FO R CE_ P R IV A TE_ M E M_ S IZE ま たは
C L_CONFIG_C PU _ FOR C E _L O CAL _ M EM _ SIZ E 環境 変数に 大きな値 を設 定して くだ さい。

注: Windows* では、FPGA エミュレーターがメモリー不足で警告なく失敗することがあります。
この問題を回避するには、エラーをキャッチするため try-catch 構文を使用してカーネルコードを記述します。

4.8.4.7.4.

FPGA ランタイムとエミュレーション・バイナリーの互換性

oneAPI FPGA ランタイムは、以前のバージョンの oneAPI で構築されたエミュレーション・バイナリーをサポートしていません。現在の oneAPI のリリースでエミュレーション・バイナリーを再コンパイルする必要があります。
4.8.4.7.5.

libstdc++.so と GCC のバージョン

エミュレーターは、インテル® oneAPI DPC++/C++ コンパイラーに含まれる GCC 7.4.0 でビルドされています。そのため、エミュレートされる FPGA デバイスの実行ファイルを実行するには、libstdc++.so が GCC 7.4.0 のものである
必要があります。つまり、LD_LIBRARY_PATH 環境変数は、正しいバージョンの libstdc++.so の場所を示す必要があります。
正しいバージョンの libstdc++.so が見つからない場合、clGetPlatformIDs 関数の呼び出しは FPGA エミュ
レーター・プラットフォームのロードに失敗し、CL_PLATFORM_NOT_FOUND_KHR (エラーコード -1001) を返します。
検出される libstdc++.so のバージョンによっては、clGetPlatformIDs 関数の呼び出しが成功することもありますが、後で clCreateContext 関数を呼び出すと CL_DEVICE_NOT_AVAILABLE (エラーコード -2) で失敗する可能性があります。
88インテル® oneAPI プログラミング・ガイド

LD_LIBRARY_PATH 環境変数が互換性のある libstdc++.so を指していない場合、次のコマンドでホストプロ
グラムを起動します。
$ env LD_LIBRARY_PATH=<互換性のある libstdc++.so へのパス>:$LD_LIBRARY_PATH <実行可能ファイル> [引数]4.8.5 シミュレーションによるカーネルの評価
Questa*-インテル® FPGA Edition Software のシミュレーターと Questa*-インテル® FPGA Starter Edition Software
は、カーネル機能の評価を支援します。
シミュレーター手順では、ホストで実行されるシミュレーション・バイナリーを生成します。コードのハードウェア部分はRTL シミュレーターで評価され、ホスト部分はプロセッサーでネイティブ実行されます。この機能を使用すると、カーネルをハードウェア向けにコンパイルして FPGA デバイスでその都度実行しなくても、カーネルの機能をシミュレートして設計を繰り返すことができます。

注: シミュレーターのパフォーマンスは、ハードウェアと比較すると非常に低速であるため、小規模なデータセットを使用してテストすることを推奨します。

カーネルの動的なパフォーマンスおよび、エミュレーションやレポートツールが提供する情報よりも、カーネルの機能に関する正確な情報を必要とする場合、シミュレーターを使用します。
シミュレーターはサイクル精度とビット精度が高く、生成されたハードウェアと同じネットリストを備えており、デバッグ向けに完全な波形を提供できます。Siemens* EDA (旧 Mentor Graphics) Questa* ソフトウェアで波形を表示します。


シミュレーションの要件

Questa*-インテル® FPGA Edition Software のインストール



シミュレーション環境の設定



シミュレーション用にカーネルをコンパイル

カーネルをシミュレート

シミュレーションした 波形を表示



シミュレーターの問題のトラブルシューティング

4.8.5.1.

シミュレーションの要件

FPGA シミュレーション手順を実行するには、事前に次のソフトウェアをダウンロードする必要があります。
インテル® Quartus® Prime 開発ソフトウェア・プロ・エディション: このパッケージをインテル® FPGA ソフト
ウェア・ダウンロード・ センター (英語) からダウンロードします。

89インテル® oneAPI プログラミング・ガイド

互換シミュレーション・ソフトウェア (Questa*-インテル® FPGA Edition および Questa*-インテル® FPGA
Starter Edition): インテル® FPGA ソフトウェア・ダウンロード・センター (英語) で入手できます。

注:
Questa*-インテル® FPGA Edition にはライセンスが必要です (Questa*-インテル® FPGA Starter
Edition のライセンスは無料です)。詳細については、「インテル® FPGA ソフトウェアのインストールとライセンス」 (英語) をご覧ください。
独自ライセンスの Siemens* EDA ModelSim* SE または Siemens* EDA Questa Advanced
Simulator (英語) ソフトウェアを使用することもできます。インテル® Quartus® Prime 開発ソフト
ウェア・プロ・エディションがサポートするすべての ModelSim* および Questa* ソフトウェアのバージョンについては、『インテル® Quartus® Prime 開発ソフトウェア・プロ・エディション: <バー
ジョン番号> ソフトウェアとデバイスのサポート・リリースノート』の「EDA インターフェイスの情報」(英語) を参照してください。
Linux* では、Questa*-インテル® FPGA Edition Software および Questa*-インテル® FPGA
Starter Edition Software を利用するため、Red Hat* 開発ツール (英語) をインストールする必要があります。

4.8.5.2.

Questa*-インテル® FPGA Edition Software のインストール

インストール手順については、『Questa*-インテル® FPGA Edition Software クイック・スタート: インテル® Quartus®
Prime 開発ソフトウェア・プロ・エディション』 (英語)を参照してください。

注: oneAPI 環境で QUARTUS_ROOTDIR_OVERRIDE 環境変数を調べると、インテル® Quartus®
Prime 開発ソフトウェアのインストール場所を確認できます。

4.8.5.3.

シミュレーション環境の設定

インテル® Quartus® Prime 開発ソフトウェアおよび Questa* シミュレーション・ソフトウェアのバイナリーを含むディレクトリーを PATH 環境変数に追加する必要があります。

注: このトピックで紹介するコマンドは、シミュレーションの前提条件に示すよう FPGA アドオン
パッケージとともに Questa* シミュレーション・ソフトウェアがインストールされている必要があります。ほかの場所に Questa* シミュレーション・ソフトウェアをインストールした場合、PATH 環
境変数を選択してください。

90インテル® oneAPI プログラミング・ガイド

4.8.5.3.1.

インテル® Quartus® Prime 開発ソフトウェア (シミュレーションのみ)

FPGA シミュレーション手順の場合にのみ、インテル® Quartus® Prime 開発ソフトウェアのバイナリーを明示的に追加する必要があります。ディレクトリーを、以下のコマンドで PATH 環境変数に追加します。
Linux*:$ export PATH=$PATH:<quartus_installdir>/quartus/binWindows*:$ set "PATH=%PATH%;<quartus_installdir>\quartus\bin64"

さらに、ロードする ICD (インストール可能なクライアント・ドライバー) を指定するため、OCL_ICD_FILENAMES 環
境変数を設定する必要があります。
$ set "OCL_ICD_FILENAMES=%OCL_ICD_FILENAMES%;alteracl_icd.dll"

4.8.5.3.2.

Questa*-インテル® FPGA Starter Edition Software

無償の Questa*-インテル® FPGA Starter Edition Software では、次のコマンドを実行します。
Linux*:$ export PATH=$PATH:<quartus_installdir>/questa_fse/binWindows*:$ set "PATH=%PATH%;<quartus_installdir>\questa_fse\win64"

4.8.5.3.3.

Questa*-インテル® FPGA Edition Software

ライセンスを取得した Questa*-インテル® FPGA Edition Software では、次のコマンドを実行します。
Linux*:$ export PATH=$PATH:<quartus_installdir>/questa_fe/binWindows*:$ set "PATH=%PATH%;<quartus_installdir>\questa_fe\win64"

これでシミュレーション用のソフトウェアをコンパイルできます。

91インテル® oneAPI プログラミング・ガイド

4.8.5.4.

シミュレーション用にカーネルをコンパイル

シミュレーションを行う前に、インテル® Quartus® Prime 開発ソフトウェア・プロ・エディションがシステムにインストー
ルされていることを確認してください。詳細については、『インテル® oneAPI ツールキット・インストール・ガイド』 (英語)と「インテル® FPGA 開発手順」 (英語) のウェブページを参照してください。
シミュレーション用にカーネルをコンパイルするには、icpx コマンドに -Xssimulation オプションを追加します。
$ icpx -fsycl -fintelfpga -Xssimulation fpga_compile.cpp

また、シミュレーション中に波形の収集を有効にするには、icpx コマンドに -Xsghdl[=<depth>] オプションを追加します。オプションの <depth> にはログに記録される階層のレベル数を指定します。<denpth> 属性が省略されると、階層レベルは 1 になります。すべての波形をログに記録するには、深度 0 (-Xsghdl=0) を指定します。
Windows* システムでシミュレーションを実行する場合、Microsoft* リンカーと追加のライブラリーが必要です。以下の設定を確認します。


環境変数 PATH には、Microsoft* Visual Studio* の LINK.EXE コマンドへのパスを含める必要があります。



環境変数 LIB には、Microsoft* コンパイル・ライブラリーへのパスを含めます。コンパイル・ライブラリーは、
Microsoft* Visual Studio* で提供されます。

4.8.5.5.

カーネルをシミュレート

シミュレーション・ランタイムは、自動的に検出または指定された board_spec.xml/ipinterfaces.xml ファイルに基づいてシミュレーション・デバイスを作成します。2 つのシミュレーション環境変数を適用して、.xml ファイルの検索方法を制御できます。
CL_CONTEXT_MPSIM_DEVICE_INTELFPGA: この環境変数を 1 に設定すると、シミュレーション・ランタイムは、次のルールに基づいて使用する board_spec.xml/ipinterfaces.xml ファイルを自動的に検索します。

‐

現在の作業ディレクトリーに .prj ディレクトリーが 1 つだけ存在する場合、コンパイラーはそのディレク
トリーにある board_spec.xml/ipinterfaces.xml ファイルを使用します。

‐

現在の作業ディレクトリーに複数の .prj ディレクトリーが存在する場合、コンパイラーは現在の実行ファ
イル名と一致する名前を持つディレクトリーにある board_spec.xml/ipinterfaces.xml ファイルを使用します。名前を比較する際に、コンパイラーは拡張子 (Linux＊ では .exe、.bin、および .elf、Windows* では .exe) を削除します。

注: 自動検索に失敗すると、ランタイムは CL_DEVICE_NOT_AVAILABLE エラーを返します。

INTELFPGA_SIM_DEVICE_SPEC_DIR: 自動検索に失敗、または自動検出された .xml ファイルが正しくない
場合、この環境変数を使用してターゲットの .xml ファイルを含むディレクトリーへのパスを指定します。この環
境変数は、CL_CONTEXT_MPSIM_DEVICE_INTELFPGA 変数の値を 1 に強制するため、シミュレーションでデザインを実行する際に両方の変数を指定する必要はありません。

92

インテル® oneAPI プログラミング・ガイド

シミュレーション・フローでシミュレーション中に生成された波形を表示するには、Siemens* EDA Questa* Simulator
または ModelSim SE のいずれかがインストールされ、利用可能である必要があります。
シミュレーターを介して SYCL* ライブラリーを実行するには、以下を行います。
1.

CL_CONTEXT_MPSIM_DEVICE_INTELFPGA または INTELFPGA_SIM_DEVICE_SPEC_DIR 環境変数を設定して、シミュレーション・デバイスを有効にします。
Linux*:$ export CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1$ export INTELFPGA_SIM_DEVICE_SPEC_DIR=<prj dir>Windows*:$ set CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1$ set INTELFPGA_SIM_DEVICE_SPEC_DIR=<prj dir>

注: 環境変数が設定されている場合、シミュレーション・デバイスのみが使用可能であり、物理ボー
ドへのアクセスは無効になります。環境変数の設定を解除するには、次のコマンドを実行します。
Linux*:$ unset CL_CONTEXT_MPSIM_DEVICE_INTELFPGA$ unset INTELFPGA_SIM_DEVICE_SPEC_DIR
Windows*:$ set CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=$ set INTELFPGA_SIM_DEVICE_SPEC_DIR=

ホストプログラムがシミュレーターを検出できない場合、CL_CONTEXT_COMPILER_MODE_INTELFPGA=3 を設定する必要があります。
2.

ホストプログラムを実行します。Linux* システムでは、GDB または Eclipse* を使用してホストをデバッグできます。必要に応じて、カーネルコードのシミュレーション波形を調査して作成されたハードウェアの機能を確認できます。
-Xsghdl オプションを使用してコンパイルしたプログラムを実行すると、波形ファイル (vsim.wlf) が生成されます。このファイルは、ホストコードを実行する際に Questa*-インテル® FPGA Edition Software で表示できます。
vsim.wlf ファイルは、ホストプログラムを実行したディレクトリーに書き込まれます。

93インテル® oneAPI プログラミング・ガイド

4.8.5.6.

シミュレーションした波形を表示

デフォルトでは、インテル® oneAPI DPC++/C++ コンパイラーは、信号をログに記録するとシミュレーション速度が低下し、波形ファイルが膨大なサイズになる可能性があるため、信号を記録しないようシミュレーターに指示します。ただし、デバッグ用途で波形を記録することはできます。
シミュレーターの信号記録を有効にするには、次のように -Xsghdl オプションを指定して icpx を起動します。
$ icpx -fsycl -fintelfpga -Xssimulation -Xsghdl[=<depth>] <input files> -o <project_name><depth> 属性を指定して、ログに記録される階層レベル数を制御します。<depth> に 1 を指定すると、最上位レベルの信号のみが記録されます。<depth> 属性を省略すると、深さレベル 1 がデフォルトとして設定されます。すべての波形をログに記録するには、深度 0 (-Xsghdl=0) を指定します。
シミュレーション実行後、次のようなスクリプトを呼び出して生成された波形ファイルを表示できます。
Linux*:$ bash <project_directory>/view_waveforms.shWindows*:$ <project_directory>\view_waveforms.cmd

注: <project_directory> は通常 <project_name>.prj ですが、<project_name> は
icpx コマンドの -o 引数で指定される名前になります。

4.8.5.7.

シミュレーターの問題のトラブルシューティング

この節では、シミュレーションを実行する際に発生する可能性があるシミュレーターの問題に対するトラブルシュー
ティングについて説明します。
4.8.5.7.1.

Windows* におけるコンパイルまたは実行の失敗

Windows* では、パスが非常に長いディレクトリーから実行すると、コンパイルまたは実行時にシミュレーションが失敗することがあります。-o コンパイルオプションを使用して、コンパイル結果を短いパスの場所に出力します。
4.8.5.7.2.

socket=-11 エラーが transcript.log に記録される

次のエラーメッセージが表示される場合、Questa*-インテル® FPGA Edition Software や ModelSim* SE など複数のシミュレーターのリソースが混在している可能性を示します。
Message: "src/hls_cosim_ipc_socket.cpp:202: void IPCSocketMaster::connect():
Assertion `sockfd != -1 && "IPCSocketMaster::connect() call to accept() failed"' failed."94インテル® oneAPI プログラミング・ガイド

シミュレーターのリソースが競合する例として、 ModelSim* SE を使用してデバイスをコンパイルし、Questa*インテル® FPGA Starter エディションでホストプログラムを実行する場合が上げられます。
4.8.5.7.3.

Questa*-インテル® FPGA Starter Edition Software との互換性

Questa*-インテル® FPGA Starter Edition Software には、設計サイズの大きさに制限があり、大規模な設計をシミュレートすることができません。Questa*-インテル® FPGA Starter Edition Software を使用してシミュレーションを起動
すると、次のエラーメッセージが表示される場合があります。
Error: The simulator's process ended unexpectedly.

代わりに、Questa*-インテル® FPGA Edition、または ModelSim* SE ソフトウェアを使用して設計をシミュレートします。
4.8.5.7.4.

環境変数が未設定

環境変数 CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1 の設定を忘れると、エラーメッセージが表示されることがあります。
Linux*
terminate called after throwing an instance of 'sycl::_V1::runtime_error'
what(): No device of requested type available. Please check https://www.intel.com/
content/www/us/en/developer/articles/system-requirements/intel-oneapi-dpcpp-systemrequirements.html -1 (PI_ERROR_DEVICE_NOT_FOUND)
Aborted (core dumped)

Windows*
シミュレーターがクラッシュし、デバッガーに次のメッセージが表示されることがあります。
Unhandled exception at 0x00007FFD92DFDE4E (ucrtbase.dll) in <your exe>.exe: Fatal program
exit requested.

この問題を解決するには、環境変数 CL_CONTEXT_MPSIM_DEVICE_INTELFPGA=1 を設定します。

95インテル® oneAPI プログラミング・ガイド

4.8.6 FPGA デバイスセレクター
ホストコードで正しい SYCL* デバイスセレクターを使用して、FPGA エミュレーター、シミュレーター、またはハード
ウェアのターゲットを選択します。シミュレーションにも FPGA ハードウェア・デバイス・セレクターを使用できます。次のコード例は、セレクターを使用してコンパイル時にターゲットデバイスを指定する方法を示しています。
1.

// FPGA デバイスセレクターは、パイプや fpga_reg などすべての2.

// FPGA 拡張機能とともにユーティリティー・ヘッダーで定義されます#include <sycl/ext/intel/fpga_extensions.hpp>

3.
4.
5.

int main() {// 次のいずれかを選択:

6.

// - FPGA エミュレーター・デバイス (CPU で FPGA をエミュレーション)

7.

// - FPGA シミュレーター

8. // - FPGA デバイス (実際の FPGA)
9. #if FPGA_SIMULATOR
10.
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
11. #elif FPGA_HARDWARE
12.
auto selector = sycl::ext::intel::fpga_selector_v;
13.

14. #else // #if FPGA_EMULATOR
15.
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
16. #endif
17.
queue q(selector);
18. ...
19. }

注:




FPGA エミュレーターと FPGA は異なるターゲットデバイスです。define プリプロセッサーを使用して、エミュレーターと FPGA セレクターを選択することを推奨します。これにより、ソースを変更することなくコマンドラインで -D オプションを使用してターゲットを切り替えることができます。例えば上記のコード例では、icpx に -DFPGA_EMULATOR オプションを渡すことで FPGA エミュレーター向けにコンパイルできます。
FPGA は事前コンパイル (AOT) のみをサポートしているため、FPGA をターゲットにする場合、
動的セレクター (default_selector など) は使用できません。

警告: FPGA エミュレーターや FPGA ハードウェアをターゲットにする場合、適切なコンパイルオプ
ションを指定し、ホストコードで正しいデバイスセレクターを使用する必要があります。そうでない
場合、ランタイムエラーが発生する可能性があります。FPGA 向けの SYCL* コードのコンパイルに関する詳細は、「インテル® oneAPI サンブルブラウザー」 (英語) の「fpga_compile」 (英語) チュー
トリアルを参照してください。

96インテル® oneAPI プログラミング・ガイド

4.8.7 FPGA IP オーサリング手順
FPGA IP オーサリング手順では、コンパイラーは SYCL* コードを使用して、インテル® Quartus® Prime 開発ソフトウェ
アのカスタム・プロジェクトに統合できる IP コンポーネントを生成します。特定のアクセラレーション・プラットフォームの代わりに、サポートされているインテル® FPGA デバイスファミリーまたは製品番号をコンパイルのターゲットにしてIP オーサリング手順を使用します。
この手順を使用することで、システムに展開できるさまざまなターゲット上の IP コンポーネント向けに SYCL* コードをコンパイルして、IP 開発をスピードアップします。
IP コンポーネント開発手順を開始する詳細については、『インテル® oneAPI ツールキットとインテル® Quartus®
Prime 開発ソフトウェアの導入ガイド』 (英語)を参照してください。
IP コンポーネントを作成する一般的な設計手順は、次のステージで構成されます。
1.

IP コンポーネントとテストバッチを作成します。
IP コンポーネント・コードとテストバッチ・コードを含む完全な SYCL* アプリケーションを作成します。SYCL* デバ
イスコード (カーネルコー) は IP コンポーネントに対応し、SYCL* ホストコードはエミュレーションおよびシミュ
レーション手順のテストベンチとして機能します。
SYCL* コードの記述方法については、「SYCL* を使用した C++ のデータ並列処理」を参照してください。
また、SYCL* での IP コンポーネントの記述に関する追加情報については、「SYCL* で IP コンポーネントをコーディング」を参照してください。

2.

エミュレーションによって、IP コンポーネントのアルゴリズムとテストベンチの機能を検証します。
設計を x86-64 実行可能ファイルにコンパイルして実行することで、IP コンポーネントの機能を検証し、IP アルゴ
リズムを改良します。詳細については、「IP コンポーネントのエミュレートとデバッグ」を参照してください。

3.

コンポーネントの FPGA パフォーマンスを最適化し改良します。
-Xstarget=<FPGA デバイスファミリー> または -Xstarget=<FPGA 製品番号> コンパイラー・オプションと、-Xssimulation または -Xshardware オプションを使用して、FPGA デバイスファミリーや製品番号をター
ゲットとする設計をコンパイルし、コンポーネントの FPGA パフォーマンスを最適化します。FPGA 最適化サポートを確認して、コンポーネントの最適化可能な場所を確認します。このステップでは、コンポーネントの RTL コードを生成します。
詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「設計を解析」 (英語) を参照してください。
FPGA 最適化レポートを参照して初期の最適化を完了した後、シミュレーションを行ってコンポーネントをさらに改良できるか確認します。
詳細については、「シミュレーションによる IP コンポーネントの評価」を参照してください。

97インテル® oneAPI プログラミング・ガイド

4.

FPGA ハードウェア・イメージをコンパイルして、コンポーネントを合成します。
-Xstarget=<FPGA デバイスファミリー> または -Xstarget=<FPGA 製品番号> コンパイラー・オプションを使用すると、インテル® oneAPI DPC++/C++ コンパイラーはコンポーネントの入力と出力を仮想ピンに関連付けて設計をコンパイルし、コンポーネントのエリアと fMAX を正確に見積もります。ボード・サポート・パッケージなしでコンパイルされるため、生成された出力はボードに展開できません。
詳細については、「インテル® Quartus® Prime 開発ソフトウェアによるコンポーネントの IP 合成」を参照してくだ
さい。
コンポーネントを合成すると、FPGA のエリア利用率や fMAX などの正確な結果品質 (QoR) メトリックが生成されます。

5.

インテル® Quartus® Prime 開発ソフトウェアまたは Platform Designer を使用して、IP をシステムに統合します。
詳細については、「IP をシステムに統合」を参照してください。

期待されたコンポーネントのパフォーマンスが達成されたら、インテル® Quartus® Prime 開発ソフトウェアを使用してコンポーネントを合成します。合成では、設計のエリアとパフォーマンス (fMAX) の正確な見積もりが生成されます。ただし、設計ではインテル® Quartus® Prime 開発ソフトウェアのレポートでタイミングが完全にクローズされることは期待されていません。
生成されるプロジェクトは、設計に最適な配置を実現するするため 1000MHz のクロック速度をターゲットにしており、
インテル® Quartus® Prime 開発ソフトウェアのログでタイミングクローズの警告が表示される場合があります。FPGA
最適化レポートに示される fMAX 値は、コンポーネントがタイミングを完全にクローズできる最大クロックレートを想定しています。
インテル® Quartus® Prime 開発ソフトウェアのコンパイルが完了すると、FPGA 最適化レポートのサマリーセクションに、コンポーネントのエリアとパフォーマンス・データが表示されます。
これらの推定値はシミュレーションのみを目的として IP コンポーネントをコンパイルした場合に生成される推定値よりも正確です。
通常、インテル® Quartus® Prime 開発ソフトウェアによるコンパイル時間は、IP コンポーネントのサイズと複雑さに応じて、数分から数時間かかります。
コンポーネント IP を合成して QoR (結果品質) データを生成するには、コンポーネントの合成後にインテル® Quartus®
Prime 開 発 ソ フ ト ウ ェ ア に よ る コ ン パ イ ル 手 順 を 自 動 実 行 す る よ う コ ン パ イ ラ ー に 指 示 し ま す 。
-Xstarget=<FPGA デバイスファミリー> または -Xstarget=<FPGA 製品番号> オプションを icpx コマンドに追加します。
$ icpx -fsycl -fintelfpga -Xshardware -Xstarget=<FPGA デバイスファミリー>...

$ icpx -fsycl -fintelfpga -Xshardware -Xstarget=<FPGA 製品番号>...

98

インテル® oneAPI プログラミング・ガイド

次のフローチャートは、一般的な IP コンポーネントのオーサリング手順ステージの概要を示しています。
インテル® FPGA 製品の IP 合成手順の概要

4.8.7.1.

SYCL* で IP コンポーネントをコーディングSYCL* で IP コンポーネントを記述する場合、追加の要件と用法を考慮してください。


RTL インターフェイスのカスタマイズ



推奨されるコーディング・スタイル

‐

ラムダのコーディング・スタイルの例‐

ファンクターのコーディング・スタイルの例

メモリー・マップド・ホスト・インターフェイス‐

メモリー・マップド・ホスト・インターフェイスのアドレス



ホストパイプエージェント IP コンポーネント・カーネル‐



レジスター・マップ・ファイルの例

ストリーミング IP コンポーネント・カーネル‐

ストリーミング IP コンポーネント・カーネルの制限



カーネル引数インターフェイス

パイプライン化カーネル

安定した引数99

インテル® oneAPI プログラミング・ガイド

IP コンポーネントのリセット動作

printf コマンド

4.8.7.1.1.

RTL インターフェイスのカスタマイズ

コンパイラーは、RTL コンポーネントをより大きなシステムに統合するコンポーネントのインターフェイスを生成します。
IP コンポーネントには、コンポーネントの呼び出しインターフェイスとデータ・インターフェイスの 2 つの基本インターフェイス・タイプがあります。
IP はデフォルトで、入力を処理するコントロール・ステータス・レジスター (CSR) のエージェント・インターフェイスによって生成されます。「ストリーミング IP コンポーネント・カーネル」では、ストリーミング・インターフェイスの使用法を示します。
データは、カーネル引数、ホストパイプ、またはメモリー経由 (アクセサーや USM) を介して、カーネルに渡されます。
ラムダ式 (単にラムダとも呼ばれます) のキャプチャー・リストで値として項目を渡すか、アクセサーまたは統合共有メモ
リー (USM) ポインターを介して IP 上に Avalon メモリー・マップド・ホスト・インターフェイスを作成できます。
IP は、アクセサー、USM ポインター、またはパイプを介してのみ出力を生成できます。CSR インターフェイスは、インテル® oneAPI DCP++/C++ コンパイラーが生成した IP コンポーネントからの出力をキャプチャーできません。
4.8.7.1.2.

推奨されるコーディング・スタイル

IP を作成するには、推奨される次の一般的なコーディング・スタイルを使用します。


ラムダのコーディング・スタイルの例: ラムダのコーディング・スタイルは、ほとんどのシステムでの SYCL* プログ
ラミングで使用されます。



ファンクターのコーディング・スタイルの例: ファンクターのコーディング・スタイルでは、IP コンポーネント (カーネル) のコードをホストコードから分離して記述できます。

ラムダのコーディング・スタイルの例
1. #include <iostream>
2. #include <vector>
3.
4. // oneAPI ヘッダー
5. #include <sycl/sycl.hpp>
6. #include <sycl/ext/intel/fpga_extensions.hpp>
7.
8. using namespace sycl;
9.
10. // グローバルスコープでカーネル名を前方宣言します
11. // これは、最適化レポートでの名前のマングリングを減らす FPGA におけるベスト・プラクティスです
12. class VectorAddID;
13.
14. void VectorAdd(const int *vec_a_in, const int *vec_b_in, int *vec_c_out,
15.
int len) {16.
for (int idx = 0; idx < len; idx++) {17.
int a_val = vec_a_in[idx];

100インテル® oneAPI プログラミング・ガイド

18.
int b_val = vec_b_in[idx];
19.
int sum = a_val + b_val;
20.
vec_c_out[idx] = sum;
21.
}
22. }
23.
24. constexpr int kVectSize = 256;25.
26. int main() {27.
bool passed = true;
28.
try {
29.
// コンパイル時のマクロを使用して次のいずれかを選択します30.

// - FPGA エミュレーター・デバイス (CPU で FPGA をエミュレーション)

31.

// - FPGA デバイス (実際の FPGA)

32.
// - シミュレーター・デバイス
33. #if FPGA_SIMULATOR
34.
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
35. #elif FPGA_HARDWARE
36.
auto selector = sycl::ext::intel::fpga_selector_v;
37. #else // #if FPGA_EMULATOR
38.
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
39. #endif
40.
41.
// デバイスキューを作成
42.
sycl::queue q(selector);
43.
44.
// デバイスが USM ホスト割り当てをサポートするか確認
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.

auto device = q.get_device();
std::cout << "Running on device: "<< device.get_info<sycl::info::device::name>().c_str()<< std::endl;
if (!device.has(sycl::aspect::usm_host_allocations)) {std::terminate();}// 配列を宣言して、カーネルがそれらを認識できるよう共有メモリーに割り当て
int *vec_a = malloc_shared<int>(kVectSize, q);
int *vec_b = malloc_shared<int>(kVectSize, q);
int *vec_c = malloc_shared<int>(kVectSize, q);for (int i = 0; i < kVectSize; i++) {vec_a[i] = i;vec_b[i] = (kVectSize - i);}
std::cout << "add two vectors of size " << kVectSize << std::endl;
q.single_task<VectorAddID>([=]() {VectorAdd(vec_a, vec_b, vec_c, kVectSize);}).wait();// vec_c が正しいか確認
for (int i = 0; i < kVectSize; i++) {int expected = vec_a[i] + vec_b[i];if (vec_c[i] != expected) {std::cout << "idx=" << i << ": result " << vec_c[i] << ", expected ("<< expected << ") A=" << vec_a[i] << " + B=" << vec_b[i]101インテル® oneAPI プログラミング・ガイド

76.
<< std::endl;
77.
passed = false;
78.
}
79.
}
80.
81.
std::cout << (passed ? "PASSED" : "FAILED") << std::endl;
82.
83.
free(vec_a, q);84.
free(vec_b, q);85.
free(vec_c, q);86.
} catch (sycl::exception const &e) {87.
// ホストコードで例外をキャッチ
88.
std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n";89.
90.
// ランタイムが FPGA ハードウェアを検出できなかった可能性があります!
91.
if (e.code().value() == CL_DEVICE_NOT_FOUND) {92.
std::cerr << "If you are targeting an FPGA, please ensure that your "93.
"system has a correctly configured FPGA board.\n";94.
std::cerr << "Run sys_check in the oneAPI root directory to verify.\n";95.
std::cerr << "If you are targeting the FPGA emulator, compile with "96.
"-DFPGA_EMULATOR.\n";
97.
}
98.
std::terminate();99.
}
100. return passed ? EXIT_SUCCESS : EXIT_FAILURE;
101. }

ファンクターのコーディング・スタイルの例
このスタイルでは、すべてのインターフェイスを 1 つの場所で指定し、SYCL* ホストプログラムから IP コンポーネントを呼び出すことができます。
1.
2.
3.
4.
5.
6.
7.

#include <iostream>// oneAPI ヘッダー
#include <sycl/ext/intel/fpga_extensions.hpp>#include <sycl/sycl.hpp>// グローバルスコープでカーネル名を前方宣言します

8. // これは、最適化レポートでの名前のマングリングを減らす FPGA におけるベスト・プラクティスです9.
10. class VectorAddID;
11.
12. struct VectorAdd {13.
int *const vec_a_in;14.
int *const vec_b_in;15.
int *const vec_c_out;
16.
int len;17.
18.
void operator()() const {19.
for (int idx = 0; idx < len; idx++) {20.
int a_val = vec_a_in[idx];
21.
int b_val = vec_b_in[idx];
22.
int sum = a_val + b_val;
23.
vec_c_out[idx] = sum;
24.
}
25.
}
26. };102

インテル® oneAPI プログラミング・ガイド

27.
28. constexpr int kVectSize = 256;29.
30. int main() {31.
bool passed = true;
32.
try {
33.
// コンパイル時のマクロを使用して次のいずれかを選択します34.

// - FPGA エミュレーター・デバイス (CPU で FPGA をエミュレーション)

35.

// - FPGA デバイス (実際の FPGA)36.
// - シミュレーター・デバイス
37. #if FPGA_SIMULATOR
38.
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
39. #elif FPGA_HARDWARE
40.
auto selector = sycl::ext::intel::fpga_selector_v;
41. #else // #if FPGA_EMULATOR
42.
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
43. #endif
44.
45.
// デバイスキューを作成
46.
sycl::queue q(selector);
47.
48.
// デバイスが USM ホスト割り当てをサポートすることを確認
49.
auto device = q.get_device();50.
51.
std::cout << "Running on device: "52.
<< device.get_info<sycl::info::device::name>().c_str()
53.
<< std::endl;
54.
55.
if (!device.has(sycl::aspect::usm_host_allocations)) {56.
std::terminate();
57.
}
58.
59.
// 配列を宣言して、カーネルがそれらを認識できるよう共有メモリーに割り当て
60.
int *vec_a = sycl::malloc_shared<int>(kVectSize, q);61.
int *vec_b = sycl::malloc_shared<int>(kVectSize, q);62.
int *vec_c = sycl::malloc_shared<int>(kVectSize, q);63.
for (int i = 0; i < kVectSize; i++) {64.
vec_a[i] = i;65.
vec_b[i] = (kVectSize - i);
66.
}
67.
68.
std::cout << "add two vectors of size " << kVectSize << std::endl;
69.
70.
q.single_task<VectorAddID>(VectorAdd{vec_a, vec_b, vec_c, kVectSize})71.
.wait();
72.
73.
// vec_c が正しいか確認
74.
for (int i = 0; i < kVectSize; i++) {75.
int expected = vec_a[i] + vec_b[i];76.
if (vec_c[i] != expected) {77.
std::cout << "idx=" << i << ": result " << vec_c[i] << ", expected ("78.
<< expected << ") A=" << vec_a[i] << " + B=" << vec_b[i]79.
<< std::endl;
80.
passed = false;
81.
}
82.
}
83.
84.
std::cout << (passed ? "PASSED" : "FAILED") << std::endl;
85.

103

インテル® oneAPI プログラミング・ガイド

86.
sycl::free(vec_a, q);87.
sycl::free(vec_b, q);88.
sycl::free(vec_c, q);89.
} catch (sycl::exception const &e) {90.
// ホストコードで例外をキャッチ
91.
std::cerr << "Caught a SYCL host exception:\n" << e.what() << "\n";92.
93.
// ランタイムが FPGA ハードウェアを検出できなかった可能性があります!
94.
if (e.code().value() == CL_DEVICE_NOT_FOUND) {95.
std::cerr << "If you are targeting an FPGA, please ensure that your "96.
"system has a correctly configured FPGA board.\n";97.
std::cerr << "Run sys_check in the oneAPI root directory to verify.\n";98.
std::cerr << "If you are targeting the FPGA emulator, compile with "99.
"-DFPGA_EMULATOR.\n";
100.
}
101.
std::terminate();102. }
103. return passed ? EXIT_SUCCESS : EXIT_FAILURE;
104. }

4.8.7.1.3.

メモリー・マップド・ホスト・インターフェイス

各外部メモリー・インターフェイスは、「バッファーロケーター」識別子で一意に識別されます。バッファーロケーターは、
mmhost マクロでアノテーションされた引数またはアクセサーに適用できます。指定されたバッファーロケーターを持
つカーネル引数は、アノテーション付きポインター引数とも呼ばれます。アノテーションを持たないポインター引数には、
次のいずれかを指定できます。


バッファーロケーターを持たないアクセサー引数

mmhost マクロでアノテーションされないカーネル引数

カーネルのアノテーション付きポインター引数内の固有のバッファー位置ごとに、コンパイラーは 1 つのメモリー・マッ
プド・ホスト・インターフェイスを想定します。カーネルにアノテーションなしのポインター引数がある場合、追加でグローバル・メモリー・マップド・インターフェイス(バッファー位置 0 を使用) が想定されます。
次の方法でバッファーの位置をカーネル引数に関連付けます。


統合共有メモリーを使用したメモリー・マップド・インターフェイス
統合共有メモリー (USM) を使用すると、メモリー・マップド・ホスト・インターフェイスをカスタマイズできます。
ほとんどの場合、コンパイラーは仮想アドレス空間を自動的にエンコードしますが、場合によっては、自身でエンコードする必要があるかもしれません。詳細については、「統合共有メモリーを使用したメモリー・マップド・ホスト・
インターフェイス統合共有メモリーを使用したメモリー・マップド・ホスト・インターフェイス」を参照してください。

アクセサーを使用したメモリー・マップド・インターフェイス
アクセサーを使用すると、ランタイムと BSP はホストとデバイス間のメモリーのコピーを管理できます。
カーネルアクセサー引数は、アクセサー引数ごとに 4 つの引数になります。

104インテル® oneAPI プログラミング・ガイド

メモリー・マップド・ホスト・インターフェイスのアドレス
メモリーマップド (MM) ホスト・インターフェイスでは、ワード・アドレスではなくバイト・アドレスを使用します。
例えば、ポインターを 4 バイト幅のデータタイプで逆参照する場合、MM ホスト・インターフェイスによって発行されるア
ドレスは、ポインターベースのアドレス + 配列インデックス × 4 になります。
mm_a のベースアドレスが 0x0000 であるとすると、次の例では 0x0006 x 4 = 0x0018 であるため、インターフェ
イス上で 0x0018 になります。
uint32_t value = mm_a[0x0006];

mm_a のベースアドレスが 0x1000 である場合、結果アドレスは 0x0018 ではなく 0x1018 になります。
また、1 バイト幅のデータタイプへのポインターを逆参照する場合、MM ホスト・インターフェイスによって発行されるア
ドレスは、ポインターのベースアドレス + 配列インデックス × 1 になります。
mm_a のベースアドレスが 0x0000 であるとすると、次の例では 0x0006 x 1 = 0x0006 であるため、インターフェ
イス上で 0x0006 になります。
uint8_t value = mm_a[0x0006];

mm_a のベースアドレスが 0x1000 である場合、結果アドレスは 0x0006 ではなく 0x1006 になります。
統合共有メモリーを使用したメモリー・マップド・ホスト・インターフェイス
コンポーネントがデータへのアクセスに統合共有メモリー (USM) ホストポインターを使用する場合、IP コンポーネントのメモリー・マップド・インターフェイスをカスタマイズできます。
インターフェイスをカスタマイズするには、ファンクターを使用してコンポーネントを指定し、ここで説明するマクロを使用します。マクロを使用するには、ヘッダーファイル sycl/ext/intel/prototype/interfaces.hpp をインクルードします。
カーネルをコンパイルする際に次のオプションを指定して、ヘッダーファイルがインクルード・パスにあることを確認します。
Linux*: -I/$INTELFPGAOCLSDKROOT/includeWindows*: -I %INTELFPGAOCLSDKROOT%\include

メモリー・マップド・ホスト・インターフェイスでは、テストベンチ (またはホストプログラム) は、バッファーの位置をプロパティーとして指定する sycl::malloc_shared または sycl::malloc_host 関数を使用して USM メモリーを割り当てる必要があります。ファンクターのカーネル引数のマクロを使用してバッファーの位置を指定する場合、関数にはバッファーの位置をプロパティー引数として渡す必要があります。

105

インテル® oneAPI プログラミング・ガイド

IP コンポーネント・カーネルでは、sycl::malloc_device API を使用した USM デバイスメモリー割り当てはサポートされません。
次のマクロは、メモリー・マップド・ホスト・インターフェイスを作成します。
mmhost() マクロregister_map_mmhost() マクロconduit_mmhost() マクロ

mmhost() マクロ(またはマクロが指定されていない)

ポインターカーネル引数にマクロが指定されていない場合、または mmhost()
マクロが指定される場合、引数はカーネル呼び出しインターフェイスと同じスタイルを継承します。
デフォルトのカーネル呼び出しインターフェイスは、レジスター・マップ・ベースです。
この引数をオーバーライドするには、 register_map_mmhost() マクロと
conduit_mmhost() マクロを使用します。

カーネル呼び出しインターフェイスを制御するマクロについては、「エージェント IP コンポーネント・カーネル」および「ストリーミング IP コンポーネント・カーネル」で説明されています。
mmhost(1, // buffer location
28, // address width
64, // data width
0, // latency. Setting 0 specifies variable latencyinterface
0, // read_write_mode, 0: Read/Write, 1: Read-only, 2:
Write only
1, // maxburst
0, // align1// waitrequest, 0: false, 1: true
) int *x;106インテル® oneAPI プログラミング・ガイド

register_map_mmhost()
マクロ

ベースポインターは、レジスターマップを介して渡されます。
register_map_mmhost() マクロを使用すると、アドレスを格納するため 64
ビット・レジスターが使用される場合でも、カーネルが消費するのはアドレス幅のビット数です。
register_map_mmhost(
1, // buffer location
28, // address width
64, // data width
0, // latency. Setting 0 specifies variable latencyinterface
0, // read_write_mode, 0: Read/Write, 1: Read-only, 2:
Write only
1, // maxburst
0, // align1// waitrequest, 0: false, 1: true
) int *x;

conduit_mmhost() マクロ

ベースポインターは、コンジット・インターフェイスを介して渡されます。
conduit_mmhost() マクロを使用すると、ポインター引数用に作成されたポートサイズが、指定されたアドレス幅に調整されます。
conduit_mmhost(
1, // buffer location
28, // address width
64, // data width
0, // latency. Setting 0 specifies variable latencyinterface
0, // read_write_mode, 0: Read/Write, 1: Read-only, 2:
Write only
1, // maxburst
0, // align 1 // waitrequest, 0: false, 1: true
) int *x;

次のカーネルには、レジスター・マップ・ベースの引数インターフェイスがあります。
// 生成される IP を定義する構造体
struct MyIPComponent1{// 構造体メンバーはカーネル引数
int* a; // no macro specified// operator()() はデバイス/IP コードを定義// operator()()にマクロが指定されていません
void operator()() const { ... }};struct MyIPComponent2{
mmhost(...) int* a;...
// operator()() にカーネル呼び出しマクロが指定されていません
void operator()() const { ... }};107

インテル® oneAPI プログラミング・ガイド

次のパラメーターをカスタマイズできます。
mmhost マクロのプロパティー
プロパティー
バッファー位置説明
外部メモリー用の一意の識別子を指定するリテラル。コン
パイル時定数でなければなりません。

デフォルト
なし

有効な値
説明を参照

アドレス幅

(すべてのカーネルで) 設計全体の個別のバッファー位置の合計数は 64 未満でなければなりません。
メモリー・マップド・アドレス・バスの幅 (ビット単位)。

41

1 – 41 の整数値

データ幅

アドレス幅が有効な最大値を超えると、コンパイル時にコンパイルエラーが発生します。
メモリー・マップド・データ・パスの幅 (ビット単位)。

641

８ 、 16 、 32 、 64 、 128 、
256、512、1024
正の整数値

0

0 (リード/ライト)

カーネルに定義されたアノテーションなしのポインター引
数がない限り、バッファーの位置は 0 から始まる連続した整数である必要があります。
アノテーションなしのポインター引数がある場合、バッファーの位置は 1 から始まる必要があります。これは、アノテーションなしのポインター引数があると、推測される外部メモリー用に 0 が予約されるためです。

レイテンシー

リード/ライトモード

コンポーネントの読み取りコマンドが終了してから、外部メモリーが有効なデータを返すまでの保証されたレイテン
シー。
（DRAM にアクセスするなど） レイテンシーが可変である
場合、または共有エージェント・インターフェイスをにアクセスする場合は、0 に設定します。
インターフェイスのポート方向。

1 (リードのみ)
2 (ライトのみ)
Maxburst

読み取りまたは書き込みトランザクションに関連付けられるデータ転送の最大数。
この値は burstcount 信号の幅を制御します。固定レイ
テンシー・インターフェイスでは、この値を 1 に設定する必要があります。
詳 細 に つ い て は 、 『 Avalon® イ ン タ ー フ ェ イ ス 仕 様 』 の「Avalon® メモリー・マップド・インターフェイス信号の役
割」 (英語) でバースト信号と burstcount 信号の役割に関する情報を参照してください。

108

1

1 -1024

インテル® oneAPI プログラミング・ガイド

プロパティー
アライメント説明
引数ポインターアドレスのアライメント (バイト単位)。

デフォルト
1

有効な値

0

0: 待機要求信号を無効にします0 、 1 、 2 、 4 、 8 、 16 、
32、64、128

重要: ポインターの値は、指定されたアライメントで割り切れる
ことを確実にする必要があります。アライメントにそわないと機能障害が発生する可能性があります。

アライメントを設定することで、コンパイラーは複数のロード/ストアを組み合わせてワイドなロード/ストアを発行できるハードウェアに最適化できます。例えば、4 つの 32
ビット整数を処理する場合、データ幅を 128 ビットに設定
して、アライメントを 16 バイトにします。これにより、クロックサイクルごとに最大 16 バイトの連続した (または 4
つの 32 ビット整数) を結合されたメモリーワードとしてロードまたはストアできます。

待機要求

アライメントに 0 を指定のは、1 を指定する場合を同じです。
エージェントが読み取りまたは書き込み要求に応答できない場合にアサートされる待機要求 (waitrequest) 信
号を制御するディレクティブ。
待 機 要 求 (waitrequest) 信 号 の 詳 細 に つ い て は 、『Avalon® インターフェイス仕様』の「Avalon® メモリー・
マップド・インターフェイス信号の役割」 (英語)を参照してください。

1: 待機要求信号を有効にします重 要 : 固 定レ イ テン シー ・ イン
ターフェイス (Latency=0) を指定する場合、待機要求を 1 にしないでください。

次の例は、2 つのカスタマイズされたメモリー・マップド・ホスト・インターフェイスを作成します。ホストプログラムは、2つの USM 共有ポインターを割り当てて、それらが示すメモリーをそれぞれ値 5 と 6 で初期化します。これらのポイン
ターをカーネル引数として実行するためカーネルをキューに投入し、戻り値をチェックしてから USM に割り当てられたメモリーを解放します。

109

インテル® oneAPI プログラミング・ガイド

1. #include <sycl/sycl.hpp>
2. #include <sycl/ext/intel/fpga_extensions.hpp>
3. #include <sycl/ext/intel/prototype/interfaces.hpp>
4.
5. using namespace sycl;
6. using ext::intel::experimental::property::usm::buffer_location;
7.
8. constexpr int BL1 = 0;
9. constexpr int BL2 = 1;
10.
11. struct MyIP {12.
register_map_mmhost(13.
BL1, // buffer location
14.
28, // address width
15.
64, // data width
16.
0,// latency. Setting 0 specifies variable latency interface
17.
0,// read_write_mode, 0: Read/Write, 1: Read-only, 2: Write-only18.
1,// maxburst 0, // align 1 // waitrequest, 0: false, 1: true19. ) int *x;
20. register_map_mmhost(21.
BL2, // buffer location
22.
28, // address width23.
64, // data width24.
0,// latency. Setting 0 specifies variable latency interface
25.
0,// read_write_mode, 0: Read/Write, 1: Read-only, 2: Write-only26.
1,// maxburst
27.
0,// align 1 // waitrequest, 0: false, 1: true28. ) int *y;29.
30. register_map_interface
31.
void operator()() const {32.
*x = 5;33.
*y = 6;34.
}35. };
36.
37. void Test() {38. #if FPGA_SIMULATOR
39.
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
40. #elif FPGA_HARDWARE
41.
auto selector = sycl::ext::intel::fpga_selector_v;
42. #else // #if FPGA_EMULATOR
43.
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
44. #endif
45.
46.
sycl::queue q(selector);47.
int *HostA = malloc_shared(1, q, property_list{buffer_location(BL1)});48.
*HostA = 0;49.
int *HostB = malloc_shared(1, q, property_list{buffer_location(BL2)});50.
*HostB = 0;51.
52.
q.single_task(MyIP{HostA, HostB}).wait();53.
54.
if (*HostA == 6 && *HostB == 5) std::cout << "PASSED\n";else std::cout << "FAILED\n";55.
56.
sycl::free(HostA, q);57.
sycl::free(HostB, q); }58.
59. int main() {60.
Test();
61.
62.
if (*HostA == 6 && *HostB == 5) std::cout << "PASSED\n";110

インテル® oneAPI プログラミング・ガイド

63.
64.
65.
66. }

else std::cout << "FAILED\n";return 0;

統合共有メモリー仮想アドレス空間を使用したメモリー・マップド・インターフェイス
コンパイラーは、仮想アドレス空間に対する特定の情報を、次に示すように 64 ビット・ポインター・アドレスの上位ビットにエンコードします。
ポインターアドレスのビット範囲の説明
ビット範囲
40:0
63:41

説明
メモリーシステム内のアドレス指定に使用されます
バッファー位置から取得される仮想アドレス空間の情報を格納します

コンパイラーはポインターがどのバッファー位置に対応するか判断できないことがあり、その場合生成される RTL 内にロジックを作成し、実行時にポインターの最上位ビットをチェックしてバッファー位置を検出し、メモリー・トランザク
ションを正しい外部メモリー・インターフェイスにルーティングします。
ほとんどの場合、バッファーの位置情報は自身でエンコードする必要はありません。特殊な状況については、「手動でバッファー位置をエンコードする例」で説明します。
コンパイラーは、ソースファイル内のポインターカーネル引数で指定されたバッファー位置から、この情報を埋め込むロジックを自動的に生成します。
手動でバッファー位置をエンコードする例
カーネルに、バッファーの位置が指定されいるカーネル引数 (アノテーション付きの引数) と、バッファーの位置が指定されていない引数 (アノテーションなしの引数) が少なくとも 1 つある場合、すべてのアノテーションなしのカーネル引数の先頭ビットにバッファー位置を埋め込む必要があります。
次の例について考えてみます。
// This struct defines the IP that will be generated
struct MyIPComponent{// struct members are kernel arguments
int* a; // no buffer location specified
mmhost(1, ...) int *b; // buffer location 1
mmhost(2, ...) int *c; // buffer location 2mmhost(3, ...) int *d; // buffer location 3// operator()() defines the device/IP code
void operator()() const {*a *= 2;*b *= 2;*c *= 2;*d *= 2;}};111

インテル® oneAPI プログラミング・ガイド

この例では、コンパイラーが外部メモリーポインター a がどこを指すか判断できないため、ポインターの最上位ビットをチェックするロジックを作成し、実行時にいずれのバッファー位置にアクセスするか決定します。したがって、引数 a でこの最上位ビットを設定する必要があります (ほかのカーネル引数では設定しません)。
この場合、アノテーションのないポインター引数にコンジット・インターフェイスがある場合、ポートの幅は 64 ビットになります。また、インターフェイスがレジスター・マップ・ベースの場合も、64 ビットすべてがカーネルに渡されます。

重要:
シミュレーション例外
oneAPI シミュレーション・フローでカーネルをシミュレーションする場合、ポインター・ビットに情報を埋め込むホストコードを記述する必要はありません。バッファーの位置はすべて、ホストコードにポインターを割り当てるランタイム・スタックで処理されます。
コンパイラーがポインター引数を指すバッファー位置を推測できる場合 (例えば、mm_host インターフェイスが 1 つだ
けの場合)、コンパイラーはバッファー位置を自動的に埋め込みます。カーネルにアノテーション付きのカーネル引数とアノテーションなしのカーネル引数が混在する場合にのみ、手動でバッファー位置を指定する必要があります。
コンパイラーは、アノテーションなしのポインターカーネル引数がある場合は常に、1 つのグローバルメモリー (バッファー位置 0) を想定します。次のコードでは、アノテーションなしのポインター引数のみがあるため、コンパイラーはグローバルメモリーを 1 つ想定し、ポインターカーネル引数の上位ビットに正しい情報を埋め込みます。
// This struct defines the IP that will be generated
struct MyIPComponent{// struct members are kernel arguments
int* a; // no buffer location specified
int* b; // no buffer location specified// no other annotated kernel argument is present// operator()() defines the device/IP code
void operator()() const {*a = ...
*b = ...
}};

仮想アドレス空間情報の決定
コンパイラーが埋め込むことができないポインターカーネル引数の先頭ビットに仮想アドレス空間情報を埋め込むには、HTML レポートから埋め込む情報を取得します。
1.

まだ HTML レポートを生成していない場合、カーネルをコンパイルして HTML レポートを取得します。

2.

HTML レポートを開きます。

3.

[View] > [System Viewer] に移動します。

4.

左のペインで、[System] を拡張して [Global memory] を開きます。
[Global memory] の下に、カーネルのすべての外部メモリーのエントリーが表示されます。

112

インテル® oneAPI プログラミング・ガイド

5.

メモリーをクリックすると、そのメモリーが [System Viewer] ペインに表示されます。

6.

[System Viewer] ペインで、メモリーを示すボックスを見つけて、そのノードをクリックします。
このノードは、そのグローバルメモリーの「インターフェイス」であることを示します。

7.

[Details] ペインで、メモリーの開始アドレスを見つけます。
ポインターでこのバッファー位置にアクセスする場合、アノテーションなしのポインター引数の上位ビットは、この開始アドレスの上位と一致する必要があります。

次の図は、バッファー位置 1 をアドレス指定するために必要な廃止アドレスの最上位ビットを決定する例を示しています。

4.8.7.1.4.

アクセサーを使用したメモリー・マップド・ホスト・インターフェイス

次の例は、SYCL* の buffer_location プロパティーを使用して複数のメモリーマップド (mm_host) インターフェイ
スを作成する方法を示します。
1.
2.
3.
4.
5.
6.
7.

#include <sycl/sycl.hpp>#include <iostream>#include <sycl/ext/intel/fpga_extensions.hpp>#include <vector>
using namespace sycl;

113インテル® oneAPI プログラミング・ガイド

8.

// グローバルスコープでカーネル名を前方宣言します

9. // これは、最適化レポートでの名前のマングリングを減らす FPGA におけるベスト・プラクティスです。
10.
11. class SimpleVAdd;
12.
13.
14. // ファンクターのメンバーは、IP への入力と出力として機能します
15. // operator()() 関数内のコードでは、IP を記述します
16. template <class AccA, class AccB, class AccC>
17. class SimpleVAddKernel {18.
AccA A;
19.
AccB B;
20.
AccC C;21.
int count;
22.
23.
public:24.
SimpleVAddKernel(AccA A_in, AccB B_in, AccC C_out, int count_in)25.
: A(A_in),26.
B(B_in),27.
C(C_out),
28.
count(count_in) {}29.
30.
void operator()() const {31.
// clang フォーマット有効
32.
for (int i = 0; i < count; i++) {33.
C[i] = A[i] + B[i];
34.
}
35.
}
36. };
37.
38. constexpr int VECT_SIZE = 4;39.
40. int main() {41.
42.
#if FPGA_SIMULATOR
43.
auto selector = sycl::ext::intel::fpga_simulator_selector_v;
44.
#elif FPGA_HARDWARE
45.
auto selector = sycl::ext::intel::fpga_selector_v;
46.
#else // #if FPGA_EMULATOR
47.
auto selector = sycl::ext::intel::fpga_emulator_selector_v;
48.
#endif49.
50.
queue q(my_selector);
51.
52.
int count = VECT_SIZE; // value で配列サイズを渡す
53.
54.
// 配列を宣言して埋める
55.
std::vector<int> VA;
56.
std::vector<int> VB;
57.
std::vector<int> VC(count);58.
for (int i = 0; i < count; i++) {59.
VA.push_back(i);60.
VB.push_back(count - i);
61.
}
62.
63.
std::cout << "add two vectors of size " << count << std::endl;
64.
65.
buffer bufferA{VA};66.
buffer bufferB{VB};67.
buffer bufferC{VC};114

インテル® oneAPI プログラミング・ガイド

68.
69.
70.
71.
72.
73.
74.

q.submit([&](handler &h) {accessor accessorA{bufferA, h, read_only};
accessor accessorB{bufferB, h, read_only};
accessor accessorC{bufferC, h, read_write, no_init};h.single_task<SimpleVAdd>(SimpleVAddKernel<decltype(accessorA),
decltype(accessorB), decltype(accessorC)>{accessorA, accessorB, accessorC, count});
75.
});
76.
77.
// VC が正しいか確認
78.
bool passed = true;79.
for (int i = 0; i < count; i++) {80.
int expected = VA[i] + VB[i];81.
std::cout << "idx=" << i << ": result " << VC[i] << ", expected ("82.
<< expected << ") VA=" << VA[i] << " + VB=" << VB[i] << std::endl;
83.
if (VC[i] != expected) {84.
passed = false;
85.
}
86.
}
87.
88.
std::cout << (passed ? "PASSED" : "FAILED") << std::endl;
89.
return passed ? EXIT_SUCCESS : EXIT_FAILURE;
90. }4.8.7.1.5.

ホストパイプ

パイプは設計の要素間のリンクを提供する先入れ先出し (FIFO) 構造のバッファーです。ホストとデバイスを接続するパ
イプは、ホストパイプと呼ばれます。ホストパイプは、設計に次のインクルード文を挿入することでサポートが有効になります。
#include <sycl/ext/intel/experimental/pipes.hpp>

ホストパイプの宣言と使い方の詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』 (英語) を参照してください。

重要: マルチアーキテクチャー・バイナリー・カーネル (「ファットバイナリー」または、「フルスタック」と呼ばれることもあります) の場合、設計内の非 CSR ホストパイプの数は BSP によって制限されます。

4.8.7.1.6.

エージェント IP コンポーネント・カーネルSYCL* カーネルは、カーネルを制御し、カーネルの引数を IP コンポーネントに渡すインターフェイスを生成します。
デフォルトでは、インテル® oneAPI DPC++/C++ コンパイラーは、カーネルを制御してカーネル引数を渡すため Avalon
エージェント・インターフェイスを生成します。コンパイラーは、エージェントのメモリーマップ内でさまざまなレジスター
アドレスと提供するヘッダーファイルも生成します。register_map_offsets.hpp という最上位のヘッダーがデバイ
スイメージごとに生成され、SYCL* デバイスイメージとインターフェイスを持つ場合にインクルードできます。

115

インテル® oneAPI プログラミング・ガイド.prj ディレクトリー内のカーネルごとに追加ヘッダーが生成されます。register_map_offsets.hpp ヘッダー
ファイルは、これらのファイルをインクルードしますが、各カーネルのアドレスとオフセットが含まれます。
レジスター・マップ・ファイルの例/* Status register contains all the control bits to control kernel execution *//*****************************************************************************//* Memory Map Summary*//*****************************************************************************//*
Address | Access | Register| Argument| Description--------|--------|--------------|---------------------|------------------------------0x0| R/W| reg0[63:0]| Status[63:0]| *Read/Write the status bits|||
| that are described below--------|--------|--------------|---------------------|------------------------------0x8| R/W| reg1[31:0]| Start[31:0]| *Write 1 to initiate a|||| kernel start--------|--------|--------------|-----------------------|------------------------------0x30| R| reg6[31:0]| FinishCounter[31:0] | *Read to get number of kernel|| reg6[63:32] | FinishCounter[31:0] | finishes, note that this|||| register will clear on read--------|--------|--------------|---------------------|------------------------------0x80| R/W| reg16[63:0] | arg_input_a[63:0]|--------|--------|--------------|---------------------|------------------------------0x88| R/W| reg17[63:0] | arg_input_b[63:0]|--------|--------|--------------|---------------------|------------------------------0x90| R/W| reg18[63:0] | arg_input_c[63:0]|--------|--------|--------------|---------------------|------------------------------0x98| R/W| reg19[31:0] | arg_n[31:0]|*//**************************************************************************//* Register Address Macros*//**************************************************************************//* Status Register Bit Offsets (Bits) *//* Note: Bits In Status Registers Are Marked As Read-Only or Read-Write
Please Do Not Write To Read-Only Bits */#define KERNEL_REGISTER_MAP_DONE_OFFSET (1) // Read-only#define KERNEL_REGISTER_MAP_BUSY_OFFSET (2) // Read-only#define KERNEL_REGISTER_MAP_STALLED_OFFSET (3) // Read-only#define KERNEL_REGISTER_MAP_UNSTALL_OFFSET (4) // Read-write#define KERNEL_REGISTER_MAP_VALID_IN_OFFSET (14) // Read-only#define KERNEL_REGISTER_MAP_STARTED_OFFSET (15) // Read-only/* Status Register Bit Masks (Bits) */#define KERNEL_REGISTER_MAP_DONE_MASK (0x2)#define KERNEL_REGISTER_MAP_BUSY_MASK (0x4)#define KERNEL_REGISTER_MAP_STALLED_MASK (0x8)#define KERNEL_REGISTER_MAP_UNSTALL_MASK (0x10)#define KERNEL_REGISTER_MAP_VALID_IN_MASK (0x4000)#define KERNEL_REGISTER_MAP_STARTED_MASK (0x8000)

カーネルのデフォルトオプションはエージェントカーネルですが、関数をエージェントカーネルとしてマークする
register_map_interface マクロがあります。以下に例を示します。

116

インテル® oneAPI プログラミング・ガイド

1.
2.

#include <sycl/ext/intel/prototype/interfaces.hpp>
using namespace sycl;

3.
4.
5.
6.

struct MyIP {int *input_a, *input_b, *input_c;
int n;

7.
8.
register_map_interface void operator()() const {9.
for (int i = 0; i < n; i++) {10.
input_c[i] = input_a[i] + input_b[i];
11.
}
12.
}
13. };

4.8.7.1.7.

ストリーミング IP コンポーネント・カーネル

Avalon ストリーミング (ST) インターフェイスのように、インテル® oneAPI DPC++/C++ コンパイラーが ready-valid
ハンドシェイクで IP コンポーネント呼び出しインターフェイスを実装することもできます。
コンパイラーで ready-valid ハンドシェイクを使用して IP コンポーネント呼び出しインターフェイスを実装するには、
次のようにします。
1.

ファンクターとして IP カーネルを実装します。

2.

次のヘッダーファイルをインクルードします。

sycl/ext/intel/prototype/interfaces.hpp

3.

4.

次のオプションをコンパイルコマンド (icpx -fsycl) に追加します。
‐

Linux*: I/$INTELFPGAOCLSDKROOT/include‐

Windows*: /I %INTELFPGAOCLSDKROOT%\include

streaming_interface マクロをファンクター operator() に追加します。

次のコードはストリーミング・インターフェイスの実装例です。
1. #include <sycl/ext/intel/prototype/interfaces.hpp>
2. using namespace sycl;
3.
4. struct MyIP {5.
int *input_a, *input_b, *input_c;6.
int n;
7.
MyIP(int *a, int *b, int *c, int N_)
8.
: input_a(a), input_b(b), input_c(c), n(N_) {}9.
streaming_interface void operator()() const {10.
for (int i = 0; i < n; i++) {11.
input_c[i] = input_a[i] + input_b[i];
12.
}
13.
}
14. };

117

インテル® oneAPI プログラミング・ガイド

IP コンポーネント・カーネルは ready-valid ハンドシェイクで呼び出されます。サンプルコードをコンパイルすると、
start 信号、done 信号、ready_in 信号、そして ready_out 信号はコンジットとして生成されます。また、3 つのポ
インターのベースアドレスと N 値のコンジットも生成されます。
ストリーミングのハンドシェイクは Avalon ストリーミング (ST) に従います。IP カーネルは、start と ready_out 信号がアサートされるクロックサイクルで引数を消費します。IP コンポーネントのカーネル呼び出しは、done およびready_in 信号がアサートされるクロックサイクルで終了します。
ストリーミング IP コンポーネント・カーネルの制限
ストリーミング IP コンポーネント・カーネルを使用する場合、次のアクションはサポートされません。


ストリーミング・カーネルを SYCL* NDRange カーネルとして使用。



ストリーミング・カーネルのプロファイル。



ストリーミング・カーネルでのエージェントカーネル引数の使用。

4.8.7.1.8.

カーネル・エージェント・インターフェイス

デフォルトで、カーネル引数は start 信号と同じタイプのインターフェイスを介して (IP コンポーネントの CSR またはReady/Valid ハンドシェイクで同期された入力によって) コンポーネントを渡します。この動作はオーバーライドすることもできます。例えば、コンジットを介して渡される引数でレジスターマップ呼び出しインターフェイスを選択したり、レジスターマップ引数を使用してストリーミング呼び出しインターフェイスを選択することができます。
次の例は、CSR に呼び出しインターフェイスを配置して、コンジット・インターフェイスを介してカーネル引数を渡す方法
を示します。
#include <sycl/ext/intel/prototype/interfaces.hpp>
using namespace sycl;
struct MyIP {conduit int *input_a, *input_b, *input_c;
conduit int n;register_map_interface void operator()() const {for (int i = 0; i < n; i++) {input_c[i] = input_a[i] + input_b[i];
}
}
};

118

インテル® oneAPI プログラミング・ガイド

また、次のコードは、ハンドシェイク呼び出しインターフェイスを使用してカーネルを構成し、CSR を介してカーネル引数を渡す方法を示します。
#include <sycl/ext/intel/prototype/interfaces.hpp>
using namespace sycl;
struct MyIP {register_map int *input_a, *input_b, *input_c;
register_map int n;streaming_interface void operator()() const {for (int i = 0; i < n; i++) {input_c[i] = input_a[i] + input_b[i];}}};4.8.7.1.9.

パイプライン化カーネル

デフォルトでは、SYCL* タスクのカーネルはパイプライン化されません。そのため、カーネルを再度呼び出す前に、前の呼び出しが完了するのを待機する必要があります。
ただし、次の例に示すように、streaming_pipelined_interface マクロを使用してストリーミング・カーネルをパイプライン化できます。
struct MyIP {conduit int *input;
MyIP(int *inp_a_) : input(inp_a_) {}streaming_pipelined_interface void operator()() const {int temp = *input;*input = something_complicated(temp);}};/* シミュレーションでカーネルのパイプライン処理を行うには、wait() 関数を呼び出す前に、関数の複数インスタンスをキューに投入する必要があります。次のコード例は、
パイプライン化されたカーネルの実装方法を示します。
*/
for (int i = 0; i < kN; i++) {q.single_task(MyIP{&input_array[i]});}q.wait();4.8.7.1.10.

安定した引数

デフォルトでは、インテル® oneAPI DPC++/C++ コンパイラーは、カーネルの実行中にカーネル引数の値が変更されることを想定しています。
パイプライン化されたカーネルでは、カーネルとカーネル引数が次の条件を満たす場合、安定したカーネル引数としてマークできます。


カーネル引数はカーネル呼び出しの実行中に変更されない。



このカーネルの別の呼び出しが実行中である場合、カーネルが別のカーネル引数で起動されない。

119

インテル® oneAPI プログラミング・ガイド

stable_conduit 属性を指定して、ストリーミング (コンジット) カーネル引数が安定していることを宣言します。安定
したカーネル引数の値を変更すると、動作は未定義となります。
ストリーミング (コンジット) カーネル引数を安定していると宣言することで、カーネル設計の FPGA 領域を節約できることがあります。
カーネル実行中にすべてのカーネル引数が変更されることがない場合、 icpx コマンドで -Xsno-hardwarekernel-invocation-queue オプションを指定できます。
-Xsno-hardware-kernel-invocation-queue オプションを指定してコンパイルされたカーネルの引数を変更
すると、動作は未定義になります。
4.8.7.1.11.

IP コンポーネントのリセット動作

IP コンポーネントの場合、リセットのアサートは非同期にできますが、リセットのアサート解除は同期する必要があります。
リセットのアサートおよびアサート解除の動作は、リセット同期を使用して非同期リセットの入力から生成できます。
IP をシステムに統合する際に、Platform Designer を使用してコンポーネントにリセット同期を追加します。
IP をシステムに統合する方法は、「IP をシステムに統合」を参照してください。
リセット同期の追加例については、「Platform Designer のサンプル設計例」 (英語) を参照してください。
非同期信号転送の準安定性による同期エラーを最小限に抑えるため、シンクロナイザーが実装されています。準安定性の詳細については、『インテル® Quartus® Prime 開発ソフトウェア・プロ・エディション・ユーザーガイド: 設計の推奨事項』 (英語) にある「インテル® Quartus® Prime 開発ソフトウェアで準安定性を管理」 (英語) を参照してください。
リセットがアサートされると、コンポーネントは busy 信号を high に、done 信号を low に維持します。リセットがアサートされた後、コンポーネントは次の呼び出しを受け入れる準備ができるまで busy 信号を high に保ちます。すべてのコンポーネント・インターフェイス (エージェント、ホスト、およびストリーム) は、コンポーネントの busy 信号がlow になった後に利用可能になります。

120

インテル® oneAPI プログラミング・ガイド

IP コンポーネントのリセット動作を示す波形の例

4.8.7.1.12.

printf コマンド

sycl::oneapi::experimental::printf() 関数は、現在の IP コンポーネントではサポートされていません。

4.8.7.2.

IP コンポーネントのエミュレートとデバッグ

コンポーネントとテストベンチをインテル® oneAPI デバッガーでデバッグできる x86-64 FPGA エミュレーション実行
可能ファイルにコンパイルして、設計の機能を検証します。この手順は、エミュレーションによるデバッグと呼ばれることもあります。
設計を x86-64 実行可能ファイルにコンパイルするのは、RTL を生成してシミュレートするより高速です。コンパイル時
間が短縮されるため、コンポーネントがハードウェアにどのように実装されているか検証する前に、コンポーネントを素早くデバッグおよび調整できます。
IP コンポーネントのエミュレートに追加のソフトウェアは必要なく、ホストコードを変更する必要もありません。
詳細については、「設計のエミュレートとデバッグ」を参照してください。

4.8.7.3.

シミュレーションによる IP コンポーネントの評価-Xstarget コンパイラー・オプションを使用してコンポーネントをインテル® FPGA デバイスファミリーまたは製品番
号にコンパイルすると、インテル® oneAPI DPC++/C++ コンパイラーは、設計 C++ テストベンチを、RTL シミュレー
ターで実行されるコンポーネントを RTL コンパイル済みバージョンにリンクします。
Siemens* EDA Questa* ソフトウェアを使用してシミュレーションを行います。インテル® oneAPI ベース・ツールキットを使用して IP コンポーネントを作成するには、Quest* シミュレーション・ソフトウェアをインストールします。
この方法で設計の機能を検証するのは、シミュレーションによるデバッグと呼ばれることがあります。シミュレーション
で設計の機能を検証するには、次のデバッグ手法を行います。

121

インテル® oneAPI プログラミング・ガイド

FPGA デバイスをターゲットにして、コンパイラーが生成する実行可能ファイルを実行します。



コードの特定の場所で変数値を出力パイプ、または mm_host インターフェイスに書き込みます。



設計の実行で生成された波形を確認します。
設計をコンパイルする際に、コンパイラーは信号を記録しません (デフォルト)。シミュレーションで信号ログを有効にするには、「評価中のデバッグ」を参照してください。

シミュレーションの詳細については、「シミュレーションによるカーネルの評価」を参照してください。
4.8.7.3.1.

評価中のデバッグ

デフォルトでは、コンパイラーは、信号をログに記録するとシミュレーション速度が低下し、波形ファイルが膨大なサイズになる可能性があるため、信号を記録しないようシミュレーターに指示します。ただし、デバッグ用途で波形を記録することはできます。
シミュレーターの信号記録を有効にするには、-Xsghdl オプションを追加して icpx -fsycl コマンドを起動します。
$ icpx -fsycl -fintelfpga -Xssimulation -Xstarget=<family_or_part_number> -Xsghdl <input
files>

注: コンポーネントとテストベンチを -Xsghdl オプションでコンパイルして、生成された実行可能ファイルをシミュレーションして波形を生成します。

シミュレーションが終了したら、現在のディレクトリーにある vsim.wlf ファイルを開いて波形を表示します。
シミュレーション後に波形を表示するには、次のようにします。

1.

Questa* シミュレーターで、<プロジェクト名>.prj ディレクトリーの vsim.wlf ファイルを開きます。

2.

<IP_component_name>_inst ブロックを右クリックして [Add Wave] を選択します。
最上位のコンポーネント信号 (start、done、ready_in、ready_out パラメーター) および出力が表示できるよ
うになります。波形を参照して、コンポーネントがインターフェイスとどのように相互作用するか確認します。

122インテル® oneAPI プログラミング・ガイド

ヒント:
Questa* シミュレーターでシミュレーション波形を表示すると、シミュレーション・クロック周期は
デフォルトの 1000 ピコ秒 (ps) に設定されます。時間軸を同期して目盛りごとに 1 サイクルを表示
するには、時間解像度をピコ秒 (os) からナノ秒 (ns) に変更します。
1.
2.

4.8.7.4.

タイムラインを右クリックして、[Grid、Timeline & Cursor Control] を選択します。
[Timeline Configuration] で [Time] を ns に設定します。

FPGA IP コンポーネントのパフォーマンス最適化

インテル® oneAPI DPC++/C++ コンパイラーは、改善すべき領域を特定するツール、設計およびコンパイラーの動作を制御するさまざまなオプション、属性、そして拡張機能を提供します。
設計の詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』 (英語) を参照してください。

4.8.7.5.

インテル® Quartus® Prime 開発ソフトウェアによるコンポーネント IP の合成期待されたコンポーネントのパフォーマンスが達成されたら、インテル® Quartus® Prime 開発ソフトウェアを使用してコンポーネントを合成します。合成では、設計のエリアとパフォーマンス (fMAX) の正確な見積もりが生成されます。ただし、設計ではインテル® Quartus® Prime 開発ソフトウェアのレポートでタイミングが完全にクローズされることは期待されていません。
生成されるプロジェクトは、設計に最適な配置を実現するするため 1000MHz のクロック速度をターゲットにしており、
インテル® Quartus® Prime 開発ソフトウェアのログでタイミングクローズの警告が表示される場合があります。FPGA
最適化レポートに示される fMAX 値は、コンポーネントがタイミングを完全にクローズできる最大クロックレートを想定しています。
インテル® Quartus® Prime 開発ソフトウェアのコンパイルが完了すると、FPGA 最適化レポートのサマリーセクションに、コンポーネントのエリアとパフォーマンス・データが表示されます。これらの推定値はシミュレーションのみを目的として IP コンポーネントをコンパイルした場合に生成される推定値よりも正確です。
通常、インテル® Quartus® Prime 開発ソフトウェアによるコンパイル時間は、IP コンポーネントのサイズと複雑さに応じて、数分から数時間かかります。
コンポーネント IP を合成して QoR (結果品質) データを生成するには、コンポーネントの合成後にインテル® Quartus®
Prime 開 発 ソ フ ト ウ ェ ア に よ る コ ン パ イ ル 手 順 を 自 動 実 行 す る よ う コ ン パ イ ラ ー に 指 示 し ま す 。
-Xstarget=<FPGA デバイスファミリー> または -Xstarget=<FPGA 製品番号> オプションを icpx コマンドに追加します。
$ icpx -fsycl -fintelfpga -Xshardware -Xstarget="<FPGA デバイスファミリーまたは製品番号>"...

123

インテル® oneAPI プログラミング・ガイド

4.8.7.6.

IP をシステムに統合

インテル® Quartus® Prime 開発ソフトウェアを使用して IP コンポーネントをシステムに統合するには、Platform
Designer を含むインテル® Quartus® Prime 開発ソフトウェアに精通している必要があります。
インテル® oneAPI DPC++/C++ コンパイラーは、プロジェクト・ディレクトリー (<result>.prj/) と IP コンポーネン
トごとの IP ファイルのセット (同じシステムの一部であるカーネルのセット) を生成します。これは、-fsycl-devicecode-split=<off|per_source|per_kernel> オプションで制御できます。
コンパイラーによって生成された <result>.prj/ ディレクトリーには、以下のファイルを含む、インテル® Quartus®
Prime 開発ソフトウェアのプロジェクトに IP コンポーネントをインクルードするのに必要なすべてのファイルが含まれています。
<project_name>_di.ip
インテル® Quartus® Prime 開発ソフトウェアのプロジェクトに追加できる ip 形式のファイル。

<project_name>_di_hw.tcl
Platform Designer の IP コンポーネント・インターフェイスを記述するスクリプト。

<project_name>_di_inst.v
IP を他の Verilog モジュールにインスタンス化する方法の例。

インテル® Quartus® Prime 開発ソフトウェアのプロジェクトに IP を追加



Platform Designer システムに IP を追加

4.8.7.6.1.

インテル® Quartus® Prime 開発ソフトウェアのプロジェクトへの IP の追加

インテル® Quartus® Prime 開発ソフトウェアのプロジェクトでインテル® oneAPI DPC++/C++ コンパイラーによって生成された IP コンポーネントを使用するには、最初に .ip ファイルをプロジェクトに追加する必要があります。
.ip ファイルには、コンポーネントに必要なすべての HDL ファイルに追加するすべての情報が含まれています。また、IP合成に必要なコンポーネント固有のインテル® Quartus® Prime 開発ソフトウェアの設定ファイル (.qsf) にも適用されます。
次の手順を実行します。
1.

インテル® Quartus® Prime 開発ソフトウェア・プロ・エディションのプロジェクトを作成します。

2.

Platform Designer を開き、oneAPI フォルダーから IP を選択します。
IP を oneAPI フォルダーに配置するには、生成された IP プロジェクトを含むディレクトリーにプロジェクトを作成するか、ファイルへのパスを追加します。

124インテル® oneAPI プログラミング・ガイド

3.

残りの インテル® Quartus® Prime 開発ソフトウェアのプロジェクトを作成します。
IP コ ン ポ ー ネ ン ト の 最 上 位 モ ジ ュ ー ル を イ ン ス タ ン ス 化 す る 方 法 の 例 は 、 以 下 の フ ァ イ ル を 調 べ ま す 。
<result>.prj/<project_name>_di_inst.v

4.8.7.6.2.

Platform Designer システムに IP を追加

Platform Designer システムでインテル® oneAPI DPC++/C++ コンパイラーによって生成された IP コンポーネントを使用するには、最初にディレクトリーを IP 検索パスまたは IP カタログに追加する必要があります。
Platform Designer で、IP コンポーネントが IP カタログに表示されない場合は、次の操作を行います。
1.

インテル® Quartus® Prime 開発ソフトウェアで、[Tools] > [Options] をクリックします。

2.

[Options] ダイアログボックスの [Category] で、[IP Settings] を展開し [IP Catalog Search Locations] をクリックします。

3.

[IP Catalog Search Locations] ダイアログボックスで、_hw.tcl ファイルを含むディレクトリーのパスを<result>.prj/<project_name> 形式で IP 検索パスに追加します。

4.

[IP Catalog] で、oneAPI プロジェクト・ディレクトリーから IP を選択して、Platform Designer システムに追加します。

Platform Designer の詳細については、『インテル® Quartus®Prime 開発ソフトウェア・プロ・エディション・ユーザーガ
イド』の「Platform Designer を使用したシステムの作成」 (英語) を参照してください。
Platform Designer を使用して IP コンポーネントをシステムに追加する例については、「Platform Designer のサンプ
ル チュートリアル」 (英語) を参照してください。

4.8.7.7.

配布用に IP コンポーネントを暗号化

インテル® FPGA 設計ソリューション・ネットワークのメンバーである場合、IP 設計ファイルを暗号化し、ライセンスを生成するツールにアクセスできます。IP ユーザーは、生成されたランセンスで指定された方法でのみ、暗号化された IP を利用できます。
このライセンスは、インテル® Quartus® Prime 開発ソフトウェアで使用される FlexLM ライセンス技術と互換性があります。
インテルが提供する IP 暗号化およびライセンスインフラがインストールされている場合、 インテル® oneAPI
DCP++/C++ コンパイラーを使用して暗号化された IP を生成できます。
暗号化された IP は、ユーザーがインテル® Quartus® Prime 開発ソフトウェアのライセンス検索パスに追加したファイルによってライセンスされたインテル® Quartus® Prime 開発ソフトウェアで使用できます。詳細については、インテル®
FPGA 設計 ソリューション・ネットワークに参加して、インテルが提供するドキュメントを参照してください。
暗号化された IP でシミュレーションをサポートする場合は、シミュレーション用に個別に暗号化されたバージョンのIP を作成する必要があります。シミュレーションには、IEEE 1735 準拠の暗号化スキームが使用されます。
125インテル® oneAPI プログラミング・ガイド

インテル® Quartus®Prime 開発ソフトウェアで使用する暗号化された IP を生成するには、次のコマンドを使用します。
$ icpx -fsycl -fintelfpga -Xshardware -Xstarget=<FPGA デバイスまたは製品番号> -Xsencryptionkey=<key> -Xsencryption-id=<product_id> -Xsencryption-release-date=<yyyy.mm>

重要: このコマンドを実行する前に、IP のライセンス ファイルを作成し、そのライセンスファイルを$LM_LICENSE_FILE 環境変数に追加します。

シミュレーションで使用する暗号化された IP を生成するには、次のコマンドを使用します。
$ icpx -fsycl -fintelfpga -Xssimulation -Xstarget=< FPGA デバイスまたは製品番号> -DFPGA_SIMULATOR-I/ $INTELFPGAOCLSDKROOT/include -Xsencryption-key=<key> -Xsencryption-id=<product_id> Xsencryption-release-date=<yyyy.mm>

IP 暗号化向けの FPGA コンパイルオプション
オプション名-Xsencryptionkey

説明
ソースファイルの暗号化に使用する暗号化キーを指定します。

-Xsencryption-id

キーは 48 桁の 16 進数値でなければなりません。
IP の製品 ID を指定します。

-Xsencryption-release-date-Xsno-encryption

この ID は 4 桁の 16 進数値でなければなりません。
リリース日を yyyy.mm 形式で設定します。
IP を暗号化する icpx -fsycl コマンドのエイリアスを作成した場合、エイリアス
コマンドではこのオプションを使用して暗号化を一時的に無効化します。

4.8.8 FPGA 高速再コンパイルインテル® oneAPI DPC++/C++ コンパイラーは、FPGA ハードウェアの事前 (AOT) コンパイルのみをサポートします。
FPGA ハードウェア・イメージは、コンパイル時に生成されます。FPGA デバイスイメージの生成には、コンパイルが完了するまで数時間かかる場合があります。ホストコードにのみ影響する変更があった場合、既存の FPGA デバイスイメー
ジを再利用し、時間のかかるデバイスコンパイルを回避しホストコードのみを再コンパイルします。シミュレーター向けのコンパイルははるかに高速ですが、-reuse-exe オプションを使用すると時間を節約できます。
インテル® oneAPI DPC++/C++ コンパイラーは、デバイスコードとホストコードのコンパイルを分離する次の機能をサ
ポートします。
-reuse-exe=<exe_name> オプションを指定して、既存の FPGA デバイスイメージを再利用するようコンパ
イラーに指示します。



ホストとデバイスのコードを別々のファイルに分離します。コードの変更がホストファイルにのみ影響する場合、
FPGA デバイスイメージは生成されません。



コンパイラー・オプション -fsycl-device-code-split を使用してデバイスコードを分離します。

126インテル® oneAPI プログラミング・ガイド

次の節では、この 2 つの機能について詳しく説明します。

4.8.8.1.

-reuse-exe オプションを使用

前回のコンパイル以降、デバイスに影響するデバイスコードとオプションが変更されていない場合、 -reuseexe=<exe_name> オプションを指定して FPGA ハードウェア・シミュレーションイメージを既存の実行形ファイルから抽出して、新しい実行形式ファイルにパッケージするようにコンパイラーに指示します。これにより、デバイスコンパイ
ル時間を節約します。
使用例:# 最初のコンパイル$ icpx -fsycl -fintelfpga -Xshardware <files.cpp> -o out.fpga

最初のコンパイルで FPGA デバイスイメージが生成されますが、これには数時間を要します。ここで、ホストコードに変更を加えます。
# その後のコンパイル$ icpx -fsycl <files.cpp> -o out.fpga -reuse-exe=out.fpga -Xshardware -fintelfpga

コマンドにより次のいずれかのアクションが実行されます。
out.fpga が存在しない場合、-reuse-exe オプションは無視、され FPGA デバイスイメージが再生成されます。これは、プロジェクトを初めてコンパイルする場合、常にあてはまります。

out.fpga が存在すると、コンパイラーは FPGA デバイスコードに影響する変更が前回のコンパイル以降に行われていないか確認します。デバイスコードに影響する変更が行われていない場合、コンパイラーは既存のFPGA デバイスイメージを再利用してホストコードのみを再コンパイルします。再コンパイルには数分かかります。

out.fpga ファイルが検出できても、FPGA デバイスコードが前回のコンパイル、と同じ結果を生成することをコンパイラーが確認できない場合、警告が出力され FPGA デバイスコードは完全な再コンパイルが行われます。
コンパイラーのチェックは保守的である必要があるため、-reuse-exe オプションを使用すると、誤った再コン
パイルが行われる可能性があります。

4.8.8.2.

デバイスリンクを使用

プログラムが main.cpp と kernel.cpp で構成され、kernel.cpp ファイルのみがデバイスコードを含むと仮定します。
通常のコンパイル手順では、FPGA デバイスイメージの生成はリンク時に行われます。
# 通常のコンパイルコマンド$ icpx -fsycl -fintelfpga -Xshardware main.cpp kernel.cpp -o link.fpga

main.cpp または kernel.cpp のどちらかを変更すると、FPGA ハードウェア・イメージの再生成がトリガーされます。

127インテル® oneAPI プログラミング・ガイド

次の図はこのコンパイル手順を示します。
コンパイル手順

ホストコードを繰り返し処理し、FPGA デバイスのコンパイル時間が長くならないようにするには、デバイスリンクを使用してデバイスとホストのコンパイルを分離することを検討してください。
# デバイス・リンク・コマンド$ icpx -fsycl -fintelfpga -fsycl-link=image <input files> [options]

コンパイルは次の 3 つの手順から成ります。
1.

デバイスコードをコンパイルします。

$ icpx -fsycl -fintelfpga -Xshardware -fsycl-link=image kernel.cpp -o dev_image.a

入力ファイルには、デバイスコードを含むすべてのファイが含まれている必要があります。このステップには数時間かかります。
2.

ホストコードをコンパイルします。

$ icpx -fsycl -fintelfpga main.cpp -c -o host.o

入力ファイルには、ホストコードのみを対象とするすべてのソースファイルを含める必要があります。これには、デバイスで実行されるソースコードを含めることはできませんが、コマンドライン・オプションの解釈や結果レポートなどのセットアップ・コードとディアダウン・コードを含めることができます。このステップには数秒かかります。

128

インテル® oneAPI プログラミング・ガイド

3.

デバイスリンクを作成します。

$ icpx -fsycl -fintelfpga host.o dev_image.a -o fast_recompile.fpga

このステップには数秒かかります。入力には、1 つ以上のホスト・オブジェクト・ファイル (.o) と 1 つのデバイスファ
イル (.a) を含める必要があります。静的ライブラリー (.a ファイル) を使用する場合、必ず静的ライブラリーをリンクしてください。これ以外ではライブラリー関数は破棄されます。静的ライブラリーに関する詳細は、「静的ライブラ
リー・リンクの順序」 (英語) を参照してください。

注: ホストのみのファイルを変更する場合、手順 2 と 3 を実行します。

次の図はデバイスのリンク手順を示します。
FPGA デバイスリンク

デバイスリンクの使い方については、インテル® oneAPI サンプルブラウザー (英語) の fast_recompile チュートリ
アルを参照してください。

4.8.8.3.

-fsycl-device-code-split[=value] オプションを使用-fsycl-device-code-split[=value] オプションを使用すると、コンパイラーは各分割パーティションをそれ自身のデバイスをターゲットにしているようにコンパイルします。このオプションは、次のモードをサポートします。


auto: これはデフォルトモードであり、値なしの -fsycl-device-code-split と同等です。コンパイラー
はヒューリスティックに基づいてデバイスコードを分割する最良の方法を選択します。

129インテル® oneAPI プログラミング・ガイド



off: すべてのカーネルに対して単一のモジュールを生成します。



per_kernel: カーネルごとに個別のデバイス・コード・モジュールを生成します。各デバイス・コード・モジュー
ルには、カーネルと呼び出される関数や使用する変数など、すべての依存関係が含まれます。



per_source: ソース (翻訳単位) ごとに個別のデバイス・コード・モジュールを生成します。各デバイス・コード・
モジュールには、ソースごとにグループ化されたカーネルと、ほかの翻訳ユニットからの SYCL_EXTERNAL マ
クロマーク付きの関数を含む、使用されたすべての変数など、すべての依存関係が含まれます。

注意: FPGA では、各スプリットは、メモリーなどのデバイスリソースを FPGA 間で共有する必要があります。さらに、カーネルパイプは、同じスプリット内に source と sink を持つ必要があります。

このオプションの詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』の「fsycl-device-code-split」 (英語) のトピックを参照してください。

4.8.8.4.

どの機能を使用するか?

前述の 2 つの機能では、デバイスリンクよりも -reuse-exe オプションを使用する方が容易です。このオプションを使用すると、ホストとデバイスのコードを単一ソースとして記述することができます。これは小規模なプログラムに適しています。大規模で複雑なプロジェクトでは、デバイスリンクにはコンパイラーの動作を細かくコントロールできる利点があります。
しかし、個別ファイルのコンパイルと比較すると -reuse-exe オプションにはいくつかの欠点もあります。以下に-reuse-exe オプションを使用する際の注意点を示します。


コンパイラーは、影響するソースの変更がないことを確認するため、デバイスコードを部分的に再コンパイルする時間が必要です。大規模なプロジェクトでは、これには数分かかります。個別のファイルをコンパイルする場合、このコストは発生しません。



コンパイラーは、デバイスコードの再コンパイルが必要であると誤って判断する場合があります。単一のソース
コードでは、ホストとデバイスコードが混在するため、ホストコードに変更を加えるとコンパイラーによるデバイ
スコードのビューが変わる可能性があります。コンパイラーは常に保守的であり、以前の FPGA バイナリーの再利用が安全であると確認できない場合、完全な再コンパイルをトリガーします。個別にファイルをコンパイルすることで、これを排除できます。

4.8.9 複数の FPGA イメージを作成 (Linux* のみ)
インテル® oneAPI DPC++/C++ コンパイラーの機能を使用して、FPGA コンパイルを異なる FPGA イメージに分割することができます。この機能は、プロジェクトの設計が単一の FPGA に適合しない場合に役立ちます。これにより大規模な設計を複数の小さなイメージに分割して、FPGA デバイスを部分的に再構成できます。

130

インテル® oneAPI プログラミング・ガイド

次のいずれかのアプローチで設計を分割できます。それぞれに利点があります。


動的リンク



動的ロード

動的リンクは動的ロードよりも実装が容易ですが、すべてのデバイスイメージをメモリーにロードする必要があるため、動的リンクではホストデバイスに多くのメモリーが必要になることがあります。動的ロードにはそのような制限はありま
せんが、ソースレベルで変更が必要になります。次の表はそれぞれの違いを示しています。
動的リンクと動的ロード

実行時に FPGA イメージを動的に変更できるか?
FPGA イメージのタイプと数の定義
ホストプログラムのメモリー容量
ホストコードの呼び出し

4.8.9.1.

動的リンク
はい

動的ロード
はい

コンパイル時間
すべての FPGA イメージは実行時にメモリーに展開されます。
動的ライブラリー関数を直接呼び出します。

実行時
明示的にロードされた FPGA イメージのみ
が実行時にメモリーに展開されます。
呼び出す動的ライブラリーと関数を明示的にロードします。

動的リンク

この手順では、設計を複数のソースファイルに分割して、それぞれを個別の FPGA イメージにマッピングできます。
FPGA イメージ数が少ない設計でこの手順を使用することを推奨します。
この手順を使用するには次を行います。
1.

必要な FPGA イメージごとにカーネルを送信する個別の .cpp ファイルを生成するようにソースコードを分割します。ホストコードを 1 つ以上の .cpp ファイルに分割し、カーネルファイル内の関数を参照できるようにします。
次のような 3 つのファイルがあると想定します。
‐

ホストコードを含む main.cpp。次に例を示します。

// main.cpp
int main() {queue queueA;
add(queueA);mul(queueA);}

131

インテル® oneAPI プログラミング・ガイド‐

vector_add カーネルを送信する関数を含む vector_add.cpp の例を示します。

// vector_add.cpp
extern "C"{void add(queue queueA) {queue.submit(// カーネルコード
);
}
}

‐

vector_mul カーネルを送信する関数を含む vector_mul.cpp の例を示します。

// vector_mul.cpp
extern "C"{void mul(queue queueA) {queue.submit(// カーネルコード
);
}
}

2.

次のコマンドでソースファイルをコンパイルします。

$ icpx -fsycl -fPIC -fintelfpga -c vector_add.cpp -o vector_add.o$ icpx -fsycl -fPIC -fintelfpga -c vector_mul.cpp -o vector_mul.o// FPGA イメージのコンパイルにはかなり時間がかかります$ icpx -fsycl -fPIC -shared -fintelfpga vector_add.o -o vector_add.so -Xshardware-Xstarget=pac_a10$ icpx -fsycl -fPIC -shared -fintelfpga vector_mul.o -o vector_mul.so -Xshardware Xstarget=pac_a10// 最後のリンクステップ$ icpx -fsycl -o main.exe main.cpp vector_add.so vector_mul.so

この手順では、長い FPGA コンパイル手順を個別のコマンドに分割して、異なるシステムで実行したり、ファイルを変更した場合にのみ実行するようにできます。

4.8.9.2.

動的ロード

異なる FPGA イメージを一括してメモリーにロードしないようにするには、この手順を使用します。動的リンクと同様にこの手順でもコードを分割する必要があります。ただし、ここではホストプログラムに .so (共有オブジェクト) ファイルをロードする必要があります。この手順の利点は、コンパイル時にすべてのイメージファイルをリンクすることなく、必要に応じて大きな FPGA イメージファイルを動的にロードできることです。
この手順を使用するには次を行います。
1.

動的リンクのステップ 1 で行ったのと同じ方法でソースコードを分割します。

2.

main.cpp ファイルを次のように変更します。

132

インテル® oneAPI プログラミング・ガイド// main.cpp#include <dlfcn.h>

int main() {queue queueA;bool runAdd, runMul;// runAdd と runMul が実行時に動的に設定されると想定
if (runAdd) {auto add_lib = dlopen("./vector_add.so", RTLD_NOW);
auto add = (void (*)(queue))dlsym(add_lib, "add");
add(queueA);}
if (runMul) {auto mul_lib = dlopen("./vector_mul.so", RTLD_NOW);
auto mul = (void (*)(queue))dlsym(mul_lib, "mul");mul(queueA);}}

3.

次のコマンドでソースファイルをコンパイルします。

注: .so ファイルは実行時に動的にロードされるため、コンパイル時にリンクする必要はありません。

$ icpx -fsycl -fPIC -fintelfpga -c vector_add.cpp -o vector_add.o$ icpx -fsycl -fPIC -fintelfpga -c vector_mul.cpp -o vector_mul.o// FPGA イメージのコンパイルにはかなり時間がかかります$ icpx -fsycl -fPIC -shared -fintelfpga vector_add.o -o vector_add.so -Xshardware Xstarget=pac_a10$ icpx -fsycl -fPIC -shared -fintelfpga vector_mul.o -o vector_mul.so -Xshardware Xstarget=pac_a10$ icpx -fsycl -o main.exe main.cpp// 設計を実行する前に、.so ファイルを示すパスを LD_LIBRARY_PATH に追加します// 例: export LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH

このアプローチでは、必要に応じて実行時に .so ファイルを任意にロードできます。これには、FPGA イメージの大規
模なライブラリーがあり、そこからファイルのサブセットを選択する場合に役立ちます。

4.8.10 FPGA BSP とボード
「FPGA コンパイルの種別」で説明したように、FPGA ハードウェア・イメージを生成するには、インテル® Quartus®
Prime 開発ソフトウェア (英語) を使用して、設計を RTL から FPGA のプリミティブ・ハードウェア・イメージ・リソースにマップする必要があります。FPGA ハードウェアへのコンパイルに必要な BSP については、「インテル® FPGA 開発手順」(英語) のウェブページを参照してください。

133

インテル® oneAPI プログラミング・ガイド

4.8.10.1. ボードとは?
GPU と同様に、FPGA はサーバーまたはデスクトップ・コンピューターに搭載されるカードまたはマウントされる集積回路です。FPGA ボードは、メモリー、電力、熱管理、および他のデバイスと通信する物理インターフェイスを提供します。

4.8.10.2. BSP とは?
BSP は、ソフトウェア・レイヤーと FPGA ハードウェア・スキャホールド・デザインで構成されており、インテル® oneAPI
DPC++/C++ コンパイラーを介して FPGA をターゲットにできます。コンパイラーによって生成された FPGA デザイン
は、BSP で提供されるフレームワークに組み込まれています。

4.8.10.3. ボードバリアントとは?
BSP はさまざまな機能をサポートする複数のボードバリアントを提供できます。例えば、intel_s10sx_pac BSP には、統合共有メモリー (USM) のサポート方法が異なる 2 つのバリアントがあります。USM の詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドとリファレンス』の「統合共有メモリー(USM)」 (英語) と「USM インターフェイス」 (英語) を参照してください。

注: ボードが複数の BSP をサポートし、BSP が複数のボードバリアントをサポートする場合があります。

インテル® oneAPI ベース・ツールキット用のインテル® FPGA アドオンは、2 つのボード BSP を提供し、この BSP に
よってサポートされるボードバリアントは icpx -fsycl コマンドで次のオプションを使用して選択できます。
dpcpp コマンドのオプション
ボード
インテル® プログラマブル・
アクセラレーション・カード(インテル® Arria® 10 GXFPGA 搭載版)
インテル® FPGA プログラ
マブル・アクセラレーション・
カード (インテル® FPGA
PAC) D5005 (旧名称:
インテル® プログラマブル・
アクセラレーション・カード(インテル® Stratix® 10 SXFPGA 搭載版))

134

BSP
intel_a10gx_pac

オプション-Xstarget=intel_a10gx_pac:pac_a10

USM のサポート
明示的な USM

intel_s10sx_pac-Xstarget=intel_s10sx_pac:pac_s10

明示的な USM

インテル® oneAPI プログラミング・ガイド

ボード
インテル® FPGA プログラ
マブル・アクセラレーション・
カード (インテル® FPGA
PAC) D5005 (旧名称:
インテル® プログラマブル・
アクセラレーション・カード(インテル® Stratix® 10 SXFPGA 搭載版))

BSP
intel_s10sx_pac

オプション
Xstarget=intel_s10sx_pac:pac_s10_usm

USM のサポート
明示的な USM
制限付き USM

注:
•

•

•

インテル® oneAPI DPC++/C++ コンパイラー (インテル® oneAPI ベース・ツールキットに含まれます) は、FPGA の初期イメージを生成するのに十分な BSP の一部分を提供します。対照的に、oneAPI ベース・ツールキット用インテル® FPGA アドオンは、FPGA ハードウェア・イ
メージの生成に必要な完全な BSP を提供します。
FPGA ボードで実行形式ファイルを実行する場合、実行形式ファイルがターゲットのボードバ
リアント向けに FPGA ボードを初期化したことを確認する必要があります。FPGA ボードの初期化については、「FPGA ボードの初期化」を参照してください。
制限付き USM に適用可能な FPGA の最適化については、『インテル® oneAPI ツールキット
向け FPGA 最適化ガイド』 (英語) の事前固定 (プリピニング) とゼロコピーのメモリーアクセスを参照してください。

4.8.10.4. FPGA ボードの初期化
FPGA ハードウェア・イメージ形式を実行する前に、次のコマンドを使用して FPGA ボードを初期化する必要があります。
$ aocl initialize <board id> <board variant>

説明:
FPGA ボードの初期化パラメーター
パラメーター<board_id>

説明aocl diagnose (英語) コマンドから取得したボード ID。

<board variant>

例: ac10、ac11 など。
実行形式のコンパイル時に -Xsboard オプションで指定されたボードバリアントの名前。
例: pac_s10_usm。

例えば、システムに 1 台のインテル® FPGA プログラマブル・アクセラレーション・カード D5005 (インテル® FPGAPAC D5005) (旧名称: インテル®プログラマブル・アクセラレーション・カード (インテル® Stratix® 10 SX FPGA 搭載版)) が搭載され、次のコマンドで実行形式ファイルをコンパイルすると仮定します。
135

インテル® oneAPI プログラミング・ガイド$ icpx -fsycl -fintelfpga -Xshardware -Xstarget=intel_s10sx_pac:pac_s10_usm kernel.cpp

この場合、次のコマンドでボードを初期化する必要があります。
$ aocl initialize acl0 pac_s10_usm

初期化が完了すると、次のいずれかを実行する場合を除き、ボードを再び初期化することなく 実行形式ファイルを実行できます。


ホストの電源をオンにした後、初めて SYCL* コンパイルされたワークロードを実行する。



FPGA で SYCL* ワークロード以外を実行した後で SYCL* コンパイルされたワークロードを実行する。

-Xsboard オプションで別のボードバリアントでコンパイルされた SYCL* コンパイルされたワークロードを実行する。

4.8.10.5. FPGA ハードウェア・イメージの情報を取得
aocl binedit ユーティリティーは、コンパイルされたバイナリーから次のような情報を抽出できます。


以下のようなコンパイル環境の詳細‐

コンパイラーのバージョン‐

使用したコンパイルコマンド‐

インテル® Quartus® Prime 開発ソフトウェアのバージョン

コンパイルに使用した BSP の board_spec.xml

カーネル fMAX (インテル® Quartus® Prime 開発ソフトウェアがコンパイルした fMAX)。



コンパイルに使用した BSP およびボード

4.8.10.6. 構文
aocl ユーティリティーは次のコマンドでで使用します。
$ aocl binedit <oneapi_binary> <list/get/print/exists> [<section_name> [output_file]]

以下に利用可能なアクションを示します。


list: バイナリー中の利用可能な <section_name> をすべてリストします。



print: バイナリー中のパッケージファイルの指定されたセクションの内容を標準出力に書き出します。



get: 指定されたセクションの内容を出力ファイルに書き出します。

exists: セクションがバイナリーのパッケージファイルに存在するか確認します。0 以外の終了コードはセクションが存在しないことを示します。

136インテル® oneAPI プログラミング・ガイド

例えば、シミュレーター手順でコンパイルされたバイナリーを次のコマンドで SimulatorDevice に出力します。
$ aocl binedit <oneapi_binary> print .acl.board

また、次のコマンドで BSP のバージョンを確認できます。
$ aocl binedit <oneapi_binary> print .acl.board_package

4.8.11 複数の同種の FPGA デバイスをターゲットにする
インテル® oneAPI DPC++/C++ コンパイラーは、単一ホスト CPU から複数の同種の FPGA デバイスをターゲットにすることをサポートします。これにより、複数の FPGA でプログラムを並列化して実行することで、設計のスループットを向上できる可能性があります。
複数コンテキストでは、OpenCL* レイヤーのバッファーをコンテキスト間でコピーする必要があるため、オーバーヘッドが発生して全体のパフォーマンスに影響を及ぼします。ただし、設計が単純でオーバーヘッドが全体のパフォーマンスに影響しない場合は、複数コンテキストを使用できます。
次のいずれかの方法で複数の FPGA デバイスをターゲットにします。

4.8.11.1. 複数のデバイスキューで単一のコンテキストを作成
次の手順を実行して、単一のコンテキストで複数の FPGA デバイスをターゲットにします。
1.

単一の SYCL* コンテキストを作成し、同じプラットフォームの FPGA デバイスのコレクションをカプセル化します。

% context ctxt(deviceList, &m_exception_handler);2.

それぞれの FPGA デバイス向けに SYCL* キューを作成。

std::vector<queue> queueList;for (unsigned int i = 0; i < ctxt.get_devices().size(); i++) {queue newQueue(ctxt, ctxt.get_devices()[i], &m_exception_handler);queueList.push_back(newQueue);}3.

利用可能なすべての FPGA デバイスに、同一または異なるデバイスコードを送信します。すべてのデバイスのサブセットをターゲットにする場合、不要なデバイスを除外するため最初にデバイスの選択を実行する必要があります。

for (unsigned int i = 0; i < queueList.size(); i++) {queueList[i].submit([&](handler& cgh) {...});}137

インテル® oneAPI プログラミング・ガイド

4.8.11.2. それぞれのデバイスキュー向けにコンテキストを作成 (複数コンテキスト)
次の手順を実行して、複数のコンテキストで複数の FPGA デバイスをターゲットにします。
1.

利用可能な FPGA デバイスのリストを取得します。オプションで、デバイスメンバーまたはデバイス・プロパ
ティーに基づいてデバイスを選択できます。デバイス名などのデバイス・プロパティーは、対象のデバイス・プロパ
ティーとともにメンバー関数 get_info()const を使用します。

$ std::vector<device> deviceList = device::get_devices();2.

それぞれの FPGA デバイス向けに SYCL* キューを作成。

std::vector<queue> queueList;for (unsigned int i = 0; i < deviceList.size(); i++) {queue newQueue(deviceList[i], &m_exception_handler);queueList.push_back(newQueue);}3.

利用可能なすべての FPGA デバイスに、同一または異なるデバイスコードを送信します。すべてのデバイスのサブセットをターゲットにする場合、不要なデバイスを除外するため最初にデバイスの選択を実行する必要があります。

for (unsigned int i = 0; i < queueList.size(); i++) {queueList[i].submit([&](handler& cgh) {...});}

4.8.11.3. 制限事項
複数の FPGA デバイスをターゲットにする場合、次の制限事項を考慮してください。


すべての FPGA デバイスは同じ FPGA ビットストリームを使用します。



使用するすべての FPGA デバイスは、同一の FPGA カードである必要があります (同じ -Xsboard target)

4.8.12 複数のプラットフォームをターゲットにする(異なるデバイスセレクターを使用して) 複数のターゲット・デバイス・タイプを対象とする設計をコンパイルするには、次のコマンドを実行します。

138

インテル® oneAPI プログラミング・ガイド

4.8.12.1. エミュレーション・コンパイル
FPGA エミュレーター・ターゲットの SYCL* コードのコンパイルには、次のコマンドを使用します。
# Linux* 向け:$ icpx -fsycl jit_kernel.cpp -c -o jit_kernel.o$ icpx -fsycl -fintelfpga -fsycl-link=image fpga_kernel.cpp -o fpga_kernel.a$ icpx -fsycl -fintelfpga main.cpp jit_kernel.o fpga_kernel.a# Windows* 向け:$ icx-cl -fsycl jit_kernel.cpp -c -o jit_kernel.o$ icx-cl -fsycl -fintelfpga -fsycl-link=image fpga_kernel.cpp -o fpga_kernel.lib$ icx-cl -fsycl -fintelfpga main.cpp jit_kernel.o fpga_kernel.lib

この例は、FPGA カーネル (AOT 手順) と CPU カーネル (JIT 手順) およびライブラリーを使用します。
具体的には、main.cpp ファイルに main 関数が含まれ、CPU (jit_kernel.cpp) と FPGA (fpga_kernel.cpp)の両方のカーネルを必要とします。
サンプルの fpga_kernel.cpp ファイル:
sycl::cpu_selector device_selector;
queue deviceQueue(device_selector);
deviceQueue.submit([&](handler &cgh) {// CPU カーネル関数});

サンプルの fpga_kernel.cpp ファイル:#if FPGA_SIMULATOR
auto selector = sycl::ext::intel::fpga_simulator_selector_v;#elif FPGA_HARDWARE
auto selector = sycl::ext::intel::fpga_selector_v;#else // #if FPGA_EMULATOR
auto selector = sycl::ext::intel::fpga_emulator_selector_v;#endifqueue deviceQueue(device_selector);
deviceQueue.submit([&](handler &cgh) {// FPGA カーネル関数
});

139

インテル® oneAPI プログラミング・ガイド

4.8.12.2. FPGA ハードウェア・コンパイル
FPGA ハードウェア・ターゲット向けにコンパイルするには、-DFPGA_EMULATOR オプションの代わりに -Xshardware
オプションを指定します。
# Linux* 向け:$ icpx -fsycl jit_kernel.cpp -c -o jit_kernel.o// ハードウェアのコンパイルコマンド。時間がかかります。
$ icpx -fsycl -fintelfpga -fsycl-link=image -Xshardware fpga_kernel.cpp -o fpga_kernel.a$ icpx -fsycl -fintelfpga main.cpp jit_kernel.o fpga_kernel.a# Windows* 向け:$ icx-cl -fsycl jit_kernel.cpp -c -o jit_kernel.o// ハードウェアのコンパイルコマンド。時間がかかります。
$ icx-cl -fsycl -fintelfpga -fsycl-link=image -Xshardware fpga_kernel.cpp -o fpga_kernel.lib$ icx-cl -fsycl -fintelfpga main.cpp jit_kernel.o fpga_kernel.lib

4.8.13 FPGA-CPU インタラクション
FPGA の設計におけるパフォーマンスに影響する主な要因の 1 つは、FPGA デ実行されるカーネルが CPU ホストとどのような相互作用を持つかです。

4.8.13.1. ホストとカーネルのインタラクション
FPGA デバイスは PCIe* (英語) を介してホスト (CPU) と通信します。
ホストと FPGA デバイス通信

これは、FPGA をターゲットにする SYCL* プログラムのパフォーマンスに影響する重要な要素です。さらに、特定のSYCL* プログラムを初めて実行する場合、FPGA をハードウェア・ビットストリームで構成する必要があり、これには時間かかります。

140

インテル® oneAPI プログラミング・ガイド

4.8.13.2. データ転送
通常、FPGA ボードには、独自のプライベート DDR (英語) メモリーが搭載されます。CPU は、カーネルが FPGA ロー
カル DDR メモリーにアクセスして使用するすべてのデータを一括転送するか、ダイレクト・メモリー・アクセス (DMA)(英語) を行う必要があります。カーネルは操作を完了すると、結果を DMA 経由で CPU に転送する必要があります。転
送速度は PCIe* リンクと DMA の効率によって制限されます。インテル® プログラマブル・アクセラレーション・カード(インテル® Arria® 10 GX FPGA 搭載版) には、PCIe* Gen 3 x 8 リンクがあり、転送は通常 6 から 7GB/秒に制限されます。
データ転送時間は次のように管理されます。


SYCL* では、バッファーに読み取り専用または書き込み専用のタグを付けることができ、不要な転送を排除できます。



同時操作数を最大化することでシステム全体の効率を改善できます。PCIe* は逆方向への同時転送をサポート
し、PCIe* 転送はカーネルの実行に干渉しないため、ダブル・バッファリングなどの手法を利用できます。これらの手法の詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「カーネル呼び出し
キューを利用するダブル・バッファリング・ホスト」 (英語) と、「double_buffering」 (英語) のチュートリアルを参照してください。



制限付き USM をサポートするボードバリアントにシステムメモリーを事前に固定することで、テータ転送
スループットを向上させます。詳細については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』の「事前固定(プリピニング)」 (英語) を参照してください。

4.8.13.3. コンフィギュレーション時間
コンフィギュレーションと呼ばれる手順で、FPGA デバイスのハードウェア・ビットストリームをプログラムします。
コンフィギュレーションは、FPGA デバイスとの通信に数秒間を要する操作です。SYCL* ランタイムはコンフィギュ
レーションを自動的に管理します。ランタイムは、コンフィギュレーション行われるタイミングを決定します。例えば、カーネルが最初に起動された時にコンフィギュレーションがトリガーされることがありますが、ビットストリームは変更されていないため、同じカーネルを以降に起動する際にはコンフィギュレーションがトリガーされないことがあります。したがって、開発中は、FPGA のコンフィギュレーション後にカーソルの実行時間を計測することを推奨します。
例えば、カーネルの実行時間を計測する前に、カーネルをウォームアップ実行します。ウォームアップ・コードは、実際のコードでは削除します。

4.8.13.4. 複数のカーネル呼び出し
SYCL* プログラムが同じカーネルを SYCL* キューに複数回送信する場合 (ループ内での single_task 呼び出しなど)、1 つのカーネル呼び出しのみがアクティブになります。それ以降のカーネル呼び出しでは、前のカーネルが実行を完了するのを待機します。

141インテル® oneAPI プログラミング・ガイド

4.8.14 FPGA パフォーマンスの最適化
前述の FPGA 手順では、FPGA 向けのコンパイルの基本を説明しましたが、設計時にパフォーマンス向上について習得
すべきことはまだたくさんあります。インテル® oneAPI DPC++/C++ コンパイラーは、改善すべき領域を特定するツー
ル、設計およびコンパイラーの動作を制御するさまざまなオプション、属性、そして拡張機能を提供します。これらの情報はすべて、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』 (英語) に記載されています。設計時の最適化に関する手法を理解したい開発者はこのガイドを参照してください。

4.8.15 FPGA 向けの RTL ライブラリーを使用する
RTL ライブラリーは、1 つ以上の関数を含むファイルです。レジスター転送レベル (RTL) コードを使用して RTL ライブラ
リー・ファイルを作成できます。次に、このライブラリー・ファイルをインクルードして、SYCL* カーネル内で関数を使用します。

SYCL* で使用するライブラリーを生成するには、次のファイルを用意する必要があります。
FPGA 向けに SYRL* を使用して RTL ライブラリーを作成
ファイルまたはコンポーネント
RTL ライブラリー・ファイル
RTL ソースファイル

eXtensible マークアップ言語ファイル (.xml)

ヘッダーファイル (.hpp)

142

説明
RTL コ ン ポ ー ネ ン ト を 定 義 す る 、 Verilog 、 System Verilog, ま た は
VHDL ファイル。
インテル® Quartus® Prime 開発ソフトウェアの IP ファイル(.qip)、
Synopsys Design Constraints ファイル (.sdc)、Tcl スクリプトファイ
ル (.tcl) などの追加ファイルは許可されません。ファイル構文の詳細については、「RTL ライブラリーのオブジェクト・マニフェスト・ファイルの構文」を参照してください。
RTL コンポーネントのプロパティーを記述します。インテル® oneAPI
DPC++/C++ コンパイラーは、これらのプロパティーを使用して RTL コ
ンポーネントを SYCL* パイプラインに統合します。XML 属性の詳細については、「ATTRIBUTES の XML 要素」 (英語) を参照してください。
有効な SYCL* カーネル言語を含み、RTL コンポーネントによって実装される関数のシグネチャーを宣言するヘッダーファイルです。

インテル® oneAPI プログラミング・ガイド

ファイルまたはコンポーネント
エミュレーション・モデル・ファイル (SYCL* ベース)SYCL* 関数SYCL* ソースファイル (.cpp)
ヘッダーファイル (.hpp)

説明
エミュレーションでのみ使用される RTL コンポーネントの C++ モデルを提供します。ハードウェア向けの完全なコンパイルには RTL ソース
ファイルを使用します。
SYCL* 関数の定義を含みます。これらの関数はエミュレーションと完全なハードウェアのコンパイルで使用されます。
SYCL* 構文で SYCL* から呼び出される関数を記述するヘッダーファ
イル。

ライブラリー・ファイルの形式は、ソースコードをコンパイルするオペレーティング・システムと同じ形式を使用し、ライブ
ラリー情報を伝達する追加のセクションを持ちます。
Linux* プラットフォームでは、ライブラリーは .a アーカイブファイルで .o オブジェクト・ファイルを含みます。

Windows* プラットフォームでは、ライブラリーは .lib アーカイブファイルで .obj オブジェクト・ファイルを含みます。

ライブラリー内部の関数のハードウェアの設計や実装の詳細を理解していなくても、カーネルからライブラリーの関数を呼び出すことができます。カーネルをコンパイルする際にライブラリーを icpx コマンドラインに追加します。
ライブラリーの作成は 2 段階のプロセスからなります。
1.

2.

各オブジェクト・ファイルは、fpga_crossgen コマンドにより入力ソースファイルから作成されます。
‐

オブジェクト・ファイルは、コードの CPU 形式と FPGA 形式の両方から成るソースコードの中間表現です。

‐

オブジェクト・ファイルは、同一のインテル® HLS 設計製品でのみ使用することが想定されています。複数のHLS 設計製品を使用する場合、対象の製品ごとに個別のオブジェクトを作成する必要があります。

オブジェクト・ファイルは fpga_libtool コマンドでライブラリー・ファイルに結合します。すべてのオブジェク
トが同一の HLS 設計製品を対象とする場合、各種タイプのソースコードから生成されたオブジェクトをライブラリーに統合できます。
ライブラリーにはツールチェーンのバージョン番号が自動的に割り当てられるため、同じバージョンの HLS 設計
製品でのみ利用します。

143

インテル® oneAPI プログラミング・ガイド

ライブラリー・ツールチェーンの作成手順

4.8.15.1. ソースコードからライブラリー・オブジェクトを作成
ソースコードのオブジェクト・ファイルからライブラリーを作成することができます。SYCL* ベースのオブジェクト・ファイ
ルには、ホストで使用する CPU を取得するハードウェア実行とカーネルのエミュレーションで使用する CPU コードが含まれています。

4.8.15.2. ソースコードからオブジェクト・ファイルを作成
fpga_crossgen コマンドを使用して、ソースコードからライブラリー・オブジェクトを作成します。ソースコードから作成されたオブジェクトには、オブジェクト内の関数のエミュレートとオブジェクト関数のハードウェア合成に必要な情報が含まれています。
fpga_crossgen コマンドは、1 つの入力ソースファイルから 1 つのオブジェクト・ファイルを作成します。作成されたオブジェクトは、同じインテル® HLS 設計ツールを対象とするライブラリーでのみ利用できます。オブジェクトもまたバージョン管理されます。それぞれのオブジェクトには、コンパイラーのバージョン番号が割り当てられ、同一バージョンのインテル® HLS 設定ツールでのみ使用されます。
次のコマンドを使用してライブラリー・オブジェクトを作成します。
$ fpga_crossgen <rtl_spec>.xml --emulation_model <emulation_model>.cpp --target sycl -o<object_file>

次の表でパラメーターについて説明します。
FPGA crossgen パラメーター
パラメーター<rtl_spec>--target
-o

144

説明
RTL ライブラリーに関する詳細を指定する XML ファイル名。
ライブラリー用のインテル® HLS 設計ツール (sycl) を対象とします。オブジェクトは、
fpga_libtool を使用して SYCL* ライブラリー・アーカイブに統合されます。
(オプション) オブジェクト・ファイル名を指定します。指定しないと、オブジェクト・ファイル
名はソースコードのファイル名と同じ名前になりますが、拡張子は .o または .obj です。

インテル® oneAPI プログラミング・ガイド

コマンドの例を示します。
$ fpga_crossgen lib_rtl_spec.xml --emulation_model lib_rtl_model.cpp --source sycl --target
sycl -o lib_rtl.o

4.8.15.3. オブジェクト・ファイルをライブラリー・ファイルにパッケージ化
ほかの開発者がライブラリーをプロジェクトに組み込んで、ライブラリー内のオブジェクトに含まれる関数を呼び出すことができるように、オブジェクト・ファイルをライブラリー・ファイルに集約します。オブジェクト・ファイルをライブラリーとしてパッケージ化するには、fpga_libtool コマンドを使用します。
オブジェクト・ファイルをライブラリーにパッケージ化する前に、ライブラリーに含めるすべてのオブジェクト・ファイルのパス情報を確認してください。
ライブラリーにパッケージ化するすべてのオブジェクトは、同じバージョンでなければなりません。fpga_libtool コ
マンドは、オペレーティング・システム固有のアーカイブファイル (Linux* では .a、Windows* では .lib) のライブラリーを作成します。使用するオペレーティング・システムと異なるオペレーティング・システムで実行されているインテル®
HLS 設計製品と一緒に使用することはできません。
次のコマンドを使用してライブラリー・ファイルを作成します。
$ fpga_libtool file1 file2 ... fileN --target sycl --create <library_name>

コマンド・パラメーターは次のように定義されます。
ライブラリー・ファイルのコマンド・パラメーター
パラメーター
file1 file2 ... fileN--target sycl--create <library_name>

説明
ライブラリーに含めるオブジェクト・ファイルを指定できます。
このライブラリーはカーネル開発を対象とします。例えば、sycl オプションでは、--target は、インテル® oneAPI DPC++/C++ コンパイラーで使用するライブラ
リーを準備します。
ライブラリー・アーカイブ・ファイルの名前を指定できます。Linux* プラットフォーム
向けのライブラリーでは、ファイル拡張子 .a を指定します。

コマンドの例を示します。
$ fpga_libtool lib_rtl.o --target sycl --create lib.a

このコマンドは、RTL ソースコードから作成されたオブジェクトを lib.a という SYCL* ライブラリーにパッケージ化
します。

145

インテル® oneAPI プログラミング・ガイド

注: 追加情報については、インテル® oneAPI サンプルブラウザーにリストされている FPGA チュー
トリアルのサンプル「ライブラリーを使用」(Linux* | Windows* (英語)) を参照するか、Github* のサンプルコードにアクセスしてください。

4.8.15.4. 静的ライブラリーの使用
次のコマンドに示すように、コンパイルコマンドにはソースファイルとともに静的ライブラリーを指定できます。
$ icpx -fsycl -fintelfpga main.cpp lib.a

注:
RTL で実装した関数を利用するには、コンパイラーが関数を動的にリンクできるよう、ソースコー
ドで宣言する必要があります。次に例を示します。
SYCL_EXTERNAL extern "C" void foo()

4.8.15.5. RTL ライブラリーのオブジェクト・マニフェスト・ファイルの構文
この節では、倍精度平方根関数を実装する RTL ライブラリーの単純なオブジェクト・マニフェスト・ファイルの構文について説明します。RTL ライブラリーは、Verilog ラッパーを使用して VHDL に実装されています。
次のオブジェクト・マニフェスト・ファイル・ファイルは、my_sqrtfd (2 行目) という SYCL* ヘルパー関数を実装する
my_fp_sqrt_double (2 行目) の RTL ライブラリー向けです。
1. <RTL_SPEC>
2.
<FUNCTION name="my_sqrtfd" module="my_fp_sqrt_double">
3.
<ATTRIBUTES>
4.
<IS_STALL_FREE value="yes"/>5.
<IS_FIXED_LATENCY value="yes"/>
6.
<EXPECTED_LATENCY value="31"/>
7.
<CAPACITY value="1"/>8.
<HAS_SIDE_EFFECTS value="no"/>9.
<ALLOW_MERGING value="yes"/>10.
</ATTRIBUTES>
11.
<INTERFACE>
12.
<AVALON port="clock" type="clock"/>
13.
<AVALON port="resetn" type="resetn"/>
14.
<AVALON port="ivalid" type="ivalid"/>
15.
<AVALON port="iready" type="iready"/>
16.
<AVALON port="ovalid" type="ovalid"/>
17.
<AVALON port="oready" type="oready"/>
18.
<INPUT port="datain" width="64"/>
19.
<OUTPUT port="dataout" width="64"/>
20.
</INTERFACE>
21.
<C_MODEL>
22.
<FILE name="c_model.cl" />23.
</C_MODEL>24.
<REQUIREMENTS>
25.
<FILE name="my_fp_sqrt_double_s5.v" />146

インテル® oneAPI プログラミング・ガイド

26.
<FILE name="fp_sqrt_double_s5.vhd" />27.
</REQUIREMENTS>
28.
<RESOURCES>
29.
<ALUTS value="2057"/>
30.
<FFS value="3098"/>
31.
<RAMS value="15"/>32.
<MLABS value="43"/>
33.
<DSPS value="1.5"/>
34.
</RESOURCES>
35.
</FUNCTION>
36. </RTL_SPEC>

オブジェクト・マニフェスト・ファイルの要素と属性
XML 要素RTL_SPECFUNCTIONATTRIBUTES

説明
オブジェクト・マニフェスト・ファイルの最上位要素。このような最上位要素は、ファイル内に 1 つだ
け存在できます。上記の例の RTL_SPEC という名前は慣例的なものであり、ファイル固有の意味はありません。
RTL ライブラリーが実装する SYCL* 関数を定義する要素。FUNCTION 要素内の name 属性には、関数名を指定します。
複数の FUNCTION 要素を持つことができ、それぞれが SYCL* カーネルから呼び出すことができる
異なる関数を宣言します。異なるパラメーターを指定することで、同じ RTL ライブラリーに複数の関数を実装できます。
RTL ライブラリーのさまざまな特性 (レイテンシーなど) を記述するほかの XML 要素を含む要素。
サンプル RTL ライブラリーは、値が 32 の WIDTH という名前の 1 つの PARAMETER 設定を使用します。その他の ATTRIBUTES 固有の要素の詳細については、以下の ATTRIBUTES セクションのXML 要素を参照してください。

注: 異なるライブラリーに対して複数の SYCL* ヘルパー関数を作成する場
合、または同じ RTL ライブラリーを異なる PARAMETER 設定で使用する場合
は、関数ごとに個別の FUNCTION 要素を作成する必要があります。
INTERFACE

RTL ライブラリーのインターフェイスを記述するほかの XML 要素を含む要素。サンプルのオブジェ
クト・マニフェスト・ファイルは、すべての RTL ライブラリーが提供する必要がある Avalon ストリー
ミング・インターフェイス信号 (つまり、clock、resetn、ivalid、iready、ovalid、および
oready) を示しています。resetn 信号はアクティブ low です。同期性はターゲットデバイスで依存します。
インテル® Arria® 10、Cyclone® V、インテル® Cyclone® 10 GX、および Cyclone® 10 LP:
resetn 信号はクロック信号と非同期です。

インテル® Stratix® 10 およびインテル® Agilex® 7: resetn 信号はクロック信号と同期します。リセット信号のタイミングの詳細については、「インテル® Stratix® 10 およびインテル® Agilex®7 のストールフリーおよびストール可能な RTL* ライブラリーの設計固
有のリセット要件」 (英語) を参照してください。

注: 信号名は、.xml ファイルで指定されたものと一致する必要があります。
信号名が一致しない場合、ライブラリーの作成中にエラーが発生します。

147

インテル® oneAPI プログラミング・ガイド

XML 要素C_MODELREQUIREMENTS

説明
関数の SYCL* モデルを実装する 1 つ以上のファイルを指定する要素。モデルはエミュレーションでのみ使用されます。ただし、ライブラリー・ファイルを作成する場合、C_MODEL 要素と関連ファイルが存在する必要があります。
1 つ以上の RTL リソースファイル (つまり、.v、.sv、.vhd、.hex、および .mif) を指定する要素。
これらのファイルへの指定パスは、オブジェクト・マニフェスト・ファイルの場所に関連しています。
各 RTL リソースファイルは、SYCL* システム全体に対応する Platform Designer コンポーネントの一部になります。

注: SYCL* ライブラリーの機能は、.qip ファイルをサポートしていません。サ
ポートされていないリソース・ファイル・タイプを含むライブラリーを使用して
SYCL* カーネルをコンパイルすると、インテル® oneAPI DPC++/C++ コンパ
イラーはエラーを生成します。
RESOURCES

4.8.15.5.1.

RTL ライブラリーが使用する FPGA リソースを指定するオプションの要素。この要素を指定しない
場合、RTL ライブラリーが使用する FPGA リソースはデフォルトでゼロになります。

ATTRIBUTES 向けの XML 要素

RTL ライブラリーのオブジェクト・マニフェスト・ファイルには、ライブラリーの特性を設定に使用できる XML 要素とATTRIBUTES があります。

注: IS_STALL_FREE と EXPECTED_LATENCY を除いて、すべての要素には安全値があります。
属性に指定する値が明確でない場合、安全な値に設定してください。安全な値を使用するライブラ
リーでカーネルをコンパイルすると、ハードウェアは機能します。ただし、ハードウェアは実際のサイズよりも大きなことがあります。

RTL ライブラリーのオブジェクト・マニフェスト・ファイルの ATTRIBUTES 要素に関連付けられた XML 要素
XML 要素IS_STALL_FREE

説明
すべてのストールと有効な信号を適切に処理するようコンパイラーに指示します。この場合、コンパイラーは RTL ライブラリーの周辺にストールロジックを生成しないことで、エリアを節約できます。
IS_STALL_FREE を "yes" に設定して、ライブラリーが内部でストールを生成せず、受信ス
トールを適切に処理できないことを示します。ライブラリーはストール入力を単純に無視します。IS_STALL_FREE を "no" に設定した場合、ライブラリーはすべてのストールおよび有効なシグナルを適切に処理する必要があります。

注: IS_STALL_FREE を "yes" に設定する場合、IS_FIXED_LATENCY
も "yes" に設定する必要があります。また、RTL ライブラリーが内部状態を持つ場合、ivalid=0 入力を適切に処理する必要があります。
IS_STALL_FREE 設定が正しくないと、ハードウェアは誤った結果を生
成します。

148

インテル® oneAPI プログラミング・ガイド

XML 要素IS_FIXED_LATENCY説明
RTL ライブラリーに固定レイテンシーがあるかどうかを示します。
RTL ライブラリーが出力を計算するために既知数のクロックサイクルを常に必要とする場合
は、IS_FIXED_LATENCY に yes を設定します。EXPECTED_LATENCY 要素に割り当てる値
は、クロックサイクル数を指定します。
IS_FIXED_LATENCY の安全な値は "no" です。IS_FIXED_LATENCY="no" に設定する場
合、EXPECTED_LATENCY 値は少なくとも 1 である必要があります。

注: 特定のライブラリーには、IS_FIXED_LATENCY を "yes" に、
IS_STALL_FREE を "no" に設定できます。このようなライブラリー
は、一定数のクロックサイクルで出力を生成し、ストール信号を適切に処理します。
EXPECTED_LATENCY

RTL ライブラリーの予想レイテンシーを指定します。
IS_FIXED_LATENCY を "yes" に設定すると、EXPECTED_LATENCY 値はライブラリー内のパイプライン・ステージの数を示します。この場合、この値はライブラリーの正確なレイテンシーになるように設定する必要があります。そうしないと、コンパイラー不正なハードウェアを生成します。

CAPACITY

レイテンシーが可変のライブラリーでは場合、コンパイラーはこのライブラリーのパイプラインのバランスを、EXPECTED_LATENCY で指定された値に合わせます。iready などの信号を停止して使用する必要があるライブラリーでは、EXPECTED_LATENCY 値を少なくとも 1 に設定します。指定された値と実際のレイテンシーは異なる場合があり、パイプライン内のストール数に影響する可能性があります。ただし、ハードウェアは適切です。
ライブラリーが同時に処理できる複数入力の数を指定します。IS_STALL_FREE="no" および
IS_FIXED_LATENCY="no" に設定する場合、CAPACITY 値を指定する必要があります。それ以外では CAPACITY 値を指定する必要はありません。
CAPACITY が EXPECTED_LATENCY より小さい場合、コンパイラーは必要に応じて、このライ
ブラリーの後に容量バランス FIFO バッファーを自動的に挿入します。

HAS_SIDE_EFFECTSCAPACITY の安全な値は 1 です。
RTL ライブラリーに副作用があるかどうかを示します。内部状態を持つライブラリーや外部メ
モリーと通信するライブラリーは、副作用のあるライブラリーの例です。
HAS_SIDE_EFFECTS を "yes" に設定して、ライブラリーに副作用があることを示します。
HAS_SIDE_EFFECTS を "yes" にすると、最適化によって副作用のあるライブラリーへの呼び出しが削除されなくなります。
副作用 (つまり、IS_STALL_FREE="yes" および HAS_SIDE_EFFECTS="yes") のあるス
トールフリー・ライブラリーは、無効なデータを受け取る可能性があるため、ivalid=0 入力のケースを適切に処理する必要があります。
HAS_SIDE_EFFECTS の安全な値は "yes" です。

149

インテル® oneAPI プログラミング・ガイド

XML 要素ALLOW_MERGING説明
RTL ライブラリーの複数のインスタンスをマージするようコンパイラーに指示します。ライブラ
リーの複数のインスタンスをマージ可能にするには、ALLOW_MERGING を "yes" に設定します。インテルは ALLOW_MERGING を "yes" に設定することを推奨しています。
ALLOW_MERGING の安全な値は "no" です。

注: ライブラリーを HAS_SIDE_EFFECTS="yes" とマークしてもマージは避けられません。
PARAMETER

RTL ライブラリー・パラメーター値を指定します。
PARAMETER 属性:


name: RTL ライブラリー・パラメーターの名前を指定します。

value: パラメーターを 10 進数値で指定します。



type: RTL ライブラリーのパラメーター値として使用されるシステム・パラメーターを指定します。ボード・サポート・パッケージで SYCL* グローバルメモリー向けに構成され たメモ リー レンジを アド レス 指定する のに必要な 、 Avalon メモ リーバス 幅を
bspaddresswidth パラメーターで指定します。

注: value または type 属性を使用して、RTL ライブラリー・パラメー
ター値を指定できます。

4.8.15.5.2.

INTERFACE 向けの XML 要素

SYCL* ライブラリーの RTL ライブラリーのオブジェクト・マニフェスト・ファイルには、RTL ライブラリーのインターフェ
イス (例: Avalon ストリーミング・インターフェイス) を指定するために定義できる XML 要素が INTERFACE 配下にあります。
RTL ライブラリーのオブジェクト・マニフェスト・ファイルの ATTRIBUTES 要素に関連付けられた XML 要素
XML 要素INPUT

説明
RTL ライブラリーの input パラメーターを指定します。
INPUT 属性


port: RTL ライブラリーのポート名を指定します。

width: ポートの幅をビット数で指定します。

入力パラメーターが連結されて、入力ストリームが形成されます。

注: 構造体や配列の集約データ構造は、入力パラメーターではサポートされていま
せん。

150

インテル® oneAPI プログラミング・ガイド

XML 要素OUTPUT説明
RTL ライブラリーの output パラメーターを指定します。
OUTPUT 属性
port: RTL ライブラリーのポート名を指定します。

width: ポートの幅をビット数で指定します。

入力ストリームからの戻り値は、出力ストリームの output パラメーターを介して送られます。

注: 構造体や配列の集約データ構造は、入力パラメーターではサポートされていません。

4.8.15.5.3.

RESOURCES 向けの XML 要素

SYCL* ライブラリーの RTL ライブラリーのオブジェクト・マニフェスト・ファイルには、ライブラリーの FPGA リソースの利用率指定に定義できるオプション要素が RESOURCES 配下にあります。特定の要素を指定しないと、デフォルト値はゼロです。
外部メモリーアクセスをサポートする追加の XML 要素
XML 要素
ALUTS
FFS
RAMS
DSPS
MLABS

説明
ライブラリーが使用する組み合わせ可能なルックアップ・テーブル (ALUT) の数を指定します。
ライブラリーが使用する専用ロジックレジスターの数を指定します。
ライブラリーが使用するブロック RAM の数を指定します。
ライブラリーが使用するデジタル信号処理 (DSP) ブロックの数を指定します。
ライブラリーが使用するメモリー・ロジック・アレイ (MLAB) の数を指定します。それぞれの MLAB は 10個の ALM を消費するため、この値はメモリーに使用されるアダプティブ・ロジック・モジュール (ALM) の数を 10 で割った値になります。

4.8.15.6. RTL サポートの制限と制約
SYCL* カーネル内で使用する RTL モジュールを作成する場合、RTL モジュールが次の制限下で動作することを確認する必要があります。



RTL モジュールは、単一入力の Avalon ストリーミング・インターフェイスを使用しなければなりません。つまり、準備ができた有効なロジックのペアすべての入力をコントロールする必要があります。必要とする Avalon スト
リーミング・インターフェイス・ポートを提供するオプションもありますが、RTL モジュールをストールフリーとして宣言する必要があります。この場合、インテル® oneAPI DPC++/C++ コンパイラーがモジュールのラッパーを作成するため、特定のストール動作を実装する必要はありません。詳細については、「RTL モジュールのオブジェ
クト・マニフェスト・ファイル構文」 (英語) を参照してください。

151インテル® oneAPI プログラミング・ガイド

注: RTL モジュールが内部状態を持つ場合、無効な信号を適切に処理する必要があります。詳細は、「ストールフリーの RTL」 (英語) を参照してください。



RTL モジュールは、カーネルクロック周波数に関係なく適切に動作しなければなりません。

RTL モジュールは、外部 I/O 信号に接続できません。すべての入力と出力信号は SYCL* カーネルに由来する必要があります。



RTL モジュールには、クロックポート、リセットポート、および Avalon ストリーミング・インターフェイスの入力
ポートと出力ポート (ivalid、ovalid、iready、oready) が必要です。ここで示すようにポートに名前を付けます。

RTL モジュールは、スタンドアロンの SYCL* カーネルとしては動作できません。RTL モジュールはヘルパー関数としてのみ使用でき、カーネルのコンパイル中に SYCL* カーネルと統合できます。



RTL モジュールのインスタンス化に対応するすべての関数呼び出しは、ほかのインスタンスからに独立しており、ハードウェアの共有もありません。



カーネルコードを SYCL* ライブラリー・ファイルに組み込んではなりません。カーネルコードを SYCL* ライブラ
リー・ファイルに組込むと、オフライン・コンパイラーはエラーメッセージを出力します。ヘルパー関数はライブラ
リー・ファイルに組込んでも問題ありません。



RTL コンポーネントは、すべての入力を同時に受信する必要があります。単一の無効な入力は、すべての入力に有効なデータが含まれていることを意味します。



RTL モジュール・パラメーターは、<RTL モジュール記述ファイル名>.xml 仕様ファイルでのみ設定でき、
SYCL* カーネルソースでは設定できません。複数のパラメーターで同じ RTL モジュールを利用するには、パラメーターの組み合わせごとに個別の FUNCTION タグを作成します。



SYCL* カーネルコードを介してのみ RTL モジュールに入力データを渡すことができます。参照渡し、構造体、またはチャネルを介してデータ入力を RTL モジュールに渡してはなりません。チャネルデータの場合、抽出されたスカラーデータを渡します。

注: 参照渡しまたは構造体を介してデータ入力を RTL モジュールに渡すと、オフラインコンパイルで致命的エラーが発生します。



ライブラリーがデバッグ情報を持たない場合、デバッガー (Linux* の GDB など) はエミュレーション中にライブ
ラリー関数にステップインできません。しかし、ライブラリーデバッグ情報を持つ/持たないにかかわりなく、最適化レポートとエリアレポートはライブラリー内のそれぞれのコード行にマップされません。

RTL モジュールのソースファイル名は、インテル® oneAPI DPC++/C++ コンパイラーの IP ファイル名と同じにはできません。RTL モジュールのソースファイルとコンパイラーの IP ファイルは、<カーネルファイル名>/
system/synthesis/submodules ディレクトリーに保存されます。名前が競合すると、ディレクトリー内の既存のコンパイラー IP ファイルが RTL モジュールのソースファイルで上書きされます。



コンパイラーは .qip ファイルをサポートしません。そのため、.qip ファイルを自身で解析して、RTL ファイルのフラットリストを作成する必要があります。

152

インテル® oneAPI プログラミング・ガイド

ヒント: 単独では正しく動作するにもかかわらず、SYCL* カーネルの一部として適切に機能しない
RTL モジュールをデバッグするのは非常に困難です。<RTL モジュール記述ファイル名>.xml
ファイルの ATTRIBUTES 要素 (英語) 下にあるすべてのパラメーターを確認してください。



すべてのコンパイラーのエリア推測ツールは、RTL モジュールのエリアが 0 であると想定します。現在、コンパイ
ラーは RTL モジュールのエリアモデルを指定できません。

4.8.15.7. インテル® Stratix® 10 およびインテル® Agilex® 7 の設計固有のストールフリーおよびストール可能な RTL ライブラリーのリセット要件
インテル® Stratix® 10 およびインテル® Agilex® 7 設計向けの RTL ライブラリーを作成する場合、ライブラリーが特定ロジックのリセット要件を満たすことを確認してください。
4.8.15.7.1.

ストールフリー RTL ライブラリーのリセット要件

ストールフリーの RTL ライブラリーは、インテル® oneAPI DPC++/C++ コンパイラーがストールロジックを最適化できる固定レイテンシーのライブラリーです。これは、有効なデータを受け入れ、最後に ready_in 信号を持ちません。
インテル® Stratix® 10 の設計用にストールフリー RTL ライブラリーを作成する場合、同期クリア信号のみを使
用します。



ストールフリー RTL ライブラリーへリセット信号をアサートした後、ライブラリーは 15 クロックサイクル以内に動作する必要があります。リセット信号がライブラリー内でパイプライン処理される場合、この要件から、リセットのパイプライン処理は 15 ステージ以内に制限されます。

4.8.15.7.2.

ストール可能な RTL ライブラリーのリセット要件

ストール可能な RTL ライブラリーのレイテンシーは可変であり、正しく機能するには背圧がある入力や出力インターフェイスに依存します。
インテル® Stratix® 10 の設計用にストール可能な RTL ライブラリーを作成する場合、同期クリア信号のみを使
用します。



ストール可能な RTL ライブラリーへリセット信号をアサートした後、ライブラリーは 40 クロックサイクル以内に oready および ovalid インターフェイス信号をアサート解除する必要があります。



ストールフリー RTL ライブラリーへリセット信号を解除した後、ライブラリーは 40 クロックサイクル以内に動作する必要があります。ライブラリーは、oready インターフェイス信号をアサートすることで、準備ができていることを通知します。

153インテル® oneAPI プログラミング・ガイド

4.8.16 サードパーティーのアプリケーションで SYCL* 共有ライブラリーを使用
インテル® oneAPI DPC++/C++ コンパイラーを使用して、SYCL* コードを C 標準に準拠する共有ライブラリー (Linux*
では .so ファイル、Windows* では .dll ファイル) にコンパイルします。次に、ほかのサードパーティーのコードからこのライブラリーを呼び出して、任意のプログラミング言語から高速化された関数にアクセスできます。
サードパーティー・アプリケーションで使用するため、共有ライブラリー・ファイルにパッケージ化された SYCL* 関数

サードパーティー・アプリケーションで共有ライブラリーを使用するには、次の手順を実行します。
1.

共有ライブラリーのインターフェイスを定義します。

2.

Linux* または Windows* でそれぞれ共有ライブラリー・ファイル を作成します。

3.

共有ライブラリーを使用します。

4.8.16.1. 共有ライブラリーのインターフェイスを定義
C 標準共有ライブラリーと SYCL* コード間のインターフェイスを定義することを推奨します。インターフェイスにはエク
スポートする関数と、SYCL* コードとの関係を含める必要があります。共有ライブラリーをインクルードする関数の前にextern "C" を記述します。

注: extern "C" プリフィクスを付けない場合、関数は共有ライブラリーにマングルされた名前で表示されます。

154

インテル® oneAPI プログラミング・ガイド

vector_add 関数を含む次の例について考えてみます。
extern "C" int vector_add(int *a, int *b, int **c, size_t vector_len) {// 対象とするデバイスのデバイスセレクターを作成します#if FPGA_EMULATOR// インテル拡張: FPGA カードを搭載しないシステム向けの FPGA エミュレーター
auto selector = sycl::ext::intel::fpga_emulator_selector_v;#elif FPGA_SIMULATOR// インテル拡張: FPGA カードを搭載しないシステム向けの FPGA シミュレーター
auto selector = sycl::ext::intel::fpga_simulator_selector_v;#elif FPGA_HARDWARE// インテル拡張: FPGA カードを搭載しないシステム向けの FPGA
auto selector = sycl::ext::intel::fpga_selector_v;#else// デフォルトのデバイスセレクターは、最もパフォーマンスが高いデバイスを選択します。
auto selector = default_selector_v;#endiftry {queue q(d_selector, exception_handler);// SYCL* コードのインターフェイス:// SYCL* のベクトル加算
VectorAddKernel(q, a, b, c, vector_len);} catch (exception const &e) {std::cout << "An exception is caught for vector add.\n";return -1;}
return 0;}

4.8.16.2. Linux* の共有ライブラリー・ファイルを作成
Linux* システムでは、次の手順で共有ライブラリー・ファイルを作成します。
1.

デバイスコードを個別にコンパイルします。

$ icpx -fsycl -fPIC –fintelfpga –fsycl-link=image [kernel src files] –o <hw image name>-Xshardware

オプションは以下を示します。

‐ fPIC: コンパイラーがデバイスイメージのホスト部分に対し位置独立コードを生成するか決定します。オプション -fPIC は、完全なシンボルのプリエンプションを指定します。グローバルシンボル定義とグローバ
ルシンボル参照は、特に指定されない限りデフォルトの (プリエンプト可能な) 可視性を取得します。共有
オブジェクトを作成する場合、このオプションを使用する必要があります。このオプションは -fpic とすることもできます。

注: 共有ライブラリー内のポインターがローカルアドレスではなくグローバルアドレスを参照する
ようにするため PIC が必要です。

155インテル® oneAPI プログラミング・ガイド

2.

‐fintelfpga: FPGA デバイスをターゲットにします。

‐

fsycl-link=image: インテル® oneAPI DPC++/C++ コンパイラーに、FPGA で使用するデバイスバイ
ナリーの部分リンクを行うように指示します。

‐

Xshardware: エミュレーターではなくハードウェア向けにコンパイルします。

ホストコードを個別にコンパイルします。

$ icpx -fsycl –fPIC –fintelfpga <host src files> -o <host image name> -c -DFPGA=1

オプションは以下を示します。
‐

3.

DFPGA=1: コンパイラーマクロ FPGA を 1 に設定します。これは、ターゲットデバイスを変更するためデバ
イスセレクターで使用されます (これを可能にするには対応するホストコードが必要です)。デバイスセレク
ターを FPGA に設定することもできるため、これはオプションです。詳細については、「FPGA デバイスセレ
クター」を参照してください。

ホストとデバイスのイメージをリンクしてバイナリーを作成します。

$ icpx -fsycl –fPIC –fintelfpga –shared <host image name> <hw image name> -o lib<libraryname>.so

オプションは以下を示します。
‐

shared: 出力する共有ライブラリー(.so ファイル)‐

出力ファイル名: GCC タイプのコンパイラーは lib プリフィクス。詳細については、「Linux* 上の GCC との共有ライブラリー」 (英語) を参照。以下に例を示します。

$ gcc -Wall -fPIC -L. -o out.a -l<library name>.so

注: 上記の複数ステップの手順の代わりに、単一ステップコンパイルで共有ライブラリーを作成することもできます。ただし、テスト用途で実行ファイル (a.out など) をビルドする場合、またはSYCL* コードや C インターフェイスに変更を加える場合は、完全コンパイルを行う必要があります。

4.8.16.3. Windows* の共有ライブラリー・ファイルを作成
Windows* システムでは、次の手順でライブラリー・ファイルを作成します。

156

インテル® oneAPI プログラミング・ガイド

注:

同じプロジェクト・プロパティーで新しい構成を作成することを推奨します。これにより、アプリ
ケーションをビルドする際に、プロジェクトの構成タイプを変更しなくても済みます。
インテル® PAC (インテル® Arria® 10GX FPGA 搭載版) およびインテル® FPGA PAC D5005(以前のインテル® PAC (インテル® Stratix® 10 SX FPGA 搭載版)) 向けのデフォルトのインテル® oneAPI ベース・ツールキットおよび FPGA アドオンによる Windows* ライブラ
リーの作成は、FPGA エミュレーションでのみサポートされます。Windows* 向けのカスタム・プラットフォームの FPGA ハードウェア・コンパイルについては、ボードベンダーに問い合わ
せてください。

1.

Microsoft* Visual Studio* で、[プロジェクト] > [プロパティ] に移動します。プロジェクトの [プロパティペー
ジ] ダイアログボックスが開きます。

2.

[構成のプロパティ] > [全般] > [プロジェクトのデフォルト] > [構成の種類] オプションで、ドロップダウン・リス
トから [ダイナミック ライブラリー(.dll)] を選択します。

[プロジェクトのプロパティ] ダイアログボックス

3.

[OK] をクリックしてダイアログを閉じます。

プロジェクトは自動的にビルドされ、ダイナミック・ライブラリー (.dll) が生成されます。

157

インテル® oneAPI プログラミング・ガイド

4.8.16.4. 共有ライブラリーを使用
ここで示す手順は、使用する言語またはコンパイラーによって異なる可能性があります。詳細については、使用する言語の仕様を参照してください。「Linux* 上の GCC と共有ライブラリー」 (英語) を参照してください。
通常、共有ライブラリーを使用するには次の手順を実行します。
1.

サードパーティーのホストコードで共有ライブラリー関数を呼び出します。

2.

コンパイル中にホストコードを共有ライブラリーにリンクします。

3.

ライブラリー・ファイルが検出できることを確認します。次に例を示します。

$ export LD_LIBRARY_PATH=<lib file location>:$LD_LIBRARY_PATH

以下に共有ライブラリーの利用例を示します。
共有ライブラリーの利用例

158インテル® oneAPI プログラミング・ガイド

4.8.17 IDE での FPGA ワークフロー
インテル® oneAPI ツールは、サードパーティー統合開発環境 (IDE) と統合して、Linux* (Eclipse*) および Windows*(Visual Studio*) でソフトウェア開発にシームレスな GUI 環境を提供します。詳細は、「サードパーティー IDE でのインテル® oneAPI ツールキットの FPGA ワークフロー」 (英語) を参照してください。
Linux* で Visual Studio* Code を使用した FPGA の開発については、「インテル® oneAPI ツールキットの FPGA 開発(Linux* で Visual Studio* Code 向けのサンプルブラウザーを使用」 (英語) を参照してください。

159

インテル® oneAPI プログラミング・ガイド

5

API ベースのプログラミング

最適化されたアプリケーション向けの特殊 API を提供することで、プログラミング・プロセスを簡素化するインテル®
oneAPI ツールキットのライブラリーを利用できます。この章では、サンプルコードを含むライブラリーの基本的な情報と、特定の利用ケースでどのライブラリーが最も有効であるか判断するのに役立つ情報を提供します。利用可能な APIなど、それぞれのライブラリーの詳細は、ライブラリーのドキュメントをご覧ください。
oneAPI ツールキットのライブラリー
ライブラリーインテル® oneDPL
インテル® oneMKL
インテル® oneTBB
インテル® oneDAL
インテル® oneCCL
インテル® oneDNN

インテル® oneVPL

使用法
ハイパフォーマンスの並列アプリケーションで使用します。
高度に最適化および並列化された数学ルーチンをアプリケーショ
ンで利用できます。
マルチコア CPU でのインテル® TBB ベースの並列処理と、アプリ
ケーションでの SYCL* デバイス高速並列処理を組み合わせます。
ビッグデータ解析アプリケーションと分散計算を高速化します。
ディープラーニングとマシンラーニングのワークロードを処理するアプリケーションで使用します。
インテル® アーキテクチャー・ベースのプロセッサーおよび
インテル® プロセッサー・グラフィックス向けに最適化された、ニューラル・ネットワークを使用するディープラーニング・アプリ
ケーションで使用します。
アプリケーションのビデオ処理を高速化します。

5.1 インテル® oneAPI DPC++ ライブラリー (インテル® oneDPL)
インテル® oneDPL は、インテル® oneAPI DPC++/C++ コンパイラーと連携して生産性の高い API を提供します。これらの API を使用して、ハイパフォーマンスな並列アプリケーション向けに、デバイス全体で SYCL* プログラミングの労力を最小限に抑えることができます。
インテル® oneDPL は次のコンポーネントで構成されます。


Parallel STL‐

Parallel STL の使用手順‐

マクロライブラリー・クラスと関数の追加セット (このドキュメントでは拡張 API と呼びます)。
‐

並列アルゴリズム‐

イテレーター‐

関数オブジェクト・クラス‐

範囲ベースの API

160

インテル® oneAPI プログラミング・ガイド



テスト済みの標準 C++ API乱数ジェネレーター

5.1.1 インテル® oneDPL ライブラリーの使い方
インテル® oneDPL を使用するには、インテル® oneAPI ベース・ツールキット (英語) をインストールします。
Patallel STL と API 拡張を使用するには、必要なヘッダーファイルをソースコードでインクルードします。すべてのインテル® oneDPL ヘッダーファイルは oneapi/dpl ディレクトリーにあります。それらをインクルードするには、#include <oneapi/dpl/…> を使用します。インテル® oneDPL には、大部分のクラスと関数対する名前空間
oneapi::dpl があります。
テスト済みの C++ 標準 API を使用するには、対応する C++ ヘッダーファイルをインクルードし、std 名前空間を使用する必要があります。

5.1.2 インテル® oneDPL サンプルコード
インテル® oneDPL のサンプルコードは、https://github.com/oneapi-src/oneAPI-samples/tree/master/Libraries/
oneDPL (英語) から入手できます。それぞれのサンプルには、ビルド手順が説明された Readme が含まれています。
それぞれのサンプルには、ビルド手順が説明された Readme が含まれています。

5.2 インテル® oneAPI マス・カーネル・ライブラリー (インテル® oneMKL)
インテル® oneMKL は、最大限のパフォーマンスを必要とするアプリケーション向けに最適化され、広範囲に並列化されたルーチンの数学計算ライブラリーです。インテル® oneMKL には、C/Fortran プログラミング言語インターフェイスを備えた CPU アーキテクチャー向けのインテル® マス・カーネル・ライブラリー (インテル® MKL) のハイパフォーマンス
な最適化が含まれており、各種 CPU アーキテクチャーとインテル® グラフィックス・テクノロジーでパフォーマンスを高める SYCL* インターフェイスが追加されています。インテル® oneMKL は、BLAS および LAPACK 線形代数ルーチン、
高速フーリエ変換、ベクトル数学関数、乱数生成関数、その他の機能を提供します
OpenMP* オフロードを使用して、インテル® GPU で標準のインテル® oneMKL 計算を実行できます。詳細については、「C インターフェイスの OpenMP* オフロード」 (英語) および「Fortran インターフェイスの OpenMP* オフロード」 (英語) を参照してください。
CPU と GPU アーキテクチャー向けに最適化された新しい SYCL* インターフェイスには、次のような計算機能が追加されています。


BLAS と LAPACK 密線形代数ルーチン



スパース BLAS スパース線形代数ルーチン



乱数生成器 (RNG)
161

インテル® oneAPI プログラミング・ガイド

ベクトルの数学演算用に最適化されたベクトル数学 (VM) ルーチン

高速フーリエ変換 (FFT)

機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneMKL のウェブサイト (英語) をご覧ください。インテル® oneMKL をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償オプショ
ンとして優先サポート (英語) を利用できます。インテルのコミュニティー・サポートについては、インテル® oneMKL
フォーラム (英語) を参照してください。コミュニティーがサポートするオープンソース・バージョンについては、oneMKL
GitHub* (英語) のページを参照してください。
次の表に、oneMKL サイトの違いを示します。
oneMKL の oneAPI 仕様 (英語)

パフォーマンスに優れた数学ライブラリー関数の DPC++ インターフェイス
を定義します。oneMKL 仕様は、oneMKL 実装よりも頻繁に更新されます。

oneAPI マス・カーネル・ライブラリー (oneMKL)
インターフェイス・プロジェクト (英語)

oneMKL 仕様のオープンソース実装です。このプロジェクトは、oneMKL 仕様で文書化された DPC++ インターフェイスをあらゆる数学ライブラリーに実装し、各種ターゲット・ハードウェアでの動作を実証することを目標としています。ここで提供される実装は、まだ完全ではない可能性があり、時間をかけて完全な仕様を構築することを目標としています。複数のハードウェア・
ターゲットやほかの数学ライブラリーにサポートを拡張するため、コミュニティーにこのプロジェクトへの貢献を呼び掛けています。

インテル® oneAPI マス・カーネル・ライブラリー(インテル® oneMKL) プロジェクト (英語)

oneMKL 仕様のインテル製品実装 (DPC++ インターフェイスを使用) および同等の機能を提供する C と Fortran インターフェイスは、インテル® oneAPI
ベース・ツールキットの一部として提供されます。インテル® CPU およびインテル® GPU ハードウェア向けに高度に最適化されています。

5.2.1 インテル® oneMKL の使い方
SYCL* インターフェイスを使用する場合、考慮すべきことがあります。
インテル® oneMKL は、インテル® oneAPI DPC++/C++ コンパイラーおよびインテル® oneDPL に依存しています。アプリケーションは、インテル® oneAPI DPC++/C++ コンパイラーでビルドされ、SYCL* ヘッダーを利用しており、DPC++ リンカーを使用してインテル® oneMKL とリンクされている必要があります。

インテル® oneMKL の SYCL* インターフェイスは、入力データ (ベクトル、行列など) にデバイスのアクセスが可能な統合共有メモリー (USM) ポインターを使用します。

インテル® oneMKL の一部の SYCL* インターフェイスは、入力データ向けのデバイスへのアクセスが可能な
USM ポインターのほかに、sycl::buffer オブジェクトのアクセスもサポートしています。

インテル® oneMKL の SYCL* インターフェイスは、浮動小数点タイプに基づいてオーバーロードされます。標準
ライブラリー・タイプ std::complex<float>、std::complex<double> を使用する、単精度実数引数(float)、倍精度実数引数 (double)、半精度実数引数 (half)、および異なる精度の複素数引数を受け入れる汎用行列乗算 API があります。

インテル® oneMKL の 2 レベルの名前空間構造が SYCL* インターフェイスに追加されます。

162

インテル® oneAPI プログラミング・ガイド

インテル® oneMKL の 2 レベルの名前空間
名前空間
oneapi::mkl
oneapi::mkl::blas
oneapi::mkl::lapack
oneapi::mkl::rng
oneapi::mkl::stats
oneapi::mkl::vm
oneapi::mkl::dft
oneapi::mkl::sparse

説明
oneMKL の各種ドメイン間の共通要素が含まれます。
密ベクトル-ベクトル、行列-ベクトル、および行列-行列の低レベル操作が含まれます。
行列因数分解や固有値ソルバーなど高レベルの密行列演算が含まれます。
各種確率密度関数の乱数生成器が含まれます。
単精度および倍精度の多次元データセットの基本的な統計予測値が含まれます。
ベクトル数学ルーチンが含まれます。
高速フーリエ変換操作が含まれます。
スパース行列ベクトル乗算、スパース三角ソルバーなどのスパース行列演算が含まれます。

5.2.2 インテル® oneMKL サンプルコード
SYCL* インターフェイスとインテル® oneMKL の一般的なワークフローを示すため、次のサンプルコードは、GPU デバ
イスで倍精度の行列-行列乗算を行います。

注: 次のコード例では、行中のコメントで示されるように、コンパイルと実行に追加のコードが必要です。

1. // 標準 SYCL* ヘッダー
2. #include <CL/sycl.hpp>
3. // STL クラス
4. #include <exception>
5. #include <iostream>
6. // インテル® oneMKL の SYCL*/DPC++ API の宣言
7. #include "oneapi/mkl.hpp"
8. int main(int argc, char *argv[]) {
9.
//
10.
// ユーザーは、m、n、k、ldA、ldB、ldC の設定と A、B、C 行列のデータを取得
11.
//
12.
// A、B、および C は、data() と size() メンバー関数を含む std::vector などのコンテナに格納します

13.
14.
15.
16.
17.
18.
19.
20.
21.
22.

//
//

25.
26.
27.

// 必須ではありませんが、システムが適切に構成されていない場合に参照できる有用な情報が提供されます
auto my_exception_handler = [](sycl::exception_list exceptions) {for (std::exception_ptr const& e : exceptions) {// GPU デバイスを作成
sycl::device my_device;
try {my_device = sycl::device(sycl::gpu_selector());}
catch (...) {std::cout << "Warning: GPU device not found! Using default device instead." <<std::endl;
23.
}
24.
// キューにアタッチする非同期例外ハンドラーを作成

163

インテル® oneAPI プログラミング・ガイド

28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.

try {
std::rethrow_exception(e);}catch (sycl::exception const& e) {std::cout << "Caught asynchronous SYCL exception:\n"<< e.what() << std::endl;}
catch (std::exception const& e) {std::cout << "Caught asynchronous STL exception:\n"<< e.what() << std::endl;}}};// 例外ハンドラーがアタッチされた gpu デバイスで実行キューを作成
sycl::queue my_queue(my_device, my_exception_handler);// デバイスとホスト間のオフロード向けに行列データの SYCL* バッファーを作成
sycl::buffer<double, 1> A_buffer(A.data(), A.size());
sycl::buffer<double, 1> B_buffer(B.data(), B.size());
sycl::buffer<double, 1> C_buffer(C.data(), C.size());// add oneapi::mkl::blas::gemm を実行キューに追加し、同期例外をキャッチ
exceptions
48.
try {
49.
using oneapi::mkl::blas::gemm;
50.
using oneapi::mkl::transpose;51.
gemm(my_queue, transpose::nontrans, transpose::nontrans, m, n, k, alpha,A_buffer, ldA, B_buffer,
52.
ldB, beta, C_buffer, ldC);
53.
}
54.
catch (sycl::exception const& e) {55.
std::cout << "\t\tCaught synchronous SYCL exception during GEMM:\n"56.
<< e.what() << std::endl;
57.
}
58.
catch (std::exception const& e) {59.
std::cout << "\t\tCaught synchronous STL exception during GEMM:\n"60.
<< e.what() << std::endl;
61.
}
62.
// 続行する前に、キャッチされた非同期例外を処理
63.
my_queue.wait_and_throw();
64.
//
65.
// 後処理の結果
66.
//
67.
// C バッファーからデータをアクセスし、C 行列の一部を出力
68.
auto C_accessor = C_buffer.template get_access<sycl::access::mode::read>();69.
std::cout << "\t" << C << " = [ " << C_accessor[0] << ", "70.
<< C_accessor[1] << ", ... ]\n";71.
std::cout << "\t[ " << C_accessor[1 * ldC + 0] << ", "72.
<< C_accessor[1 * ldC + 1] << ", ... ]\n";73.
std::cout << "\t[ " << "... ]\n";74.
std::cout << std::endl;
75.
76.
return 0;77. }(倍精度値) 行列 A (サイズ m * k)、B (サイズ k * n)、C (サイズ m * n) は、ホストマシンの配列 (次元 ldA、ldB、ldC) に格納されると想定します。スカラー (倍精度) alpha と beta を指定し、行列-行列乗算 (mkl::blas::gemm) を計算します。
C = alpha * A * B + beta * C
164

インテル® oneAPI プログラミング・ガイド

標準 SYCL* ヘッダーと対象の mkl::blas::gemm API 宣言を含むインテル® oneMKL DPC++ 固有ヘッダーをインクルードします。
// 標準 SYCL ヘッダー
#include <CL/sycl.hpp>// STL クラス#include <exception>#include <iostream>// インテル® oneMKL の SYCL/SYCL ++API の宣言#include "oneapi/mkl.hpp"

次に、通常のようにホストマシンで行列データをロードまたはインスタンス化し、GPU デバイスを作成して非同期例外
ハンドラーを作成し、最後に例外ハンドラーでデバイスキューを作成します。ホストで発生する例外は、標準 C++ 例外
メカニズムでキャッチできます。ただし、デバイスで発生する例外は非同期エラーとして見なされ、例外リストに保存されて、ユーザー定義の例外ハンドラーによって処理されます。
// GPU デバイスを作成
sycl::device my_device;
try {my_device = sycl::device(sycl::gpu_selector());}
catch (...) {std::cout << "Warning: GPU device not found! Using default device instead."<< std::endl;}// キューにアタッチする非同期例外ハンドラーを作成// 必須ではありませんが、システムが適切に構成されていない場合に参照できる有用な情報が提供されます
auto my_exception_handler = [](sycl::exception_list exceptions) {for (std::exception_ptr const& e : exceptions) {try {std::rethrow_exception(e);}catch (sycl::exception const& e) {std::cout << "Caught asynchronous SYCL exception:\n"<< e.what() << std::endl;}
catch (std::exception const& e) {std::cout << "Caught asynchronous STL exception:\n"<< e.what() << std::endl;}}};

これで、行列データが SYCL バッファーにロードされ、ターゲットのデバイスにオフロードして、完了後にホストに戻すことができます。最後に、mkl::blas::gemm API がすべてのバッファー、サイズ、および転置操作で呼び出され、行列乗算カーネルとデータをターゲットにキューに追加します。
// 例外ハンドラーがアタッチされた gpu デバイスで実行キューを作成
sycl::queue my_queue(my_device, my_exception_handler);// デバイスとホスト間のオフロード向けに行列データの SYCL バッファーを作成
sycl::buffer<double, 1> A_buffer(A.data(), A.size());
sycl::buffer<double, 1> B_buffer(B.data(), B.size());
sycl::buffer<double, 1> C_buffer(C.data(), C.size());// add oneapi::mkl::blas::gemm を実行キューに追加し、同期例外をキャッチ
165

インテル® oneAPI プログラミング・ガイド

try {using oneapi::mkl::blas::gemm;
using oneapi::mkl::transpose;gemm(my_queue, transpose::nontrans, transpose::nontrans, m, n, k, alpha, A_buffer, ldA,
B_buffer,
ldB, beta, C_buffer, ldC);}
catch (sycl::exception const& e) {std::cout << "\t\tCaught synchronous SYCL exception during GEMM:\n"<< e.what() << std::endl;}
catch (std::exception const& e) {std::cout << "\t\tCaught synchronous STL exception during GEMM:\n"<< e.what() << std::endl;}

gemm カーネルがキューに登録された後、実行されます。キューは、すべてのカーネルの実行を待機し、キャッチされた
非同期例外を例外ハンドラーに渡してスローするように要求します。ランタイムは、ホストと GPU デバイス間のバッ
ファーのデータ転送を処理します。C_buffer のアクセサーが作成されるまでに、バッファーのデータはホストマシンに暗黙的に転送されます。この場合、アクセサーは 2 x 2 の C_buffer のサブ行列を出力するために使用されます。
// C バッファーからデータをアクセスし、C 行列の一部を出力
auto C_accessor = C_buffer.template get_access<sycl::access::mode::read>();std::cout << "\t" << C << " = [ " << C_accessor[0] << ", "<< C_accessor[1] << ", ...]\n";
std::cout << "\t[ " << C_accessor[1 * ldC + 0] << ", "<< C_accessor[1 * ldC + 1] << ", ...]\n";
std::cout << "\t[ " << "...]\n";
std::cout << std::endl;
return 0;

結果データは C_buffer オブジェクトにあり、明示的にどこかにコピーしない限り (元の C コンテナに戻すなど)、
C_buffer がスコープ外になるまでアクセサーを介してのみ利用できます。

5.3 インテル® oneAPI スレッディング・ビルディング・ブロック(インテル®
oneTBB)
インテル® oneTBB は、ホスト上でタスクベースの、共有メモリー並列プログラミングを可能にする、広く使用されている C++ ライブラリーです。このライブラリーは、SYCL* および ISO C++ で利用可能な機能のほかに、CPU 上での並列
プログラミング向けに次のような機能を提供します。


汎用並列アルゴリズム



コンカレント・コンテナ



スケラーブル・メモリー・アロケーター



ワークスチール・タスク・スケジューラー

低レベル同期プリミティブ

166インテル® oneAPI プログラミング・ガイド

インテル® oneTBB はコンパイラーに依存せず、さまざまなプロセッサーとオペレーティング・システムで利用できます。
CPU 向けのマルチスレッド並列処理を実現するため、ほかのインテル® oneAPI ライブラリー インテル® oneMKL、
インテル® oneDNN など) で使用されています。
機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneTBB のウェブサイト (英語) をご覧ください。インテル® oneTBB をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償オプショ
ンとして優先サポート (英語) を利用できます。インテルのコミュニティー・サポートについては、インテル® oneTBB
フォーラム (英語) を参照してください。コミュニティーがサポートするオープンソース・バージョンについては、oneTBB
GitHub* (英語) のページを参照してください。

5.3.1 インテル® oneTBB の使い方
インテル® oneTBB は、ほかの C++ コンパイラーでもインテル® oneAPI DPC++ コンパイラーと同じ方法で使用できます。詳細は、「インテル® oneTBB ドキュメント」 (英語) をご覧ください。
現在、インテル® oneTBB はアクセラレーターを直接サポートしません。ただし、DPC++ 言語、OpenMP* オフロードのほかのインテル® oneAPI ライブラリーを組み合わせて、利用可能なすべてのハードウェア・リソースを効率良く使用するプログラムを構築できます。

5.3.2 インテル® oneTBB サンプルコード
2 つの基本的なインテル® oneTBB サンプルコードが、 https://github.com/oneapi-src/oneAPI-samples/tree/
master/Libraries/oneTBB (英語) で入手できます。これらのサンプルコードは、CPU と GPU 向けに記述されています。


tbb-async-sycl は、インテル® oneTBB フローグラフ非同期ノードと機能ノードを使用し、計算カーネルを分割して CPU と GPU 間で実行する方法を示します。フローグラフ非同期ノードは、SYCL* を使用して機能ノードが計算の CPU 部分を実行する間に、GPU で実装された計算を実行します。



tbb-task-sycl は、2 つのインテル® oneTBB タスクが同じ計算カーネルを実行する方法を示します。1 つのタスクが SYCL* コードを実行し、もう一方はインテル® oneTBB コードを実行します。



tbb-resumable-tasks-sycl は、インテル® oneTBB 再開タスクと parallel_for を使用して、計算カー
ネルを分割して CPU と GPU で実行する方法を示します。再開可能なタスクは SYCL* を使用して GPU で計算を実装し、parallel_for は計算の CPU 部分を実行します。

5.4 インテル® oneAPI データ・アナリティクス・ライブラリー (インテル®
oneDAL)インテル® oneDAL は、データ解析のすべてのステージ (前処理、変換、解析、モデリング、検証、意思決定) で、バッチ、
オンライン、および分散処理モードで計算を実行する、高度に最適化されたアルゴリズムのビルディング・ブロックを提供することで、ビッグデータ解析の高速化を支援するライブラリーです。

167インテル® oneAPI プログラミング・ガイド

アルゴリズムの計算だけでなくデータの取り込みを最適化し、スループットとスケーラビリティーを向上します。C++、および Java* API に加えて、Spark* や Hadoop* などの一般的なデータソースへのコネクターが含まれます。インテル®
oneDAL の Python* ラッパーは、インテル® ディストリビューションの Python* (英語) に含まれます。
さらに従来の機能に加えて、インテル® oneDAL は従来の C++ インターフェイスに DPC++ API 拡張機能を提供し、一部のアルゴリズムで GPU も利用できるようにします。
このライブラリーは、分散計算では特に有用です。通信レイヤーから独立した分散アルゴリズムのビルディング・ブロッ
クの完全なセットを提供します。これにより、ユーザーは利用したい通信基盤を使って、高速でスケーラブルな分散アプ
リケーションを構築できます。
機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneDAL のウェブサイト (英語) をご覧ください。インテル® oneDAL をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償オプショ
ンとして優先サポート (英語) を利用てきます。インテルのコミュニティー・サポートについては、インテル® oneDAL
フォーラム (英語) を参照してください。コミュニティーがサポートするオープンソース・バージョンについては、oneDAL
GitHub* (英語) のページを参照してください。

5.4.1 インテル® oneDAL の使い方
アプリケーションをビルドしてインテル® oneDAL とリンクするのに必要な依存関係に関する情報は、「インテル®
oneDAL のシステム要件」 (英語) を参照してください。
インテル® oneDAL ベースのアプリケーションは、適切なデバイスセレクターを選択することで、CPU または GPU でア
ルゴリズムをシームレスに実行できます。新機能により次のことが可能になります。


数値テーブルから SYCL* バッファーを抽出してカスタムカーネルに渡す。



SYCL* バッファーから数値テーブルを作成する。

アルゴリズムは、SYCL* バッファーを再利用して GPU データを保持し、GPU と CPU 間でデータを繰り返しコピーする
過負荷を排除するように最適化されています。

5.4.2 インテル® oneDAL サンプルコード
インテル® oneDAL のサンプルコードは GitHub* リポジトリーから入手できます。次のサンプルコードは、インテル®
oneDAL 固有の機能を示す分かりやすい例です。
https://github.com/oneapi-src/oneDAL/tree/master/examples/oneapi/dpc/source/svm (英語)168インテル® oneAPI プログラミング・ガイド

5.5 インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー(インテル® oneCCL)
インテル® oneCCL は、ディープラーニング (DL)、およびマシンラーニング (ML) ワークロード向けのスケーラブルでハ
イパフォーマンスな通信ライブラリーです。インテル® Machine Learning Scaling Library に由来するアイデアを発展させて、新しい機能と利用ケースを実現するため設計と API を拡張しています。
インテル® oneCCL は次の機能を備えています。


低レベルの通信ミドルウェア上に構築された MPI と libfabrics。



通信パフォーマンスに対する計算の生産的なトレードオフを可能にすることで、通信パターンのスケーラビリ
ティーを促進する最適化。



優先順位、永続的な操作、アウトオブオーダー実行など、一連の DL 固有の最適化。



CPU や GPU など各種ハードウェア・ターゲットで実行する DPC++ API。



さまざまなインターコネクトで動作: インテル® Omni-Path アーキテクチャー (インテル® OPA)、InfiniBand*、イーサネット。

機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneCCL のウェブサイト (英語) をご
覧ください。インテル® oneCCL をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償
オプションとして優先サポート (英語) を利用できます。コミュニティーがサポートするオープンソース・バージョンについては、oneCCL GitHub* ページ (英語) を参照してください。

5.5.1 インテル® oneCCL の使い方
MPI やインテル® oneAPI DPC++/C++ コンパイラーなど、ハードウェアとソフトウェアの依存関係に関する完全なリス
トについては、「インテル® oneCCL のシステム要件」 (英語) を参照してください。
SYCL* 対応 API は、インテル® oneCCL のオプション機能です。インテル® oneCCL ストリーム・オブジェクトを作成する
場合、CPU と SYCL* バックエンドのどちらかを選択できます。
CPU バックエンド: 最初の引数に ccl_stream_host を指定します。



SYCL* バックエンド: デバイスタイプに応じて ccl_stream_cpu または ccl_stream_gpu を指定します。



SYCL* ストリームで動作する集合操作‐

C API では、インテル® oneCCL は通信バッファーが void* にキャストされた sycl::buffer オブジェ
クトであると想定します。

‐

C++ API では、インテル® oneCCL は通信バッファーが参照渡しされることを想定します。

使用法に関する詳しい説明は、https://oneapi-src.github.io/oneCCL/ (英語) から入手できます。

169インテル® oneAPI プログラミング・ガイド

5.5.2 インテル® oneCCL サンプルコード
インテル® oneCCL の サ ン プ ル コード は、https://github.com/oneapi-src/oneAPI-samples/tree/master/
Libraries/oneCCL (英語) から入手できます。
コードをビルドして実行する手順を含む入門サンプルは、同じ GitHub* リポジトリーから入手できます。

5.6 インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー(インテル® oneDNN)
インテル® oneDNN は、ディープラーニング・アプリケーション向けのオープンソースのパフォーマンス・ライブラリーです。このライブラリーには、インテル® アーキテクチャー・ベースのプロセッサーおよびインテル® プロセッサー・グラ
フィックス向けに最適化されたニューラル・ネットワークの基本的な構成要素が含まれます。インテル® oneDNN は、
インテル® アーキテクチャー・ベースのプロセッサーとインテル® プロセッサー・グラフィックス上でアプリケーションのパフォーマンス向上に注目するディープラーニング・アプリケーションおよびフレームワーク開発者を対象としています。
ディープラーニングでは、インテル® oneDNN を利用するアプリケーションを使用すべきです。
インテル® oneDNN は、インテル® oneAPI DL フレームワーク・デベロッパー・ツールキット、インテル® oneAPI ベース・
ツールキットの一部として配布され、apt または yum チャネルから入手できます。
インテル® oneDNN は、C および C++ インターフェイス、OpenMP*、インテル® oneTBB、OpenCL* ランタイムなど、
DNNL で現在サポートされる機能を引き続きサポートします。インテル® oneDNN は、oneAPI プログラミング・モデルの DPC++ API とランタイムサポートを導入します。
機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneDNN ウェブサイト (英語) をご覧ください。インテル® oneDNN をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償オプション
として優先サポート (英語) を利用できます。コミュニティーがサポートするオープンソース・バージョンについては、
oneDNN GitHub* (英語) のページを参照してください。

5.6.1 インテル® oneDNN の使い方
インテル® oneDNN は、インテル® 64 アーキテクチャーまたは互換プロセッサーをベースにするシステムをサポートします。サポートされる CPU およびグラフィックス・ハードウェアのリストは、インテル® oneAPI ディープ・ニューラル・ネッ
トワーク・ライブラリーのシステム要件を参照してください。
インテル® oneDNN は実行時に命令セット・アーキテクチャー (ISA) を検出し、オンライン生成機能を使用して、サポートされる最新の ISA 向けに最適化されたコードを展開します。
アプリケーションが使用する CPU または GPU ランタイム・ライブラリーとの相互運用性を保証するため、オペレーティ
ング・システムごとにいくつかのパッケージが提供されます。

170インテル® oneAPI プログラミング・ガイド

オペレーティング・システムごとのパッケージ
設定
cpu_dpcpp_gpu_dpcpp
cpu_iomp
cpu_gomp
cpu_vcomp
cpu_tbb

依存関係
DPC++ ランタイム
インテルの OpenMP* ランタイム
GNU* OpenMP* ランタイム
Microsoft* Visual C++* OpenMP* ランタイム
インテル® oneTBB

パッケージには必要なライブラリーが含まれていないため、ビルド時にインテル® oneAPI ツールキットまたはサードパーティーのツールを使用してアプリケーションで依存関係を解決する必要があります。
SYCL* 環境では、インテル® oneDNN は DPC++ SYCL* ランタイムを介して CPU または GPU ハードウェアと対話します。インテル® oneDNN は SYCL* を使用するほかのコードを使用することもできます。これを可能にするため、インテル® oneDNN は基盤となる SYCL* オブジェクトと相互作用する API 拡張機能を提供します。
そのような状況の 1 つとして、インテル® oneDNN が提供しないカスタム操作を行うため SYCL* カーネルを実行する
場合が考えられます。その場合、インテル® oneDNN はカーネルをシームレスに送信するのに必要な API を提供し、同じデバイスキューを使用して実行コンテキストをインテル® oneDNN と共有します。
相互運用性を提供する API は、次の 2 つのシナリオを想定します。


既存の SYCL* オブジェクトをベースとするインテル® oneDNN オブジェクトの構築



既存のインテル® oneDNN オブジェクト向けの SYCL* オブジェクトへのアクセス

次の表にインテル® oneDNN オブジェクトと SYCL* オブジェクトのマッピングを示します。
インテル® oneDNN と SYCL* オブジェクトのマッピング 1
インテル® oneDNN オブジェクト
エンジン
ストリーム
メモリー

SYCL* オブジェクト
cl::sycl::device and cl::sycl::context
cl::sycl::queue
cl::sycl::buffer<uint8_t, 1> または統合共有メモリー (USM) ポインター

注: 内部的にライブラリー・メモリー・オブジェクトは、1D uint8_t SYCL* バッファーを使用しますが、異なるタイプの SYCL* バッファーを介してメモリーを初期化およびアクセスできます。この場
合、バッファーは異なるタイプの cl::sycl::buffer<uint8_t, 1> に再解釈されます。

171インテル® oneAPI プログラミング・ガイド

インテル® oneDNN と SYCL* オブジェクトのマッピング 2
インテル® oneDNN オブジェクト
エンジン
ストリーム
メモリー

SYCL* オブジェクトからの再構成
dnnl::sycl_interop::make_engine(sycl_dev, sycl_ctx)
dnnl::sycl_interop::make_stream(engine, sycl_queue)
USM ベース: dnnl::memory(memory_desc, engine, usm_ptr)
バッファーベース: dnnl::sycl_interop::make_memory(memory_de sc,
engine, sycl_buf)

インテル® oneDNN と SYCL* オブジェクトのマッピング 3
インテル® oneDNN オブジェクト
エンジン
ストリーム
メモリー

SYCL* オブジェクトの抽出
dnnl::sycl_interop::get_device(engine)
dnnl::sycl_interop::get_context(engine)
dnnl::sycl_interop::get_queue(stream)
USM ポインター: dnnl::memory::get_data_handle()
バッファー: dnnl::sycl_interop::get_buffer(memory)

注:





インテル® oneDNN でアプリケーションをビルドするには、コンパイラーが必要です。
インテル® oneAPI DPC++/C++ コンパイラーは、インテル® oneAPI ベース・ツールキットに含まれています。
SYCL* 相互運用性 API を有効にするには、dnnl_sycl.hpp をインクルードする必要があります。
OpenMP* はランタイム・オブジェクトの受け渡しに依存しないため、インテル® oneDNN と連携する相互運用 API は必要ありません。

5.6.2 インテル® oneDNN サンプルコード
インテル® oneDNN のサンプルコードは、https://github.com/oneapi-src/oneAPI-samples/tree/master/Libraries/
oneDNN (英語) から入手できます。導入向けのサンプルは新規ユーザーを対象としており、ビルドコマンドと実行コマンドの例を含む readme ファイルが含まれています。

5.7 インテル® oneAPI ビデオ・プロセシング・ライブラリー (インテル®
oneVPL)インテル® oneVPL は、CPU、GPU、およびそのほかのアクセラレーターでポータブルなメディア・パイプラインを構築する、ビデオデコードとエンコード、および処理をおこなうプログラミング・インターフェイスです。インテル® oneVPL API
は、インテル® ハードウェア・アクセラレーターを最大限に活用する、高品質で高いパフォーマンスのビデオ・アプリケー
ションを開発するために使用されます。メディア・セントリックのビデオ解析ワークロードにおけるデバイスの検出と選択、およびゼロコピーバッァー共有向けの API プリミティブを提供します。
172

インテル® oneAPI プログラミング・ガイド

インテル® oneVPL は、インテル® メディア SDK と下位互換性があり、アーキテクチャー間の互換性も提供するため、ソースコードを変更することなく現在および将来のハードウェアで最適な実行が保証されます。
インテル® oneVPL はオープン仕様の API です。
機能一覧、ドキュメント、サンプルコード、ダウンロードについては、インテル® oneVPL ウェブサイト (英語) をご覧ください。インテル® oneVPL をインテル® oneAPI ベース・ツールキット (英語) の一部として利用する場合、有償オプション
として優先サポート (英語) を利用できます。インテルのコミュニティー・サポートについては、インテル® oneVPL フォー
ラム (英語) を参照してください。コミュニティーがサポートするオープンソース・バージョンについては、 oneVPL
GitHub* (英語) のページを参照してください。

5.7.1 インテル® oneVPL の使い方
アプリケーションはインテル® oneVPL を使用して、ビデオのエンコードとデコード、および画像処理コンポーネントをプログラムできます。インテル® oneVPL はアクセラレーターを使用する前に、リファレンス設計として使用できるデフォルトの CPU 実装を提供します。
インテル® oneVPL アプリケーションは、次のプログラミング・モデルの基本的な手順に従います。
1.

インテル® oneVPL ディスパッチャーは、実行時に利用可能なすべてのアクセラレーターを自動検索します。

2.

ディスパッチャーは、選択したアクセラレーター・コンテキストのセッションを初期化します。

3.

インテル® oneVPL は、セッションの開始時にビデオ・コンポーネントを構成します。

4.

インテル® oneVPL 処理ループが開始されます。処理ループは非同期で動作します。

5.

アプリケーションがインテル® oneVPL に作業メモリーを管理させることを選択した場合、メモリー割り当ては処理ループ内のビデオ呼び出しによって暗黙的に管理されます。

6.

作業が完了すると、インテル® oneVPL はクリア呼び出しによりすべてのリソースをクリーンアップします。

インテル® oneVPL API は、クラシックな C スタイルのインターフェイスで定義されており、C++ と SYCL* とも互換性があります。

5.7.2 インテル® oneVPL サンプルコード
インテル® oneVPL には、インテル® oneVPL API の使い方を示す豊富なサンプルコードが用意されています。サンプル
コードはリリースパッケージに含まれており、GitHub* リポジトリーの oneAPI-samples (英語) からも入手できます。
例えば、「hello-decode」 (英語) サンプルでは、HEVC 入力ストリームの簡単なデコード操作とインテル® oneVPL プロ
グラミングの基本的な手順を説明しています。
サンプルコードは次のような手順に分解できます。

173

インテル® oneAPI プログラミング・ガイド

注: 以下の例は最新のサンプルとは異なる場合があります。最新のバージョンについては、リリース
パッケージまたはサンプルのリポジトリーを参照してください。

1.

ディスパッチャーでインテル® oneVPL セッションを初期化します。

mfxLoader loader = NULL;
mfxConfig cfg = NULL;
loader = MFXLoad();cfg = MFXCreateConfig(loader);
ImplValue.Type = MFX_VARIANT_TYPE_U32;
ImplValue.Data.U32 = MFX_CODEC_HEVC;
sts = MFXSetConfigFilterProperty(cfg,(mfxU8*)"mfxImplDescription.mfxDecoderDescription.decoder.CodecID", ImplValue);sts = MFXCreateSession(loader, 0, &session);

ここで、MFXCreateConfig() はディスパッチャーの内部構成を作成します。ディスパッチャーが構成されると、アプリケーションは MFXSetConfigFilterProperty() を使用して、コーデック ID とアクセラレーター・リ
ファレンスなどの要件を設定します。アプリケーションが要件を設定するとセッションが作成されます。
2.

デコードループを開始します。

while(is_stillgoing) {sts = MFXVideoDECODE_DecodeFrameAsync(session,(isdraining) ? NULL : &bitstream, NULL,&pmfxOutSurface,&syncp);......
}

入力ストリームの準備が完了するとストリームには必要なコンテキストが用意され、デコードループはすぐに開始されます。
MFXVideoDECODE_DecodeFrameAsync() は、ビットストリームを第 2 パラメーターとして受け取ります。
ビットストリームが NULL に到達すると、インテル® oneVPL は入力から残りのフレームを排出して操作を完了します。3 番目のパラメーターは作業メモリーです。例に示す NULL 入力はアプリケーションがインテル® oneVPLに作業メモリーの管理を要求することを意味します。

174インテル® oneAPI プログラミング・ガイド

3.

デコード呼び出しの結果を評価します。

while(is_stillgoing) {sts = MFXVideoDECODE_DecodeFrameAsync(...);
switch(sts) {case MFX_ERR_MORE_DATA:......
ReadEncodedStream(bitstream, codec_id, source);......
break;
case MFX_ERR_NONE:
do {sts = pmfxOutSurface->FrameInterface->Synchronize(pmfxOutSurface,
WAIT_100_MILLSECONDS);
if( MFX_ERR_NONE == sts ) {sts = pmfxOutSurface->FrameInterface->Map(pmfxOutSurface, MFX_MAP_READ);
WriteRawFrame(pmfxOutSurface, sink);
sts = pmfxOutSurface->FrameInterface->Unmap(pmfxOutSurface);
sts = pmfxOutSurface->FrameInterface->Release(pmfxOutSurface);
framenum++;}} while( sts == MFX_WRN_IN_EXECUTION );break;
default:
break;}}

MFXVideoDECODE_DecodeFrameAsync() の呼び出しごとに、アプリケーションはインテル® oneVPL がMFX_ERR_NONE で新しいストリームが完了するまで入力ビットストリームの読み取りを続行し、関数が正常に操作を完了したことを示します。新しいフレームごとにアプリケーションは出力メモリー (surface) の準備ができるまで待機し、フレームを出力および解放します。
Map() は、ディスクリート・グラフィックスのメモリー空間をホストメモリー空間にマップするのに使用されます。
4.

終了してクリーンアップを行います。

MFXUnload(loader);free(bitstream.Data);
fclose(sink);
fclose(source);

最後に、MFXUnload() が呼び出されインテル® oneVPL からリソースが再利用されます。これは、インテル®
oneVPL ライブラリーがリソースを再利用するためアプリケーションが行うべき唯一の呼び出しです。

175インテル® oneAPI プログラミング・ガイド

注: この例では、インテル® oneVPL プログラミング・モデルの主な手順について説明しています。
入力と出力ユーティリティー関数については説明していません。

5.8 その他のライブラリー
その他のライブラリーは、各種インテル® oneAPI ツールキットに含まれます。各ライブラリーの詳細については、それぞれのライブラリーの公式ドキュメントをご覧ください。
インテル® インテグレーテッド・パフォーマンス・プリミティブ (インテル® IPP)

インテル® MPI ライブラリーインテル® オープン・ボリューム・カーネル・ライブラリー

176

インテル® oneAPI プログラミング・ガイド

6

ソフトウェア開発プロセス

oneAPI プログラミング・モデルを使用したソフトウェア開発プロセスは、標準の開発プロセスをベースにしています。
プログラミング・モデルは、アクセラレーターを使用してパフォーマンスを向上するため、この節ではその作業に固有の手順を説明します。これには以下のものがあります。


パフォーマンス・チューニング・サイクル



コードのデバッグほかのアクセラレーター向けのコードの移行

コードのコンポーザビリティー

6.1 SYCL* と DPC++ へのコードの移行
C++ または OpenCL* などほかのプログラミング言語で記述されたコードは、複数のデバイスで使用するため DPC++
コンパイラーでコンパイルされる SYCL* コードへ移行できます。移行手順は、元の言語によって異なります。

6.1.1 C++ から SYCL* への移行
SYCL* は、C++ をベースとする「単一ソース」スタイルのプログラミング・モデルです。C++17 と C++20 の機能を基に構築され、ヘテロジニアス・プログラミングにおけるオープン、マルチベンダー、およびマルチアーキテクチャーのソ
リューションをサポートします。
DPC++ コンパイラー・プロジェクトは、SYCL* を LLVM C++ コンパイラーに導入し、複数のベンダーとアーキテク
チャーに対応したハイパフォーマンスな実装を実現しています。
既存の C++ アプリケーションを高速化する場合、大部分の C++ コードは変更する必要がないため、SYCL* はシームレ
スな統合を可能にします。デバイス側のコンパイルを可能にする SYCL* の構造については、「oneAPI プログラミング・モデル」をご覧ください。

6.1.2 DPC++ コンパイラーを使用した CUDA* から SYCL* への移行
インテル® DPC++ 互換性ツール (インテル® DPCT) は、インテル® oneAPI ベース・ツールキットに含まれます。このツールの目的は、NVIDIA* CUDA* で記述された既存のプログラムから、DPC++ コンパイラーでコンパイルされる
SYCL* で記述されたプログラムへの移行を支援することです。このツールは、可能な限り SYCL* コードを自動生成します。しかし、すべてのコードが自動的に移行されるとは限らず、手動での変更が必要な場合があります。このツールには、
IDE プラグインヘルプと、DPC++ への移行を完了するためのユーザーガイド (英語) を含まれます。手動での変更が完了
したら、DPC++ コンパイラーを使用して実行可能ファイルを作成します。

177インテル® oneAPI プログラミング・ガイド

インテル® DPC++ 互換性ツールを使用した CUDA* から SYCL* への移行



移行されたコード例、ツールのダウンロード手順などの説明は、インテル® DPCT ウェブサイト (英語) でご覧いただけます。



ツールの詳しい使用方法は、『インテル® DPC++ 互換性ツール・ユーザーガイド』 (英語) を参照してください。

6.1.3 OpenCL* コードから SYCL* への移行
現在の DPC++ プロジェクトの SYCL* ランタイムは、並列処理を実現するため OpenCL* コードを採用しています。
通常、SYCL* ではカーネルを実装するコードの行数と必要な API 関数やメソッドの呼び出しは少なくなります。ホストのソースコード行にデバイスのソースコードを埋め込むことで、OpenCL* プログラムを作成できます。
ほとんどの OpenCL* アプリケーション開発者は、デバイスへのカーネルオフロードに伴うセットアップ・コードの必要性を認識しているでしょう。SYCL* を使用すると、OpenCL* C コードに関連する大部分のセットアップ・コードなしで、シンプルで現代的な C++ ベースのアプリケーションを開発できます。これにより、習得の労力が軽減され、並列化の実装に集中できます。
さらに、OpenCL* アプリケーションの機能は、SYCL* API を介して引き続き利用できます。更新されたコードは、必要に応じて SYCL* インターフェイスを使用できます。

6.1.4 CPU、GPU、および FPGA 間の移行
DPC++ コンパイラーを使用した SYCL* では、プラットフォームは CPU、GPU、FPGA、またはその他のアクセラレーター
やプロセッサーなどのデバイス (なくてもかまいません) に接続されたホストデバイスで構成されます。
プラットフォームに複数のデバイスが存在する場合、一部または大部分のワークをデバイスへオフロードするようにア
プリケーションを設計します。oneAPI プログラミング・モデルで複数のデバイスにワークを分散するには、いくつかの方法があります。
1.

デバイスセレクターの初期化 - SYCL* ではセレクターと呼ばれるクラスが提供され、プラットフォーム内のデバ
イスを手動で選択するか、oneAPI ランタイムのヒューリスティックがデバイスで利用可能な計算機能を判断してデフォルトデバイスを選択できるようになっています。

178

インテル® oneAPI プログラミング・ガイド

2.

データセットの分割 - データに依存関係がない高い並列性を持つアプリケーションでは、データセットを明示的に分割して異なるデバイスで利用します。次のサンプルコードは、複数のデバイスにワークロードを分配する例です。icpx -fsycl snippet.cpp コマンドでコードをコンパイルします。

1. int main() {2.
int data[1024];3.
for (int i = 0; i < 1024; i++)4.
data[i] = i;
5.
try {
6.
cpu_selector cpuSelector;
7.
queue cpuQueue(cpuSelector);8.
gpu_selector gpuSelector;
9.
queue gpuQueue(gpuSelector);10.
buffer<int, 1> buf(data, range<1>(1024));
11.
cpuQueue.submit([&](handler& cgh) {12.
auto ptr =13.
buf.get_access<access::mode::read_write>(cgh);14.
cgh.parallel_for<class divide>(range<1>(512),15.
[=](id<1> index) {16.
ptr[index] -= 1;
17.
});
18.
});
19.
gpuQueue.submit([&](handler& cgh1) {20.
auto ptr =21.
buf.get_access<access::mode::read_write>(cgh1);
22.
cgh1.parallel_for<class offset1>(range<1>(1024),
23.
id<1>(512), [=](id<1> index) {24.
ptr[index] += 1;
25.
});
26.
});
27.
cpuQueue.wait();28.
gpuQueue.wait();
29.
}
30.
catch (exception const& e) {31.
std::cout <<32.
"SYCL exception caught: " << e.what() << '\n';33.
return 2;
34.
}
35.
return 0;
36. }

3.

デバイス間で複数のカーネルをターゲットにする - アプリケーションに複数の独立したカーネルで並列処理可能なスコープがある場合、ターゲットデバイスごとに異なるキューを使用します。SYCL* でサポートされる
プ ラ ッ ト フ ォ ー ム と プ ラ ッ ト フ ォ ー ム ご と の デ バ イ ス の リ ス ト は 、 get_platforms() とplatform.get_devices() を呼び出すことで取得できます。すべてのデバイスが特定されたら、デバイス
ごとにキューを作成し、異なるカーネルを異なるキューに配置します。次のサンプルコードは、複数の SYCL*
デバイスにカーネルを配置する方法を示します。

1. #include <stdio.h>
2. #include <vector>
3. #include <CL/sycl.hpp>
4. using namespace cl::sycl;
5. using namespace std;
6. int main()
7. {8.
size_t N = 1024;
9.
vector<float> a(N, 10.0);10.
vector<float> b(N, 10.0);11.
vector<float> c_add(N, 0.0);179インテル® oneAPI プログラミング・ガイド

12.
vector<float> c_mul(N, 0.0);
13.
{
14.
buffer<float, 1> abuffer(a.data(), range<1>(N),15.
{ property::buffer::use_host_ptr() });16.
buffer<float, 1> bbuffer(b.data(), range<1>(N),17.
{ property::buffer::use_host_ptr() });18.
buffer<float, 1> c_addbuffer(c_add.data(), range<1>(N),19.
{ property::buffer::use_host_ptr() });20.
buffer<float, 1> c_mulbuffer(c_mul.data(), range<1>(N),21.
{ property::buffer::use_host_ptr() });
22.
try {
23.
gpu_selector gpuSelector;
24.
auto queue = cl::sycl::queue(gpuSelector);
25.
queue.submit([&](cl::sycl::handler& cgh) {26.
auto a_acc = abuffer.template27.
get_access<access::mode::read>(cgh);
28.
auto b_acc = bbuffer.template29.
get_access<access::mode::read>(cgh);
30.
auto c_acc_add = c_addbuffer.template31.
get_access<access::mode::write>(cgh);32.
cgh.parallel_for<class VectorAdd>
33.
(range<1>(N), [=](id<1> it) {34.
//int i = it.get_global();35.
c_acc_add[it] = a_acc[it] + b_acc[it];
36.
});
37.
});
38.
cpu_selector cpuSelector;
39.
auto queue1 = cl::sycl::queue(cpuSelector);
40.
queue1.submit([&](cl::sycl::handler& cgh) {41.
auto a_acc = abuffer.template42.
get_access<access::mode::read>(cgh);
43.
auto b_acc = bbuffer.template44.
get_access<access::mode::read>(cgh);
45.
auto c_acc_mul = c_mulbuffer.template46.
get_access<access::mode::write>(cgh);47.
cgh.parallel_for<class VectorMul>
48.
(range<1>(N), [=](id<1> it) {49.
c_acc_mul[it] = a_acc[it] * b_acc[it];
50.
});
51.
});
52.
}
53.
catch (cl::sycl::exception e) {54.
/* In the case of an exception being throw, print the55.
error message and56.
* return 1. */57.
std::cout << e.what();58.
return 1;
59.
}
60.
}
61.
for (int i = 0; i < 8; i++) {62.
std::cout << c_add[i] << std::endl;
63.
std::cout << c_mul[i] << std::endl;
64.
}
65.
return 0;
66. }

180

インテル® oneAPI プログラミング・ガイド

6.2 コンポーザビリティー
oneAPI プログラミング・モデルは、開発ツールチェーン全体をサポートするエコシステムを実現します。これには、CPU、
GPU、FPGA など複数のアクセラレーターをサポートするコンパイラーとライブラリー、デバッガーと解析ツールが含まれます。

6.2.1 C/C++ OpenMP* および SYCL* のコンポーザビリティー
oneAPI プログラミング・モデルは、OpenMP* オフロードをサポートする LLVM/Clang ベースの統合コンパイラーを提供します。これにより、OpenMP* 構造を使用してホスト側のアプリケーションを並列化するか、ターゲットデバイスにオフロードするシームレスな統合が可能になります。インテル® oneAPI ベース・ツールキットで利用可能なインテル®
oneAPI DPC++/C++ コンパイラーと、インテル® oneAPI HPC ツールキットやインテル® oneAPI IoT ツールキットで利用可能なインテル® C/C++ コンパイラー・クラッシックは、制限付きで OpenMP* と SYCL* の互換性を提供します。
単一のアプリケーションでは、OpenMP* target 領域または SYCL* 構造を使用して、さまざまな関数やコードセグメ
ントなどのコード領域の実行をデバイスにオフロードできます。
OpenMP* と SYCL* オフロード構造は、別々のファイル、同じファイル、または同じ関数 (制限付き) で使用できます。
OpenMP* および SYCL* オフロードコードは、実行可能ファイル、静的ライブラリー、またはさまざまな組み合わせで一緒にバンドルできます。

注: DPC++ 向けの SYCL* は CPU でデバイスコードを実行する場合、インテル® oneTBB のランタイムを使用します。そのため、CPU で OpenMP* と SYCL* の両方を使用すると、スレッドのオー
バーサブスクリプションが発生する可能性があります。システムで実行されるワークロードのパフォーマンスを解析することで、この問題が生じているか確認することができます。

6.2.1.1.

制限事項

同じアプリケーションで OpenMP* と SYCL* 構造を混在する場合、いくつかの考慮すべき制限があります。


OpenMP* ディレクティブは、デバイスで実行される SYCL* カーネル内では使用できません。同様に、SYCL*
コードは、OpenMP* target 領域内では使用できません。ただし、ホスト CPU で実行される OpenMP* コード
内で SYCL* 構造を使用することはできます。

プログラム内の OpenMP* および SYCL* デバイス領域は相互依存関係を持つことができません。例えば、デバ
イスコードの SYCL* 領域で定義された関数は、同じデバイスで実行される OpenMP* コードから呼び出すことはできません (その逆も同様)。OpenMP* デバイス領域と SYCL* デバイス領域は個別にリンクされ、個別のバイナリーとしてコンパイラーによって生成されるファットバイナリーを構成します。



現時点では、OpenMP* と SYCL* ランタイム・ライブラリー間での直接的な相互作用はサポートされていません。
例えば、OpenMP* API で生成されたデバイス・メモリー・オブジェクトは、SYCL* コードからはアクセスできません。OpenMP* で生成されたデバイス・メモリー・オブジェクトを SYCL* コードで使用すると、未定義の動作となり
ます。

181

インテル® oneAPI プログラミング・ガイド

6.2.1.2.

例

次のコードは、SYCL* と OpenMP* オフロード構造を同じアプリケーションで使用する例を示します。
1. #include <CL/sycl.hpp>
2. #include <array>
3. #include <iostream>
4.
5.
6. float computePi(unsigned N) {7.
float Pi;
8. #pragma omp target map(from : Pi)
9. #pragma omp parallel for reduction(+ : Pi)
10.
for (unsigned I = 0; I < N; ++I) {11.
float T = (I + 0.5f) / N;
12.
Pi += 4.0f / (1.0 + T * T);
13.
}
14.
return Pi / N;
15. }
16.
17.
18. void iota(float *A, unsigned N) {19.
cl::sycl::range<1> R(N);20.
cl::sycl::buffer<float, 1> AB(A, R);21.
cl::sycl::queue().submit([&](cl::sycl::handler &cgh) {22.
auto AA = AB.template get_access<cl::sycl::access::mode::write>(cgh);23.
cgh.parallel_for<class Iota>(R, [=](cl::sycl::id<1> I) {24.
AA[I] = I;
25.
});
26.
});
27. }
28.
29.
30. int main() {31.
std::array<float, 1024u> Vec;
32.
float Pi;33.
34.
35. #pragma omp parallel sections
36.
{
37. #pragma omp section38.
iota(Vec.data(), Vec.size());
39. #pragma omp section
40.
Pi = computePi(8192u);
41.
}
42.
43.
44.
std::cout << "Vec[512] = " << Vec[512] << std::endl;
45.
std::cout << "Pi = " << Pi << std::endl;
46.
return 0;47. }サンプルコードをコンパイルするには次のコマンドを使用します。
$ icpx -fsycl -fiopenmp -fopenmp-targets=spir64 offloadOmp_dpcpp.cpp

182インテル® oneAPI プログラミング・ガイド

説明:-fsycl オプションは SYCL* を有効にします。

-fiopenmp -fopenmp-targets=spir64 オプションは OpenMP* オフロードを有効にします。

次はサンプルコードからの出力例となります。
$ ./a.out
Vec[512] = 512
Pi = 3.14159

注:コードに OpenMP* オフロードが含まれておらず、通常の OpenMP* コードのみが含まれる場合、-fopenmp-targets を省略した次のコマンドを使用します。
$ icpx -fsycl -fiopenmp omp_dpcpp.cpp

6.2.2 OpenCL* コードの相互運用性
oneAPI プログラミング・モデルでは、開発者は SYCL *API のさまざまな部分からすべての OpenCL* コードの機能を引き続き利用できます。SYCL* が提供する OpenCL* コードの相互運用性は、SYCL* が持つ高度なプログラミング・モ
デル・インターフェイスを利用しながら、従来の OpenCL* コードを再利用するのに役立ちます。この相互運用性モードには 2 つに主要機能があります。
1.

OpenCL* コードのオブジェクトから SYCL* オブジェクトを生成する。例えば、SYCL* バッファーは、OpenCL*
cl_mem から、または cl_command_queue の SYCL* キューから構築できます。

2.

SYCL* オブジェクトから OpenCL* コードのオブジェクトを取得する。例えば、SYCL* アクセサーに関連付けられた暗黙の cl_mem を使用する OpenCL* カーネルを起動します。

6.3 DPC++ と OpenMP* オフロード処理のデバッグ
ホスト・プラットフォーム向けにコードを記述、デバッグ、および最適化する場合、コードを改善する手順はシンプルです。
デバッガーで実行中のビルド、キャッチ、およびクラッシュや不正な結果の原因となる言語レベルのエラーに対処し、プロファイル・ツールを使用してパフォーマンスの問題を特定して修正します。
コードの一部分が DPC++ または OpenMP* オフロードにより別のデバイスで実行されるアプリケーションでは、コードの改善はかなり複雑になる可能性があります。


DPC++ または OpenMP* オフロードの誤った使い方は、接続されたオフロードデバイスでプログラムが実行される際に、ジャストインタイム (JIT) コンパイルされるまで認識できないことがあります (この問題は、事前コン
パイル (AOT) で確認できることがあります)。
183

インテル® oneAPI プログラミング・ガイドプログラムの論理的なエラーによるクラッシュは、ホスト、オフロードデバイス、または各種計算デバイスを連携されるソフトウェア・スタックで予期しない動作として現れる可能性があります。原因を究明するには以下が必要です。
‐

インテル® ディストリビューションの GDB などの標準デバッガーを使用して、ホスト上のコードで何が起こっているかデバッグします。

‐

デバイス固有のデバッガーを使用してオフロードデバイスの問題をデバッグします。ただし、デバイスのアーキテクチャー、計算スレッドを表現する規則、またはアセンブリーがホストとは異なることに注意してください。

‐

カーネルとデータがデバイスとのやり取りを行う場合にのみ中間ソフトウェア・スタックで現れる問題をデバッグするには、デバイスとホスト間の通信、および処理中に報告されるエラーを監視する必要があります。

ホストとオフロードデバイスで発生する可能性がある一般的なパフォーマンスの問題に加えて、ホストとオフ
ロードデバイスが連携するパターンは、アプリケーションのパフォーマンスに大きな影響を与えることがあります。これは、ホストとオフロードデバイス間の通信を監視する必要があるもう 1 つのケースです。

ここでは、オフロードプログラムの実行中に利用できる各種デバッグ、およびパフォーマンスに解析ツールとその用法について説明します。
リソースをオフロードする拡張機能を備えた OpenMP* または SYCL* API を使用するアプリケーションのトラブル
シューティングは、「高度な並列アプリケーションのトラブルシューティング」 (英語) のチュートリアルを参照してください。

6.3.1 SYCL* と OpenMP* 開発向けの oneAPI デバッグツール
次に示すツールは、SYCL* および OpenMP* オフロード処理のデバッグに役立ちます。
SYCL* および OpenMP* オフロード処理をデバッグするツール
ツール
環境変数
GPU 向けのプロファイル・ツールである
ze_tracer ツール (GPU 向け PTI)

OpenCL* アプリケーションのインターセ
プト・レイヤーインテル® ディストリビューションの GDB
インテル® Inspector

184

使用方法
環境変数を使用して、プログラムを変更することなく、プログラムの実行時にOpenMP* および SYCL* ランタイムから診断情報を収集できます。
SYCL* よび OpenMP* オフロードで oneAPI レベルゼロと OpenCL* バックエンドを使用する場合、このツールを利用してバックエンドのエラーをデバッグし、ホストとデバイスの両方でパフォーマンスのプロファイルを実行できます。
関連資料:
Onetrace ツールの GitHub* (英語)GPU 向け PTI の GitHub* (英語)SYC*L および OpenMP* オフロードで OpenCL* バックエンドを使用する場合、このライブラリーを利用してバックエンドのエラーをデバッグし、ホストとデバイスの両方でパフォーマンスのプロファイルを実行できます。
通常ホストおよびデバイス (CPU、GPU、FPGA エミュレーション) で、論理的なバグを調査する際にアプリケーションのソースレベルのデバッグで使用されます。
このツールは、オフロードの失敗につながる問題を含め、メモリーとスレッドの問題インテル® oneAPI プログラミング・ガイド

ツール

使用方法
を検出してデバッグするのに役立ちます。

注: インテル® Inspector は、インテル® oneAPI HPC ツール
キットまたはインテル® oneAPI IoT ツールキットに含まれます。
アプリケーション・デバッグ

これらのツールとランタイムベースのアプローチに加えて、開発者は別のアプロー
チから問題を見つけることもできます。次に例を示します。


カーネルの出力と期待される出力を比較

デバッグ用途の変数を作成して中間結果を確認



カーネル内で結果をプリント

注: SYCL* と OpenMP* では、どちらもオフロード領域内からの stdout への出力をサポートします。どの SIMD レーン
またはスレッドが出力しているか確認してください。
SYCL* 例外ハンドラー

インテル® Advisor
インテル® VTune™ プロファイラー

6.3.1.1.

一部の DPC++ プログラミングのエラーは、プログラムの実行中に SYCL* ランタ
イムから例外として返されます。これらは、実行時にフラグを使用するコード内のエラーを診断するのに役立ちます。詳細とサンプルについては、「SYCL* 例外」を参照
してください。SYCL* 例外のサンプルについては、以下を参照してください。


ガイド付き行列乗算の例外



ガイド付き行列乗算の無効なコンテキスト



ガイド付き行列乗算の競合状態

Fortran、C、C++、OpenCL* および SYCL* アプリケーションが最新のプロセッサーで最大限のパフォーマンスを発揮するのを支援します。
ネイティブシステムまたはリモートシステムでパフォーマンス・データを収取して解析します。

デバッグ環境変数

OpenMP* と SYCL* のオフロードランタイム、およびレベルゼロ、OpenCL*、シェーダーコンパイラーは、ホストとオフ
ロードデバイス間の通信を監視する環境変数を提供します。この環境変数を使用して、オフロード計算向けに選択されたランタイムを検出または制御できます。
6.3.1.1.1.

OpenMP* オフロード環境変数

OpenMP* オフロードがどのように動作するかを理解し、バックエンドの制御に利用できるいくつかの環境変数が用意されています。

185

インテル® oneAPI プログラミング・ガイド

注: OpenMP* は FPGA デバイスではサポートされません。

OpenMP* オフロード環境変数
環境変数
LIBOMPTARGET_DEBUG=<Num>

説明
デバッグ情報の出力を制御します。詳細は、「ランタイム」 (英語) を参照してください。この環境設定は、OpenMP* オフロードランタイムからのデバッグ出力を有効にします。以下が報告されます。


検出および使用された利用可能なランタイム (1、2)

選択されたランタイムが開始および停止されたタイミング
(1、2)



使用されるオフロードデバイスの詳細 (1、2)

ロードされたサポート・ライブラリー (1、2)

すべてのメモリー割り当てと割り当て解除のサイズとアドレス (1、2)

デバイス間とのデータコピーに関する情報、また統合共有メ
モリーではデバイスマッピング (1、2)

カーネルの起動と起動時の詳細情報 (引数、SIMD 幅、グループ情報など) (1、2)

呼び出されたゼロレベル/OpenCL* API 関数 (関数名、引数/
パラメーター) (2)値:<Num> = 0: 無効<Num> = 1: デバイス検出、カーネルコンパイル、メモリコピー操作、
カーネル呼び出し、およびその他のプラグイン依存アクションなどのプラグインアクションからの基本的なデバッグ情報を表示します。
<Num> = 2: <Num>=1 の出力に加えて、どの GPU ランタイム API
関数がどの引数/パラメーターで呼び出されたかを表示します。
デフォルト: 0186

インテル® oneAPI プログラミング・ガイド

環境変数
LIBOMPTARGET_INFO=<Num>

説明
この環境変数は、オフロードランタイムからの基本的なオフロード情報の表示を制御します。以下を表示します。ユーザーがlibomptarget にさまざまなランタイム情報を要求できるようにします。詳細は、「ランタイム」 (英語) を参照してください。
OpenMP* デバイスカーネルが受け取ったすべてのデータ引数を出力します (1)

マップされたアドレスがデバイス・マッピング・データ・テーブ
ルにすでに存在することを示します (2)ターゲットのオフロードが失敗した場合、デバイス・ポイン
ター・マップの内容をダンプします (4)

デバイス・マッピング・テーブルでエントリーが変更されたことを示します (8)

データがデバイス間でコピーされたことを示します (32)

値: (0, 1, 2, 4, 8, 32)
LIBOMPTARGET_PLUGIN_PROFILE=<Num>[,<Unit>]デフォルト: 0
この環境変数は、オフロードされた OpenMP* コードのパフォーマン
ス・データの表示を有効にします。以下を表示します。


合計データ転送時間 (リードとライト)



データ割り当て回数

モジュールのビルド時間 (ジャストインタイム・コンパイル)



各カーネルの実行時間。

値:F - 無効化T - ミリ秒単位のタイミングで有効化T,usec - マイクロ秒単位のタイミングで有効化

デフォルト: F
例: export LIBOMPTARGET_PLUGIN_PROFILE=T,usec<Enable>:= 1 | T<Unit> := usec | unit_usec
基本的なプラグイン・プロファイルを有効にし、プログラムの終了時に結果を出力します。<Unit> を指定しない場合、マイクロ秒がデ
フォルトの単位になります。

187インテル® oneAPI プログラミング・ガイド

環境変数
LIBOMPTARGET_PLUGIN=<Name>

説明この環境変数を使用して OpenMP* オフロードの実行に使用する
バックエンドを選択できます。

注: レベルゼロのバックエンドは GPU デバイ
スでのみサポートされます。
<Name>:=LEVEL0 | OPENCL | CUDA | X86_64 | NIOS2 |level0 | opencl | cuda | x86_64 | nios2 |使用するオフロードのプラグイン名を指定します。このオプションが指定されると、オフロードランタイムは他の RTL をロードしません。
値:

LEVEL0 または LEVEL_ZERO - レベルゼロ・バックエンドを
使用します



OPENCL - OpenCL* バックエンドを使用します

デフォルト:

LIBOMPTARGET_PROFILE=<FileName>188GPU オフロードデバイス: LEVEL0

CPU または FPGA オフロードデバイス: OPENCL

libomptarget が Clang の -ftime-trace オプションと同様の
時間プロファイルの出力を生成できるようにします。詳細は、「ランタイム」 (英語) を参照してください。

インテル® oneAPI プログラミング・ガイド

環境変数
LIBOMPTARGET_DEVICES=<DeviceKind>

説明<DeviceKind> :=DEVICE | SUBDEVICE | SUBSUBDEVICE | ALL |device | subdevice | subsubdevice | all
サブデバイスをユーザーに公開する方法を制御します。
DEVICE/device: 最上位レベルのデバイスのみが OpenMP* デバ
イスとしてレポートされ、subdevice 節がサポートされます。
SUBDEVICE/subdevice: 第 1 レベル のサブデバイ ス のみ がOpenMP* デバイスとしてレポートされ、subdevice 節は無視されます。
SUBSUBDEVICE/subsubdevice: 第 2 レベルのサブデバイス
のみが OpenMP* デバイスとしてレポートされ、subdevice 節は無視されます。レベルゼロ・バックエンドを使用する インテル®
GPU で、サブのサブデバイスをタイル内の単一計算スライスとして制 限 す る に は 、 追 加 の GPU 計 算 ラ ン タ イ ム 環 境 変 数
CFESingleSliceDispatchCCSMode=1 も設定する必要があります。
ALL/all: 最上位のデバイスとそれらのサブデバイスが OpenMP*
デバイスとしてレポートされ、subdevice 節は無視されます。これは、インテル® GPU ではサポートされておらず、今後廃止される予定です。
デフォルト: <DeviceKind>=device に相当

LIBOMPTARGET_LEVEL0_MEMORY_POOL=<Option><Option>:= 0 | <PoolInfoList><PoolInfoList> := <PoolInfo>[,<PoolInfoList>]<PoolInfo>:=<MemType>[,<AllocMax>[,<Capacity>[,<PoolSize>]]]<MemType>:= all | device | host | shared<PoolSize>:= 正の整数または空(MB 単位の最大割り当てサイズ)<Capacity>:= 正の整数または空(単一ブロックからの割り当て数)<PoolSize>:= 正の整数または空(MB 単位の最大プールサイズ)

再利用可能なメモリープールの構成を制御します。プールは、合計サイズが <PoolSize> を超えない、1 ブロックから最大 <AllocMax>
サイズの <Capacity> 割り当てが可能なメモリーブロックのリストです。

LIBOMPTARGET_LEVEL0_STAGING_BUFFER_SIZE=<Num>

デフォルト:<Option>=device,1,4,256,host,1,4,256,shared,8,4,
256 に相当
ステージ・バッファー・サイズを <Num> KB に設定します。ステージ
バッファーホストとデバイス間のコピー操作において、2 段階のコ
ピー操作の一時ストレージとして使用されます。バッファーはディスク
リート・デバイスでのみ使用されます。
デフォルト: 16189

インテル® oneAPI プログラミング・ガイド

環境変数
LIBOMPTARGET_LEVEL_ZERO_COMMAND_BATCH=<
Value>

説明<Value> := <Type>[,<Count>]<Type> :=none | NONE | copy | COPY | compute | COMPUTE<Count> := バッチ処理するコマンドの最大数
ターゲット領域のコマンドバッチ処理を有効にします。
<Type>=none|NONE: コマンドバッチ処理を無効にします。
<Type>=copy|COPY: データ転送でターゲット領域のコマンド
バッチ処理を有効にします。
<Type>=compute|COMPUTE: データ転送と計算にターゲット領
域のコマンドバッチ処理を有効にし、コピーエンジンの利用を無効にします。
<Type> が copy または compute (有効) のいずれかで、<Count> が指定されていないと、ターゲット領域ですべてのコマンドに対してバッチ処理が行われます。
デフォルト: <Type>=none (無効)

LIBOMPTARGET_LEVEL_ZERO_USE_IMMEDIATE_C
OMMAND_LIST=<Bool><Bool> := 1 | T | t | 0 | F | f
カーネル送信に即時コマンドリストの使用を有効/無効にします。

OMP_TARGET_OFFLOAD=MANDATORY

6.3.1.1.2.

デフォルト: 無効
これは OpenMP* 仕様で定義されています。
https:// www.openmp.org/spec-html/5.1/
openmpse74.html#x340-515000617 (英語)SYCL* と DPC++ 環境変数

DPC++ コンパイラーは、すべての標準 SYCL* 環境変数をサポートします。すべての環境変数については GitHub* (英語) をご覧ください。デバッグで注目すべきは、次の SYCL* 環境変数と追加のレベルゼロ環境変数です。

190

インテル® oneAPI プログラミング・ガイド

SYCL* と DPC++ 環境変数
環境変数
SYCL_DEVICE_FILTER

説明
この複雑な環境変数を使用すると、ランタイムで使用されるランタイム、計算デバイス ID を利用可能なすべての組み合わせのサブセットに制御できます。
計算デバイス ID は、SYCL* API、clinfo、または sycl-ls (0 から始まる番号) によって返される ID に対応します。その ID を持つデバイスが特定のタイプであったり、特定のランタイ
ムをサポートするかには関連性がありません。プログラムが特定のセレクター
gpu_selector など) を使用して、SYCL_DEVICE_FILTER のフィルターで除外されたデバイスを要求すると、例外がスローされます。
詳細については、GitHub* にある環境変数の説明をご覧ください。
https://github.com/intel/llvm/blob/sycl/sycl/doc/EnvironmentVariables.md (英語)
次のような値を含みます。

ONEAPI_DEVICE_SELECTORSYCL_PI_TRACE

opencl:cpu - 利用可能なすべての CPU デバイスで OpenCL* ランタイムのみを
使用します



opencl:gpu - 利用可能なすべての GPU デバイスで OpenCL* ランタイムのみを
使用します



opencl:gpu:2 - GPU である 3 番目のデバイスでのみ OpenCL* ランタイムのみを使用します

level_zero:gpu:1 - GPU である 2 番目のデバイスでのみレベルゼロランタイ
ムのみを使用します

opencl:cpu,level_zero - CPU デバイスでは OpenCL* ランタイムのみを使用
し、サポートされる計算デバイスではレベルゼロランタイムを使用します

デフォルト: 利用可能なすべてのランタイムとデバイスを使用します
このデバイス選択環境変数によって、SYCL* ベースのアプリケーションの実行時に使用するデバイスの選択を制御できます。デバイスを特定のタイプ (GPU やアクセラレーター) またはバックエンド (レベルゼロや OpenCL*) に制限するのに役立ちます。このデバイス選択のメカ
ニズムは、SYCL_DEVICE_FILTER を置き換えるものです。ONEAPI_DEVICE_SELECTORの構文は OpenMP* と共有されており、デバイスを可能にします。詳しい説明は、インテル®
oneAPI DPC++ コンパイラーのドキュメント (英語) を参照してください。
この環境設定は、ランタイムからのデバッグ出力を有効にします。
値:1 - SYCL* プラグインとデバイスが検出され使用されたことを報告します

2 - 引数と結果の値を含む SYCL* API 呼び出しを報告します-1 - 利用可能なすべてのトレースを報告します

デフォルト: 無効191

インテル® oneAPI プログラミング・ガイド

環境変数
ZE_DEBUG

説明
この環境変数は、ランタイムが使用された際にレベルゼロ・バックエンドからのデバッグ出力を有効にします。以下が報告されます。


レベルゼロ API の呼び出し

レベルゼロイベント情報

値: 任意の値で定義された変数 (有効)
デフォルト: 無効

6.3.1.1.3.

サポート向けの診断情報を生成する環境変数

レベルゼロ・バックエンドは、動作を制御して診断を支援するいくつかの環境変数を提供します。


レベルゼロ仕様、コア・プログラミング・ガイド:
https://spec.oneapi.com/level-zero/latest/core/PROG.html#environment-variables (英語)

レベルゼロ仕様、ツール・プログラミング・ガイド:
https://spec.oneapi.com/level-zero/latest/tools/PROG.html#environment-variables (英語)

デバッグ情報の追加リソースは、実行時または事前コンパイル(AOT) 時に、レベルゼロまたは OpenCL* バックエンド(OpenMP* オフロードと SYCL*/DPC++ ランタイムで使用される) によって呼び出されるインテル® グラフィックス・コ
ンパイラーから提供されます。インテル® グラフィックス・コンパイラーは、ターゲットのオフロードデバイス向けの実行
形 式 コー ドを生 成 し ます 。 環境 変 数の 完 全 な リスト は、 https://github.com/intel/intel-graphics-compiler/blob/master/documentation/configuration_flags.md (英語) を参照してください。パフォーマンスの問題をデバッグする際に必要となるのは、次の 2 つです。


IGC_ShaderDumpEnable=1 (デフォルトは 0) によって、インテル® グラフィックス・コンパイラーが生成する
すべての LLVM、アセンブリー、および ISA コードが /tmp/IntelIGC/<application_name> に書き込まれます。



IGC_DumpToCurrentDir=1 (デフォルトは 0) は、IGC_ShaderDumpEnable によって生成されるすべてのファイルを /tmp/IntelIGC/<application_name> に書き込みます。多数のファイルが生成される可能性があるため、一時ディレクトリーを作成することを推奨します。

インテル® oneAPI の異なるバージョン間で OpenMP* オフロードや SYCL* オフロード・アプリケーションのパフォー
マンスの問題が生じる場合、異なるコンパイラー・オプションを使用したり、デバッガーを使用するなど、
IGC_ShaderDumpEnable を有効にして結果ファイルを提供する必要があります。互換性の詳細については、「oneAPI ライブラリーの互換性」を参照してください。

6.3.1.2.

オフロード・インターセプト・ツール

オフロード・ソフトウェア自身に組み込まれているデバッガーと診断情報に加えて、オフロード・パイプラインを介して送信される API 呼び出しとデータを監視するのは有益です。レベルゼロでは、アプリケーションが onetrace または
ze_tracer ツールの引数として実行される場合、アプリケーションのレベルゼロのさまざまな動作がインターセプトされ192インテル® oneAPI プログラミング・ガイド

報告されます。OpenCL* では、OpenCL* 呼び出しをインターセプトして報告するライブラリーを LD_LIBRARY_PATHに追加して、環境変数を設定しファイルへの診断情報生成を制御できます。また、onetrace または cl_tracer を使用して、アプリケーションの OpenCL* API 呼び出しのさまざまな情報をレポートすることもできます。ここでも、アプリケーショ
ンは onetrace や cl_tracer ツールへの引数として実行されます。
6.3.1.2.1.

OpenCL* アプリケーションのインターセプト・レイヤー

このライブラリーは、SYCL* または OpenMP* オフロードのバックエンドとして OpenCL* が使用される場合にデバッ
グおよびパフォーマンス・データを収集します。OpenCL* が SYCL* または OpenMP* オフロードのバックエンドである
場合、このツールはバッファーのオーバーライト、メモリーリーク、ポインターの不一致を検出し、ランタイム・エラー・
メッセージのより詳しい情報を提供します (CPU、FPGA、または GPU のいずれかが計算デバイスである場合にこれらの問題を診断できます)。OpenCL* バックエンドを使用するプログラムで onetrace を利用する場合や、レベルゼロ・バッ
クエンドを使用するプログラムで OpenCL* アプリケーション・ライブラリーのインターセプト・レイヤーを利用する場合には、あまり役立たないことに注意してください。
追加のリソース:

OpenCL* ア プ リ ケ ー シ ョ ン の イ ン タ ー セ プ ト ・ レ イ ヤ ー の ビ ル ド と 使 用 法 に 関 す る 各 種 情 報 は 、
https://github.com/intel/opencl-intercept-layer (英語) から入手できます。

注:
最良の結果を得るには、次のフラグを使用して cmake を実行します。
-DENABLE_CLIPROF=TRUE -DENABLE_CLILOADER=TRUE


同様のツール (CLIntercept) に関する情報は、https://github.com/gmeeker/clintercept (英語) および
https://sourceforge.net/p/clintercept/wiki/Home/ (英語) で入手できます。



OpenCL* アプリケーションのインターセプト・レイヤーの制御に関連する情報は、https:// github.com/intel/
opencl-intercept-layer/blob/master/docs/controls.md (英語) にあります。

GPU の最適化に関する情報は、『oneAPI GPU 最適化ガイド』 (英語 | 日本語)から入手できます。

6.3.1.2.2.

GPU 向けのプロファイル・ツールのインターフェイス (onetrace、cl_tracer および ze_trace)

OpenCL* アプリケーションのインターセプト・レイヤーと同様に、これらツールは、レベルゼロが SYCL* またはOpenMP* バックエンドである場合にデバッグおよびパフォーマンス・データを収集します。レベルゼロは、GPU で実行される計算のバックエンドとしてのみ利用できることに注意してください (現時点で、CPU と FPGA 向けのレベルゼ
ロ・バックエンドはありません)。onetrace ツールは、https://github.com/intel/pti-gpu (英語) にある GPU 向けのプ
ロファイル・ツール・インターフェイス (GPU 向け PTI) プロジェクトの一部です。このプロジェクトには、レベルゼロまたは OpenCL* オフロード・バックエンドからのアクティビティーのみをトレースする ze_tracer や cl_tracer ツールも含
まれています。ze_tracer および cl_tracer ツールは、ほかのバックエンドを使用するアプリケーションで使用されると、出力を生成しませんが、onetrace は使用するオフロード・バックエンドにかかわりなく出力できます。

193

インテル® oneAPI プログラミング・ガイド

onetrace ツールはソースで配布されています。ツールのビルドに関する手順は、https://github.com/intel/pti-gpu/
tree/master/tools/onetrace (英語) を参照してください。このツールは次の機能を提供します。


呼び出しのログ: このモードでは、すべての標準レベルゼロ (L0) API 呼び出しとその引数、およびタイムスタンプ
付きの戻り値をトレースできます。これにより、ホストプログラムが接続された計算デバイスを利用する際に発生する障害の補足情報が得られます。



ホストとデバイスのタイミング: すべての API 呼び出しの存続期間、カーネルの存続期間、およびアプリケーショ
ン全体の実行時間を提供します。



デバイス・タイムライン・モード: 各デバイス・アクティビティーのタイムスタンプを提供します。すべてのタイムスタ
ンプは、同じ (CPU) 時間スケールで示されます。



Chrome* 呼び出しのログモード: chrome://tracing ブラウザーツール (英語) で開くことができる JSON 形式
への API 呼び出しをダンプします。

このデータはオフロードの障害やパフォーマンスの問題をデバッグするのに役立ちます。
追加のリソース:GPU 向けプロファイル・ツール・インターフェイス (GPU 向け PTI) GitHub* プロジェクト (英語)

onetrace ツールの GitHub* (英語)

6.3.1.3.

インテル® ディストリビューションの GDB

インテル® ディストリビューションの GDB は、プログラムの状態を調査および変更できるアプリケーション・デバッガーです。アプリケーションのホスト部分とデバイスにオフロードされたカーネルの両方を、同じデバッグセッションでシー
ムレスにデバッグできます。このデバッガーは、CPU、GPU、および FPGA エミュレーション・デバイスをサポートします。
主な機能を以下に示します。
GPU デバイスに自動的に接続してデバッグイベントを監視

デバッグ用に JIT コンパイルされた、または動的にロードされたカーネルバイナリーを自動検出

プログラムの実行を停止するブレークポイントを設定 (カーネル内部と外部の両方)



スレッドのリスト表示、現在のスレッド・コンテキストへの切り替えアクティブな SIMD レーンのリスト表示、現在の SIMD レーンのコンテキストをスレッドごとに切り替え

複数のスレッドと SIMD レーン・コンテキストの式値の評価と出力



レジスター値の調査と変更

マシン命令を逆アセンブル



関数呼び出しスタックの表示とナビゲート



ソースと命令レベルのステップ実行

非停止およびすべて停止のデバッグモード

194インテル® oneAPI プログラミング・ガイド

インテル® プロセッサー・トレースを使用した実行の記録 (CPU のみ)

インテル® ディストリビューションの GDB の詳細とドキュメントへのリンクは、『インテル® ディストリビューションのGDB 導入ガイド (Linux* 版)』 (英語) または『インテル® ディストリビューションの GDB 導入ガイド(Windows* 版)』 (英語) をご覧ください。

6.3.1.4.

オフロード向けインテル® Inspector

インテル® Inspector は、シリアルおよびマルチスレッド・アプリケーションを開発するユーザー向けの動的メモリーおよびスレッドエラーを検出するツールです。動的に生成されたオフロードコードだけでなく、アプリケーションのネイティ
ブコードの正当性を検証するのに利用できます。
前述のツールや手法とは異なり、インテル® Inspector は GPU または FPGA と通信するオフロードコードのエラーを検出することはできません。インテル® Inspector では、CPU をターゲットとしてカーネルを実行するように SYCL* または OpenMP* ランタイムを設定する必要があります。解析を実行する前に、次の環境変数を設定する必要があります。
CPU デバイスでカーネルを実行するように SYCL* アプリケーションを設定します。

$ export SYCL_DEVICE_FILTER=opencl:cpu



CPU デバイスでカーネルを実行するように OpenMP* アプリケーションを設定します。

$ export OMP_TARGET_OFFLOAD=MANDATORY$ export LIBOMPTARGET_DEVICETYPE=cpu


JIT コンパイラーまたはランタイムでコード解析とトレース有効にします。

$ export CL_CONFIG_USE_VTUNE=True$ export CL_CONFIG_USE_VECTORIZER=false

次のいずれかのコマンドを使用して、コマンドラインから解析を開始します。インテル® Inspector のグラフィカル・ユー
ザー・インターフェイスからも開始できます。


メモリー: inspxe-cl -c mi3 -- <app> [app_args]



スレッド化: inspxe-cl -c ti3 -- <app> [app_args]

次のコマンドを使用して解析結果を表示します。
$ inspxe-cl -report=problems -report-all

SYCL* や OpenMP* オフロードプログラムが OpenCL* バックエンドに不正なポインターを渡したり、誤ったスレッド
からバックエンドに不正なポインターを渡す場合、インテル® Inspector は問題を警告します。これは、インターセプト・
レイヤーやデバッガーを使用して問題を見つけるよりも容易な場合があります。
『インテル® Inspector ユーザーガイド (Linux* 版)』 (英語) または『インテル® Inspector ユーザーガイド (Windows*版)』 (英語) で詳細を参照できます。

195インテル® oneAPI プログラミング・ガイド

6.3.2 オフロード処理のトレース
GPU に計算をオフロードするプログラムが開始される場合、プログラムの実行に関連する多くのコンポーネントが動作します。マシン非依存のコードをマシン依存のコードにコンパイルし、データとバイナリーをデバイスにコピーして、結果を戻す必要があります。ここでは、「oneAPI デバッグツール」で説明したツールを使用して、すべてのアクティビ
ティーをトレースする方法を示します。

6.3.2.1.

カーネル設定時間

オフロードコードをデバイスで実行する前に、マシン非依存のカーネルをターゲットデバイス向けにコンパイルしてコードをデバイスにコピーする必要があります。このカーネルのセットアップ時間が考慮されていないと、ベンチマークを複雑にしたり歪めたりする可能性があります。ジャストインタイム・コンパイルは、オフロード・アプリケーションのデバッグに遅延を引き起こすことがあります。
OpenMP* オフロードプログラムでは、環境変数 LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を設定すると、オフロードコード ModuleBuild のビルドに必要な時間が報告されます。これをプログラムの実行時間全体と比較します。
SYCL* オフロードプログラムでは、カーネルのセットアップ時間を判断するのはさらに困難になります。


レベルゼロまたは OpenCL* がバックエンドである場合、onetrace や ze_tracer よって返されるデバイスのタイ
ミングとタイムラインから、カーネルのセットアップ時間を求められます。



OpenCL* がバックエンドの場合、OpenCL* アプリケーションのインターセプト・レイヤーを使用して情報を取 得 す る 際 に 、 BuildLogging 、 KernelInfoLogging 、 CallLogging 、 CallLoggingElapsedTime 、
KernelInfoLogging、HostPerformanceTiming、HostPerformanceTimeLogging、ChromeCallLogging、または CallLoggingElapsedTime フラグを設定できます。onetrace や cl_tracer よって返されるデバ
イスのタイミングおよびタイムラインから、カーネルのセットアップ時間を求めることもできます。

この方法により、LIBOMPTARGET_PLUGIN_PROFILE=T によって戻される情報を補足できます。
インテル® VTune™ プロファイラーがカーネルのセットアップ時間を解析する方法の詳細については、「Linux* カーネ
ル解析を有効にする」を参照してください。

6.3.2.2.

バッファーの作成、サイズ、およびコピーの監視

バッファーが作成された時期、作成されたバッファーの数、およびそれらが再利用されるか、また常に作成および破棄されるかを知ることは、オフロード・アプリケーションのパフォーマンスを最適化する上で重要な鍵となります。しかし、OpenMP* や SYCL* などの高レベル・プログラミング言語を使用する場合、それらは必ずしも明確でない可能性がありユーザーからバッファーの管理は隠匿されます。
高レベルでは、プログラムの実行時に LIBOMPTARGET_DEBUG および SYCL_PI_TRACE 環境変数を使用して、バッファーに関連するアクティビティーを追跡できます。LIBOMPTARGET_DEBUG は、SYCL_PI_TRACE よりも多くの情報

196インテル® oneAPI プログラミング・ガイドを提供します (作成されたバッファーアドレスとサイズをレポート)。SYCL_PI_TRACE は、API 呼び出しをレポートするだけであり、バッファーアドレスやサイズに関する情報は含まれません。
低レベルでは、レベルゼロのバックエンドを使用する場合、onetrace や ze_tracer の呼び出しログモードは、引数を含
む す べ て の レ ベ ル ゼ ロ API 呼 び 出 し に 関 す る 情 報 を 提 供 し ま す 。 例 え ば 、 バ ッ フ ァ ー 作 成 呼 び 出 し(zeMemAllocDevice など) で、デバイスとの間で渡される結果バッファーのサイズを取得できるため役立つことがあります。onetrace と ze_tracer は、デバイス・タイムライン・モードですべてのゼロレベルデバイス間とのアクティビ
ティー (メモリー転送を含む) をダンプすることができます。アクティビティーごとに、追加 (コマンドリストへ)、送信(キューへ)、開始と終了時間を取得できます。
OpenCL* が バ ッ ク エ ン ド の 場 合 、 OpenCL* ア プ リ ケ ー シ ョ ン の イ ン タ ー セ プ ト ・ レ イ ヤ ー を 使 用 す る 際 に 、CallLogging、CallLoggingElapsedTime、および ChromeCallLogging フラグを設定して同様の情報を取得できます。onetrace や ze_tracer の呼び出しログモードは、引数を含むすべての OpenCL* API 呼び出しに関する情報を提供します。上記と同様に、onetrace と ze_tracer を使用すると、デバイス・タイムライン・モードですべての OpenCL*
デバイス間とのアクティビティー (メモリー転送を含む) をダンプすることができます。

6.3.2.3.

合計転送時間合計データ転送時間をカーネル実行時間と比較することは、接続されているデバイスへの計算のオフロードが有益であるか判断することが重要になることがあります。
OpenMP* オ フ ロ ー ド プ ロ グ ラ ム で は 、 LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を 設 定 す ると 、 ビ ル ド(DataAlloc)、オフロードデバイスの読み取り (DataRead)、および書き込み (DataWrite) に必要な時間がレポートされます (ただし合計として)。
SYCL* を使用する C++ プログラムのデータ転送時間を判断するのはさらに困難になります。


レベルゼロまたは OpenCL* がバックエンドである場合、onetrace や ze_tracer よって返されるデバイスのタイ
ミングとタイムラインから、合計データ転送時間を求められます。



OpenCL* がバックエンドの場合、onetrace または cl_tracer を使用するか、OpenCL* アプリケーションのイン
タ ー セ プ ト ・ レ イ ヤ ー を 使 用 し て 情 報 を 取 得 す る 際 に 、 BuildLogging 、 KernelInfoLogging 、
CallLogging 、 CallLoggingElapsedTime 、 KernelInfoLogging 、 HostPerformanceTiming 、
HostPerformanceTimeLogging、ChromeCallLogging、または CallLoggingElapsedTime フラグを設定できます。

インテル® VTune™ プロファイラーがカーネルのセットアップ時間を解析する方法の詳細については、『インテル®
VTune™ プロファイラー・ユーザーズガイド』の「GPU オフロード解析」、「ホットスポット・レポート」、「GPU 計算/メディ
ア・ホットスポット・ビュー」を参照してください。

6.3.2.4.

カーネル実行時間

OpenMP* オフロードプログラムでは、LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を設定すると、オフロードされたすべてのカーネル (Kernel#…) の合計実行時間が報告されます。

197

インテル® oneAPI プログラミング・ガイド

SYCL* を使用するオフロードカーネル向け:•

レベルゼロ または OpenCL* バックエンドでは、onetrace や ze_tracer のデバイス・タイミング・モードを使用してすべてのカーネルのデバイスでの実行時間を取得できます。



OpenCL* がバックエンドの場合、onetrace または cl_tracer を使用するか、OpenCL* アプリケーションのインターセプト・レイヤーを使用して情報を取得する際に、次のフラグを設定できます: CallLoggingElapsedTime、
DevicePerformanceTiming、DevicePerformanceTimeKernelInfoTracking、
DevicePerformanceTimeLWSTracking、DevicePerformanceTimeGWSTracking、
ChromePerformanceTiming、ChromePerformanceTimingInStages。

インテル® VTune™ プロファイラーがカーネルの実行時間を解析する方法の詳細については、「アクセラレーター解析グループ」を参照してください。

6.3.2.5.

デバイスカーネルが呼び出され、スレッドが生成される場合

場合によってには、オフロードカーネルが作成され、実行を開始するかなり前にデバイスへ転送されることがあります(通常は、カーネルの実行に必要なすべてのデータと制御が転送された後にのみ)。
インテル® ディストリビューションの GDB を使用してデバイスカーネルにブレークポイントを設定できます。そして、
カーネル引数の照会、スレッドの生成と破棄の監視、コード内の現在のスレッドの位置とリスト表示 (info thread を使用) などが行えます。

6.3.3 オフロード処理のデバッグ
6.3.3.1.

異なるランタイムまたは計算デバイスで実行

オフロードプログラムが正常に実行されなかったか、生成された結果が正しくない場合、比較的容易な正当性の確認方
法は、OpenMP* アプリケーションでは LIBOMPTARGET_PLUGIN と OMP_TARGET_OFFLOAD 環境変数を、またSYCL* アプリケーションでは SYCL_DEVICE_FILTER 環境変数を使用して、別のランタイム (OpenCL* とレベルゼロ)
または計算デバイス (CPU と GPU) でアプリケーションを実行することです。異なるランタイム間で再現されるエラーは、
ほとんどの場合、ランタイムの問題として排除できます。そしてデバイス間で再現されるエラーの大部分は、不良ハード
ウェアの問題を排除できます。

6.3.3.2.

CPU 実行をデバッグ

オフロードコードを CPU で実行するには、ホスト実装と OpenCL* の CPU バージョンという 2 つのオプションがあります。ホスト実装は、オフロードコードのネイティブ実装であり、オフロードされないコードと同じようにデバッグできます。OpenCL* の CPU バージョンは、OpenCL* ランタイムとコード生成プロセスを通過しますが、最終的にインテル®
oneTBB ランタイムで実行される通常の並列コードになります。繰り返しますが、これにより慣れ親しんだアセンブリーと並列処理メカニズムのデバッグ環境が提供されています。ポインターはスタック全体にアクセスでき、データを直接参照できます。また、オペレーティング・システム・プロセスの通常の上限を超えるメモリー制限はありません。

198インテル® oneAPI プログラミング・ガイド

CPU オフロード実行のエラーを検出して修正すると、GPU オフロード実行で発生するエラーよりもはるかに少ない労力でエラーを解決でき、GPU やほかのアクセラレーターが接続されたシステムを利用する必要もなくなります。
OpenMP* アプリケーションでホスト実装を適用するには、target または device 構造を削除して、通常のホスト
OpenMP* コードに置き換えます。LIBOMPTARGET_PLUGIN=OPENCL が設定され、GPU オフロードが無効になると、オフロードコードは OpenMP* ランタイムで実行され、インテル® oneTBB が並列処理を行います。
SYCL* アプリケーションで SYCL_DEVICE_FILTER=host を設定するとホストデバイスはシングルスレッドで実行を行います。これは、データ競合やデッドロックなどスレッド化の問題が実行エラーの原因であるか判断するのに役立ちます。SYCL_DEVICE_FILTER=opencl:cpu に設定すると、CPU の OpenCL* ランタイムが使用され、インテル®
oneTBB が並列処理を行います。

6.3.3.3.

インテル® ディストリビューションの GDB を使用して GPU 実行をデバッグ

インテル® ディストリビューションの GDB については、『インテル® ディストリビューションの GDB 導入ガイド (Linux*版)』 (英語) または『インテル® ディストリビューションの GDB 導入ガイド (Windows* 版)』 (英語) に詳しく記載されています。有用なコマンドについては、インテル® ディストリビューションの GDB の「リファレンス・シート」 (英語) で簡単に説明されています。ただし、GDB を使用して GPU アプリケーションをデバッグする方法は、ホストでの手順とは若干異なるため (一部のコマンドの使い方が異なり、見慣れない出力が表示されることがあります)、それらの違いの一部をここで紹介します。
「インテル® ディストリビューションの GDB を使用したデバッグのチュートリアル (Linux* 版)」 (英語) では、SYCL* プロ
グラムのデバッグセッションを開始し、カーネル内にブレークポイントを設定し、プログラムを実行して GPU にオフ
ロードしローカル値を出力し、スレッドの SIMD レーン 5 を切り替えて変数を再度出力するサンプルのデバッグセッ
ションを紹介しています。
通常の GDB と同様に、command <CMD> には GDB の help <CMD> コマンドを使用して、<CMD> の情報テキストを読み取ります。次に例を示します。
(gdb) help info threads
Display currently known threads.Usage: info threads [OPTION]...[ID]...
If ID is given, it is a space-separated list of IDs of threads to display.Otherwise, allthreads are displayed.
Options:-gidShow global thread IDs.

6.3.3.3.1.

GDB でインフェリアー、スレッド、および SIMD レーンの参照

アプリケーションのスレッドは、デバッガーによって一覧表示できます。表示される情報には、スレッド ID とスレッドが停止している位置が含まれます。GPU スレッドの場合、デバッガーはアクティブな SIMD レーンも表示します。
上記の例では、GDB の info threads コマンドでスレッドを表示していますが、見慣れない形式で情報が示されることがあります。

199

インテル® oneAPI プログラミング・ガイド

Id
1.1
1.2

Target Id
Frame
Thread <id omitted> <frame omitted>
Thread <id omitted> <frame omitted>* 2.1:1
2.1:[3 5 7]
2.2:[1 3 5 7]
2.3:[1 3 5 7]

Thread 1073741824
hread 1073741824
Thread 1073741888
Thread 1073742080<frame> at array-transform.cpp:61<frame> at array-transform.cpp:61<frame> at array-transform.cpp:61<frame> at array-transform.cpp:61

GDB は次の形式でスレッドを表示します: <インフェリアー番号>.<スレッド番号>:<SIMD レーン/s>
例えば、スレッド ID 2.3:[1 3 5 7] は、インフェリアー 2 で実行されるスレッド 3 の SIMD レーン 1、3、5 および 7 を意味します。
GDB 用語の「inferior (インフェリアー)」は、デバッグされるプロセスを指します。GPU にオフロードするプログラムのデ
バッグセッションには、通常 2 つのインフェリアーがあります。プログラムのホストを示す「ネイティブ・インフェリアー」(上記のインフェリアー 1) と、GPU デバイスを示す「リモート・インフェリアー」 (上記のインフェリアー 2) です。インテル®
ディストリビューションの GDB は自動的に GPU インフェリアーを生成するため、特に操作は必要ありません。
式の値を出力すると、式は現在のスレッドの現在の SIMD レーンのコンテキストで評価されます。thread 3:4、
thread :6、または thread 7 などの thread コマンドを使用して、スレッドと SIMD レーンを切り替えることができます。最初のコマンドは、スレッド 3 と SIMD レーン 4 に切り替えます。2 番目のコマンドは、現在のスレッドで SIMD
レーン 6 に切り替えます。3 番目のコマンドは、スレッド 7 に切り替えます。選択されるデフォルトレーンは、以前に選択したレーン (アクティブであれば)、またはスレッド内で最初にアクティブになったレーンのどちらかになります。
thread apply コマンドは、同様に広域または集中的である可能性があります (これにより、変数を調査するコマンド
からの出力を制限しやすくなります)。SIMD レーンのデバッグの詳細と例については、「インテル® ディストリビューショ
ンの GDB を使用したデバッグのチュートリアル (Linux* 版)」 (英語) を参照してください。
GDB のスレッドとインフェリアーに関する詳細は、以下ををご覧ください。
https://sourceware.org/gdb/current/onlinedocs/gdb/Threads.html (英語)https://sourceware.org/gdb/current/onlinedocs/gdb/Inferiors-Connections-andPrograms.html#Inferiors-Connections-and-Programs (英語)

6.3.3.3.2.

スケジューラーの制御

デフォルトでは、スレッドがブレークポイントに到達すると、デバッガーはブレーク・ポイント・ヒット・イベントをユーザーに通知する前にすべてのスレッドを停止します。これは GDB のすべて停止モードです。非停止モードでは、ほかのスレッドが実行される間、スレッドの停止イベントが表示されます。
すべて停止モードでは、スレッドが再開されると (例: continue コマンドで通常のように再開する、または next コマ
ンドでステップ実行する場合)、ほかのすべてのスレッドも再開されます。スレッド化されたアプリケーションで複数のブ
レークポイントが設定されていると、ブレークポイントに到達した次のスレッドが続くスレッドではない可能性があるた
め、混乱を招く可能性があります。

200

インテル® oneAPI プログラミング・ガイド

set scheduler-locking コマンドを使用することで、現在のスレッドが再開されたときにほかのスレッドが再開されないように制御することができます。これは、現在のスレッドのみが命令を実行しているときに、ほかのスレッドの介入を避けるのに有効です。help set scheduler-locking と入力すると利用可能なオプションが表示されます。
詳細は、https://sourceware.org/gdb/current/onlinedocs/gdb/Thread-Stops.html (英語) をご覧ください。SIMD
レーンは個別に再開できないことに注意してください。これは、ベースとなるスレッドとともに再開されます。
非停止モードのデフォルトでは、現在のスレッドのみが再開されます。すべてのスレッドを再開するには、continue コ
マンドで -a フラグを指定します。
6.3.3.3.3.

1 つ以上のスレッド/レーンの情報をダンプ (Thread Apply)

プログラム状態を調査するコマンドは、通常、現在のスレッドの現在の SIMD レーンのコンテキストに適用されます。複数のコンテキストの値を調査することが必要なこともあります。そのような場合、thread apply コマンドを使用します。例えば、以下はスレッド 2,5 の SIMD レーン 3-5 に対して print element コマンドを実行します。
(gdb) thread apply 2.5:3-5 print element

同様に、以下は、現在のスレッドの SIMD レーン 3、5、および 6 のコンテキストに対し print element コマンドを実行します。
(gdb) thread apply :3 :5 :6 print element

6.3.3.3.4.

ブレークポイント停止後の GPU コードのステップ実行

GPU にオフロードされたカーネル内で停止するには、カーネル内のソース行にブレークポイントを設定するだけです。
GPU スレッドがそのソース行に到達すると、デバッガーは実行を停止してブレークポイントの到達を示します。ソース行
単位でスレッドをステップ実行するには、step または next コマンドを使用します。step コマンドは関数にステップ
インし、next コマンドは関数呼び出しをステップオーバーします。ステップ実行する前に、ほかのスレッドの介入を避けるため set scheduler-locking step を設定することを推奨します。
6.3.3.3.5.

インテル® ディストリビューションの GDB で使用する DPC++ 実行形式をビルド

ホスト・アプリケーションのデバッグと同様に、GPU でデバッグ可能なバイナリーを作成するには、いくつかの追加フラグを指定する必要があります。詳細については、『インテル® ディストリビューションの GDB 導入ガイド (Linux* 版)』 (英語) をご覧ください。
JIT コンパイルを行う際にスムーズなデバッグを可能にするには、-g フラグを指定してコンパイラーのデバッグ情報生
成を有効にし、アプリケーションのホストと JIT コンパイルカーネルの両方で -O0 フラグを指定して最適化を無効にします。カーネルのフラグはリンク時に適用されます。次に例を示します。


プログラムのコンパイル: icpx -fsycl -g -O0 -c myprogram.cpp

プログラムのリンク: icpx -fsycl -g -O0 myprogram.oCmake を 使 用 し て プ ロ グ ラ ム を ビ ル ド す る 場 合 、 CMAKE_BUILD_TYPE の Debug タ イ プ を 使 用 し 、CMAKE_CXX_FLAGS_DEBUG 変数に -O0 を追加します。次に例を示します。
201

インテル® oneAPI プログラミング・ガイド$ set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")

デバッグ向けにビルドされたアプリケーションは、通常の「リリース」ビルドで最適化されたアプリケーションよりも起動に時間がかかる場合があります。そのため、デバッガーで起動すると、プログラムの実行速度が遅くなったように感じられることがあります。これにより問題が生じる場合、大規模なアプリケーションの開発者は、プログラムの実行時ではな
くビルド時に JIT オフロードコードを事前 (AOT) コンパイルすることを推奨します (このとき、-g -O0 を使用するとビルドに時間がかかる場合があります)。詳細については、「コンパイルの手順」をご覧ください。
GPU 向けの事前コンパイルを行う場合、ターゲットデバイスに対応したデバイスタイプを指定する必要があります。
次のコマンドを使用して、現在のマシンで利用可能な GPU デバイスオプションを確認できます:。
$ ocloc compile --help

さらに、カーネルのデバッグモードを有効にします。次の AOT コンパイルの例は、KBL デバイスをターゲットにしています。
$ dpcpp -g -O0 -fsycl-targets=spir64_gen-unknown-unknown-sycldevice \-Xs "-device kbl -internal_options -cl-kernel-debug-enable -options -cl-opt-disable"
myprogram.cpp

6.3.3.3.6.

インテル® ディストリビューションの GDB で使用する DPC++ 実行形式をビルド

プログラムのコンパイルとリンクに -g -O0 フラグを使用します。次に例を示します。
$ icpx -fiopenmp -O0 -fopenmp-targets=spir64 -c -g myprogram.cpp$ icpx -fiopenmp -O0 -fopenmp-targets=spir64 -g myprogram.o

次の環境変数を設定して最適化を無効にし、カーネルのデバッグ情報を有効にします。
$ export LIBOMPTARGET_OPENCL_COMPILATION_OPTIONS="-g -cl-opt-disable"$ export LIBOMPTARGET_LEVEL0_COMPILATION_OPTIONS="-g -cl-opt-disable"

6.3.3.4.

GPU 実行をデバッグ

オフロードプログラムの一般的な問題は、実行に失敗し、追加情報をほとんど持たない OpenCL* エラーが生成されることです。OpenCL* アプリケーションのインターセプト・レイヤーと onetrace、ze_tracer、および cl_tracer を使用して、このエラーに関する詳細情報を取得できます。これは、開発者が問題の原因を特定するのに役立ちます。
6.3.3.4.1.

OpenCL* アプリケーションのインターセプト・レイヤー

このライブラリーを使用する場合、Buildlogging、ErrorLogging、および USMChecking=1 オプションを使用してエラーの原因を特定できます。

202

インテル® oneAPI プログラミング・ガイド

1.

次のテキストを含む clintercept.conf ファイルをホーム・ディレクトリーに作成します。

SimpleDumpProgramSource=1
CallLogging=1
LogToFile=1//KernelNameHashTracking=1
BuildLogging=1
ErrorLogging=1
USMChecking=1//ContextCallbackLogging=1// Profiling knobs KernelInfoLogging=1 DevicePerformanceTiming=1
DevicePerformanceTimeLWSTracking=1
DevicePerformanceTimeGWSTracking=12.

次のように cliloader を使用してアプリケーションを実行します。

<OCL_Intercept_Install_Dir>/bin/cliloader/cliloader -d ./<app_name> <app_args>

3.

~CLIntercept_Dump/<app_name> ディレクトリーで次の結果を確認します。
‐

clintercept_report.txt: プロファイルの結果‐

clintercept_log.txt: OpenCL* の問題をデバッグする際に使用される OpenCL* 呼び出しログ

次のテキストは、CL_INVALID_ARG_VALUE (-50) ランタイムエラーが発生したプログラムで生成されたログファ
イルの例の一部です。
...
<<<< clSetKernelArgMemPointerINTEL -> CL_SUCCESS >>>>
clGetKernelInfo( _ZTSZZ10outer_coreiP5mesh_i16dpct_type_1c0e3516dpct_type_60257cS2_S2_S2_S2_S
2_S2 _S2_S2_fS2_S2_S2_S2_iENKUlRN2cl4sycl7handlerEE197->45clES6_EUlNS4_7nd_itemILi3EEEE225>13 ): param_name = CL_KERNEL_CONTEXT (1193)<<<< clGetKernelInfo -> CL_SUCCESS >>>>
clSetKernelArgMemPointerINTEL( _ZTSZZ10outer_coreiP5mesh_i16dpct_type_1c0e3516dpct_type_60257
cS2_ S2_S2_S2_S2_S2_S2_S2_fS2_S2_S2_S2_iENKUlRN2cl4sycl7handlerEE197>45clES6_EUlNS4_7nd_itemILi3EEEE225->13 ): kernel = 0xa2d51a0, index = 3, value = 0x41995e0
mem pointer 0x41995e0 is an UNKNOWN pointer and no device support shared system pointers!
ERROR! clSetKernelArgMemPointerINTEL returned CL_INVALID_ARG_VALUE (-50)<<<< clSetKernelArgMemPointerINTEL -> CL_INVALID_ARG_VALUE

この例は、次の値がエラーのデバッグに役立ちます。


ZTSZZ10outer_coreiP5meshindex = 3, value = 0x41995e0

このデータによりどのカーネルに問題があるか、またどの引数に問題があるかが分かり、その理由を特定できます。

203インテル® oneAPI プログラミング・ガイド

6.3.3.4.2.

onetrace、ze_tracer、および cl_tracer

OpenCL* アプリケーションのインターセプト・レイヤーと同様に、onetrace、ze_tracer および cl_tracer ツールはレベ
ルゼロのランタイムエラーの原因を検出するのに役立ちます。
onetrace または ze_tracer ツールを使用してレベルゼロにおける問題の根本的な原因を特定します (cl_tracer は、OpenCL* の問題の同様の原因を特定するのに使用されます)。
1.

呼び出しログモードでアプリケーションを実行します。ツールの出力をファイルにリダイレクトすることを推奨します。

$ ./onetrace -c ./<app_name> <app_args> [2> log.txt]

ze_tracer のコマンドも同様です。onetrace を ze_tracer に置き換えるだけです。
1.

呼び出しトレースを確認してエラーを特定します (log.txt)。次に例を示します。

>>>> [102032049] zeKernelCreate: hModule = 0x55a68c762690 desc = 0x7fff865b5570 {29 0 0 GEMM}
phKernel = 0x7fff865b5438 (hKernel = 0)<<<< [102060428] zeKernelCreate [28379 ns] hKernel = 0x55a68c790280 -> ZE_RESULT_SUCCESS (0)...
>>>> [102249951] zeKernelSetGroupSize: hKernel = 0x55a68c790280 groupSizeX = 256 groupSizeY =1 groupSizeZ = 1<<<< [102264632] zeKernelSetGroupSize [14681 ns] -> ZE_RESULT_SUCCESS (0)>>>> [102278558] zeKernelSetArgumentValue: hKernel = 0x55a68c790280 argIndex = 0 argSize = 8
pArgValue = 0x7fff865b5440<<<< [102294960] zeKernelSetArgumentValue [16402 ns] -> ZE_RESULT_SUCCESS (0)>>>> [102308273] zeKernelSetArgumentValue: hKernel = 0x55a68c790280 argIndex = 1 argSize = 8
pArgValue = 0x7fff865b5458<<<< [102321981] zeKernelSetArgumentValue [13708 ns] -> ZE_RESULT_ERROR_INVALID_ARGUMENT(2013265924)>>>> [104428764] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 2 argSize = 8
pArgValue = 0x7ffe289c7e60<<<< [104442529] zeKernelSetArgumentValue [13765 ns] -> ZE_RESULT_SUCCESS (0)>>>> [104455176] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 3 argSize = 4
pArgValue = 0x7ffe289c7e2c<<<< [104468472] zeKernelSetArgumentValue [13296 ns] -> ZE_RESULT_SUCCESS (0) ...

この例のログには次のデータが示されています。


問題の原因となるレベルゼロ API 呼び出し (zeKernelSetArgumentValue)

問題の原因 (ZE_RESULT_ERROR_INVALID_ARGUMENT)

引数インデックス (argIndex = 1)

不正な値の場所 (pArgValue = 0x7fff865b5458)



カーネルハンドル (hKernel = 0x55a68c790280)、この問題が検出されたカーネル名を示します (GEMM)「ファイルへのリダイレクト」オプションを省略して、すべての出力 (アプリケーションの出力 + ツールの出力) を 1 つのストリームにダンプすることで、より多くの情報を取得できます。単一のストリームにダンプを行うことで、アプリケー

204インテル® oneAPI プログラミング・ガイド

ションの出力に関連するエラーの原因を特定するのに役立つことがあります (例えば、アプリケーションの初期化と計算の最初のフェーズでエラーが発生しているなどが分かります)。
Level Zero Matrix Multiplication (matrix size: 1024 x 1024, repeats 4 times) Target device:
Intel® Graphics [0x3ea5]...
>>>> [104131109] zeKernelCreate: hModule = 0x55af5f39ca10 desc = 0x7ffe289c7f80 {29 0 0 GEMM}
phKernel = 0x7ffe289c7e48 (hKernel = 0)<<<< [104158819] zeKernelCreate [27710 ns] hKernel = 0x55af5f3ca600 -> ZE_RESULT_SUCCESS(0) ...
>>>> [104345820] zeKernelSetGroupSize: hKernel = 0x55af5f3ca600 groupSizeX = 256 groupSizeY =1 groupSizeZ = 1<<<< [104360082] zeKernelSetGroupSize [14262 ns] -> ZE_RESULT_SUCCESS (0)>>>> [104373679] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 0 argSize = 8
pArgValue = 0x7ffe289c7e50<<<< [104389443] zeKernelSetArgumentValue [15764 ns] -> ZE_RESULT_SUCCESS (0)>>>> [104402448] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 1 argSize = 8
pArgValue = 0x7ffe289c7e68<<<< [104415871] zeKernelSetArgumentValue [13423 ns] -> ZE_RESULT_ERROR_INVALID_ARGUMENT(2013265924)>>>> [104428764] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 2 argSize = 8
pArgValue = 0x7ffe289c7e60<<<< [104442529] zeKernelSetArgumentValue [13765 ns] -> ZE_RESULT_SUCCESS (0)>>>> [104455176] zeKernelSetArgumentValue: hKernel = 0x55af5f3ca600 argIndex = 3 argSize = 4
pArgValue = 0x7ffe289c7e2c<<<< [104468472] zeKernelSetArgumentValue [13296 ns] -> ZE_RESULT_SUCCESS (0) ...
Matrix multiplication time: 0.0427564 sec Results are INCORRECT with accuracy: 1 ...
Matrix multiplication time: 0.0430995 sec Results are INCORRECT with accuracy: 1 ...
Total execution time: 0.381558 sec

6.3.3.5.

正当性

オフロードコードは、接続された計算デバイスで大量の情報を効率良く処理するカーネル、または一部の入力パラメー
ターから大量の情報を生成する際に利用されます。それらのカーネルがクラッシュすることなく実行されると、多くの場
合、正しい結果が得られていないことはプログラム実行のかなり後で判明します。
そのような場合、どのカーネルが誤った結果を生成しているか特定するのは困難です。誤った結果を生成するカーネルを特定する方法として、プログラムを 2 回実行することが考えられます。最初はホストベースの実装を実行し、2 回目はオ
フロード実装を実行してすべてのカーネル (多くは個々のファイル) の入力と出力を取得します。次に、結果を比較して、どのカーネルが予期しない結果を生成しているか確認します (特定のイプシロンで、オフロード・ハードウェアの操作順
序やネイティブの精度の違いにより、結果の最後の 1 桁もしくは 2 桁がホストコードと異なる可能性があります)。
誤った結果を生成するカーネルが特定されたら、インテル® ディストリビューションの GDB を使用して原因を調査します。基本情報と詳細なドキュメントへのリンクについては、『インテル® ディストリビューションの GDB を使用したデバッ
グのチュートリアル (Linux* 版)』 (英語) を参照してください。
SYCL* と OpenMP* はどちらもオフロードされたカーネル内で標準のプリントメカニズム (SYCL* と C++ OpenMP*では printf、Fortran OpenMP* オフロードでは print * など) を利用できます。これを使用して、実行中の動作を確認できます。出力元のスレッドと SIMD レーンをプリントし、プリントされる情報がプリント時に一貫性を持つように、同期メカニズムを追加することを検討してください。ストリームクラスを使用して DPC++ で同様のことを行う例は、『oneAPI GPU 最適化ガイド』記載されています。OpenMP* オフロード向けの SYCL* の説明を同様のアプローチを適用できます。
205

インテル® oneAPI プログラミング・ガイド

ヒント:
SYCL* カーネルでは printf は冗長的になる可能性があります。簡単にするため次のマクロを追加します。
#ifdef __SYCL_DEVICE_ONLY__#define CL_CONSTANT __attribute__((opencl_constant))#else#define CL_CONSTANT#endif#define PRINTF(format, ...){ \static const CL_CONSTANT char _format[] = format; \sycl::ONEAPI::experimental::printf(_format, ## __VA_ARGS__); }使用例: PRINTF("My integer variable:%d\n", (int) x);

6.3.3.6.

障害

SYCL* または OpenMP* オフロード言語の誤った用法が原因で JIT コンパイルが失敗すると、プログラムはエラーで終了します。
SYCL* では事前コンパイルされていることを判定できない場合、OpenCL* バックエンドを選択して OpenCL* アプリ
ケーションのインターセプト・レイヤーを使用すると、構文エラーを持つカーネルを特定できることがあります。
ロジックエラーは、実行中にクラッシュが発生したり、エラーメッセージが表示されることがあります。これには以下が含まれます:


誤ったコンテキストに属するバッファーをカーネルに渡す場合

this ポインターをクラス要素ではなくカーネルに渡す場合



デバイスバッファーではなくホストバッファーを渡す場合



カーネルで使用されなくても、初期化されていないポインターを渡す場合

インテル® ディストリビューションの GDB (またはネイティブ GDB) を使用して注意深く調査することで、生成されたすべてのコンテキストのアドレスを記録してオフロードカーネルに渡されるアドレスが正しいコンテキストに属するか確認できます。同様に、変数のアドレスがそれを含むクラスでなく、変数自身のアドレスと一致するか確認できます。
OpenCL* 割り当て用のインターセプト・レイヤーまたは、onetrace/cl_tracer を使用して、適切なバックエンドを選択する方がバッファーとアドレスをトレースするよりも簡単なことがあります。OpenCL* バックエンドを使用する場合、
CallLogging、BuildLogging、ErrorLogging および USMChecking を設定してプログラムを実行すると、コード内のどのエラーが OpenCL* エラーを生成したか明らかにする出力が生成されます。
onetrace や ze_tracer の呼び出しログやデバイス・タイムラインを参照すると、レベルゼロのバックエンドからのエラーの原因を理解するのに役立つ追加のエラー情報が得られます。これは、上記の論理エラーを検出するのに役立ちます。
レベルゼロ・バックエンドを使用してデバイスにオフロードする際にコードでエラーが発生する場合、OpenCL* バック
エンドを試してみてください。プログラムが正常に機能する場合、レベルゼロのバックエンドにエラーをレポートしてく
206インテル® oneAPI プログラミング・ガイド

ださい。デバイス向けの OpenCL* バックエンドでもエラーが再現する場合、OpenCL* CPU バックエンドを試します。
OpenMP* オ フ ロ ー ド で は 、 OMP_TARGET_OFFLOAD を CPU に 設 定 す る こ と で 指 定 で き ま す 。 SYCL* で は 、
SYCL_DEVICE_FILTER=opencl:cpu を設定します。CPU 上でのデバッグはかなり容易になり、データのコピーとプログラムのデバイスへの変換によって生じる複雑性も排除できます。
問題が発生する可能性があるロジックの例として、次の SYCL* コードで parallel_for を実装する際に使用されるラムダ関数でキャプチャーされる対象を考えます。
class MyClass {private:int *data;
int factor;:
void run() {:auto data2 = data;
auto factor2 = factor;{
dpct::get_default_queue_wait().submit([&](cl::sycl::handler &cgh){
auto dpct_global_range = grid * block;auto dpct_local_range = block;cgh.parallel_for<dpct_kernel_name<class kernel_855a44>>(
cl::sycl::nd_range<1>(
cl::sycl::range<1> dpct_global_range.get(0)),
cl::sycl::range<1>( dpct_local_range.get(0))),[=](cl::sycl::nd_item<3> item_ct1){
kernel(data, b, factor, LEN, item_ct1);// This blows up
});
});
}
} // run} // MyClass

上記のコードでは、[=] がラムダ内で使用される変数を値でコピーするため、プログラムはクラッシュします。この例では、factor は実際には this->factor で、data は this->data であるため、this は data および factor を使
用 す る た め に 取 得 さ れ る 変 数 で す 。 OpenCL* ま た は レ ベ ル ゼ ロ で は 、 kernel(data, b, factor, LEN,
item_ct1) 呼び出しで不正な引数エラーが原因でクラッシュします。
この問題を解決するには、ローカル変数 auto data2 と auto factor2 を使用します。auto factor2 =factor は int factor2 = this->factor になるため、ラムダ内で [=] を指定して factor2 を使用すると、int が取得されます。内部セクションを kernel(data2, b, factor2, LEN, item_ct1); に変更します。

注: この問題は、CUDA* カーネルを移行する際によく発生します。同じ CUDA* カーネルの起動シ
グネチャーを保持し、コマンドグループとラムダをカーネル内に配置することで問題を解決することもできます。

OpenCL* 割り当てのインターセプト・レイヤーや onetrace または ze_tracer を使用すると、カーネルが 2 つの同一ア
ドレスで呼び出されることが分かり、拡張エラー情報を見ると、重要なデータ構造をオフロードデバイスにコピーしようとしていることを確認できます。
207

インテル® oneAPI プログラミング・ガイド

統合共有メモリー (USM) を使用して MyClass を USM に割り当てる場合、上記のコードが動作することに注意してください。ただし、USM に data のみが割り当てられている場合、前述の理由からプログラムはクラッシュします。
この例では、カーネル呼び出しですべてを変更する必要がないように、ローカルスコープ内で同じ名前の変数を再宣言できることも留意してください。
インテル® Inspector は、このような障害の診断に役立ちます。次の環境変数を設定して、CPU デバイスでオフロード
コードのメモリー解析を実行すると、インテル® Inspector は上記の問題の多くを通知します。


OpenMP*‐

export OMP_TARGET_OFFLOAD=CPU‐

export OMP_TARGET_OFFLOAD=MANDATORY‐

export LIBOMPTARGET_PLUGIN=OPENCL

SYCL*
‐

export SYCL_DEVICE_FILTER=opencl:cpu‐

または、CPU セレクターを使用してキューを初期化し、OpenCL* CPU デバイスの仕様を強制します。
cl::sycl::queue Queue(cl::sycl::cpu_selector{});



両方
‐

export CL_CONFIG_USE_VTUNE=True‐export CL_CONFIG_USE_VECTORIZER=false

注: コンパイル中に最適化を有効にするとクラッシュする可能性があります。最適化を無効にしてクラッシュが解決される場合、デバッグ向けに -g -[最適化レベル] を指定します。詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』 (英語) を参照してください。

6.3.3.7.

SYCL* 例外ハンドラーを使用する『Data Parallel C++: Mastering DPC++ for Programming of Heterogeneous Systems using C++ and SYCL』 (英語) の書籍では次のことが説明されています。
C++ の例外機能は、プログラム内でエラーが検出された位置と、エラーが処理される位置は明確に分離するように設計されており、この概念は SYCL* の同期エラーと非同期エラーの両方にも適合します。
この書籍で推奨されるメソッドを使用すると、C++ 例外処理は、エラー発生時にプログラムが何の通知もなく終了するのではなく、なんらかの通知を行って終了するのに役立ちます。

208インテル® oneAPI プログラミング・ガイド

注: この節の紺色で示したテキストは、C++ と SYCL* を使用する異種システムのプログラミングを説明する『Data Parallel C++: Mastering DPC++ for Programming of Heterogeneous Systems
using C++ and SYCL*』の第 5 章「Error Handling」からの抜粋です。簡素化のため一部のテキストを省略しています。詳細は書籍を参照してください。

エラー処理の無視
C++ と SYCL* では、エラーを明示的に処理しなくても問題が発生したことを通知できるように設計されています。未処理の同期または非同期のエラーのデフォルトの結果は、オペレーティング・システムが通知するプログラムの異常終了になります。次の 2 つの例は、それぞれ同期エラーと非同期エラーを処理しない場合に発生する動作を模倣します。
以下のコード例は、ハンドルされていない C++ 例外の結果を示しています。これは、ハンドルされていない SYCL* 同期エラーなどが原因である可能性があります。このコードでは、特定のオペレーティング・システムがどのように振舞うかテストできます。
C++ の未処理例外#include <iostream>class something_went_wrong {};int main() {std::cout << "Hello\n";throw(something_went_wrong{});}Linux* での実行例:$ Helloterminate called after throwing an instance of 'something_went_wrong'
Aborted (core dumped)

以下のコード例は、呼び出された std::terminate からの出力例を示します。これは、アプリケーションで未処理の
SYCL* 非同期エラーが発生した結果です。このコードでは、特定のオペレーティング・システムがどのように振舞うかテストできます。
プログラムでエラーを処理する必要がありますが、キャッチされないエラーをキャッチしてからプログラムが終了するた
め、プログラムが何も通知することなく失敗する心配がありません。

209インテル® oneAPI プログラミング・ガイド

std::terminate は SYCL* 非同期例外が処理されないときに呼び出される#include <iostream>
int main() {std::cout << "Hello\n";std::terminate();}Linux* での実行例:$ Helloterminate called without an active exception Aborted (core dumped)

この書籍では、同期エラーを C++ の例外で処理できる理由を詳しく説明していますが、アプリケーションで制御する
位置で非同期エラーを処理するには、SYCL* 例外が呼び出される状況に注意して、SYCL* 例外を利用する必要があります。
SYCL* で定義される同期エラーは、std::exception タイプからの派生クラスであり、以下に示すように trycatch 構造によって SYCL* エラーをキャッチできます。
sycl::exception をキャッチするパターン
try{// SYCL* ワークを実行} catch (sycl::exception &e) {// 例外を出力または処理するため何かを実行
std::cout << "Caught sync SYCL exception: " << e.what() << "\n"; return 1;}

C++ のエラー処理メカニズムに加えて、SYCL* ではランタイムによってスローされる sycl::exception 例外タイプ
を追加します。それ以外はすべて標準 C++ の例外処理であるため、開発者には馴染みがあります。さらに詳しい例を以下に示します。ここでは、追加の例外クラスが処理され、main() からリターンすることでプログラムが終了します。C++のエラー処理メカニズムに加えて、SYCL* ではランタイムによってスローされる sycl::exception 例外タイプを追加します。それ以外はすべて標準 C++ の例外処理であるため、開発者には馴染みがあります。さらに詳しい例を以下に示します。ここでは、追加の例外クラスが処理され、main() からリターンすることでプログラムが終了します。

210インテル® oneAPI プログラミング・ガイド

コードブロックから例外をキャッチするパターン
try{
buffer<int> B{ range{16} };// ERROR: 親バッファーよりも大きな sub-buffer を定義// バッファー・コンストラクターから例外がスローされますbuffer<int> B2(B, id{8}, range{16});} catch (sycl::exception &e) {// 例外を出力または処理するため何かを実行
std::cout << "Caught sync SYCL exception: " << e.what() << "\n";return 1;} catch (std::exception &e) {std::cout << "Caught std exception: " << e.what() << "\n";return 2;} catch (...){
std::cout << "Caught unknown exception\n";return 3;}
return 0;
出力例:
Caught sync SYCL exception: Requested sub-buffer size exceeds thesize of the parent buffer -30 (CL_INVALID_VALUE)

非同期エラー処理
非同期エラーは SYCL* ランタイム (またはベースとなるバックエンド) によって検出され、エラーはホストプログラムのコマンドの実行とは無関係に発生します。エラーは SYCL* ランタイムの内部リストに格納され、プログラマーが制御できる特定の位置でのみ処理を行うためリリースされます。非同期エラーの処理をカバーするのに次の 2 つのことを理解してください。
1.

処理すべき未処理の非同期エラーがある場合に呼び出される非同期ハンドラー

2.

いつ非同期ハンドラーが起動されるか

非同期ハンドラーは、アプリケーションが定義する関数であり、SYCL* コンテキストやキューに登録されます。次のセクションで定義された時点で処理可能な未処理の非同期例外がある場合、SYCL* ランタイムによって非同期ハンドラーが呼び出されて例外リストが渡されます。非同期ハンドラは astd::function としてコンテキストまたはキューのコ
ンストラクターに渡され、通常の関数、ラムダ、ファンクターなどで定義できます。ハンドラーは、以下に示すように
sycl::exception_list 引数を受け入れる必要があります。

211インテル® oneAPI プログラミング・ガイド

ラムダとして定義された非同期ハンドラーの実装例// 単純な非同期ハンドラー関数
auto handle_async_error = [](exception_list elist) {for (auto &e : elist) {try{ std::rethrow_exception(e); }catch ( sycl::exception& e ) {std::cout << "ASYNC EXCEPTION!!\n";
std::cout << e.what() << "\n";}}};上記の例では、std::rethrow_exception の後に特定例外タイプの catch が続き、例外タイプ (この場合sycl::exception のみ) のフィルター処理を提供しています。C++ で異なるフィルター処理を行うことも、タイプにかかわりなくすべての例外を処理することもできます。ハンドラーは、構築時にキューまたはコンテキストに関連付けられます (低レベルの詳細については第 6 章 (英語) で詳しく説明されています)。例えば、上記のリストで定義されたハンド
ラーをキューに登録するには、queue my_queue{ gpu_selector{}, handle_async_error } のように記述
し、ハンドラーをコンテキストに登録するには、context my_context{ handle_async_error } のように記述します。
ほとんどのアプリケーションでは、コンテキストを明示的に作成したり管理する必要はありません (バックグラウンドで自動的に作成されます)。そのため、非同期ハンドラーを使用する場合、そのハンドラーを特定のデバイスのキューに関連付ける必要があります (明示的なコンテキストではありません)。

注: 非同期ハンドラーを定義する場合、何らかの理由でコンテキストを明示的に管理しない限り、キューで定義する必要があります。

キューやその親コンテキストに対して非同期ハンドラーが定義されていないと、そのキュー (またはコンテキスト) で処理が必要な非同期エラーが発生した場合、デフォルトの非同期ハンドラーが呼び出されます。デフォルトのハンドラー
は次のリストと同じように動作します。
デフォルトの非同期ハンドラーの例// 単純な非同期ハンドラー関数
auto handle_async_error = [](exception_list elist) {for (auto &e : elist) {try{ std::rethrow_exception(e); }catch ( sycl::exception& e ) {// 非同期例外に関連する情報を出力}}// 異常終了して、未処理の例外があることを// ユーザーに通知します
std::terminate();};212インテル® oneAPI プログラミング・ガイド

デフォルトのハンドラーは、例外リスト内のエラー情報をユーザーに通知し、アプリケーションを異常終了させます。
この場合、オペレーティング・システムも異常終了したことをレポートする必要があります。
非同期ハンドラーにどのようなエラーを知らせるかはプログラマーに依存します。アプリケーションが処理を正常に続行できるよう、エラーのログにはアプリケーションの終了、そしてエラー状態の回復までさまざまな情報があります。
一般には、sycl::exception::what() を呼び出して利用可能なエラーの詳細を通知し、アプリケーションを終了させます。非同期ハンドラーが内部で何を処理するかを決定するのはプログラマー次第ですが、しばしば見られる間違いとして、エラーメッセージ (プログラムのほかのメッセージで見逃される可能性があります) を出力してから、ハンドラー
関数を終了することです。プログラムの状態を回復して、実行を継続しても安全であると確信できるようエラー管理が成されていない限り、非同期ハンドラー関数内でアプリケーションを終了することを検討してください。
これにより、エラーが検出されたにもかかわらずアプリケーションの不正実行を続行するプログラムから誤った結果が表示される可能性が減少します。ほとんどのプログラムでは、非同期例外が発生したら異常終了することが適切です。
6.3.3.7.1.

例: サイズゼロのオブジェクトでの SYCL* のスロー

次のサンプルコードは、サイズがゼロのオブジェクトが渡されたときに SYCL* ハンドラーがどのようにエラーを生成するかを示しています。
1. #include <cstdio>
2. #include <CL/sycl.hpp>
3.
4. template <bool non_empty>
5. static void fill(sycl::buffer<int> buf, sycl::queue & q) {6.
q.submit([&](sycl::handler & h) {7.
auto acc = sycl::accessor { buf, h, sycl::read_write };8.
h.single_task([=]() {9.
if constexpr(non_empty) {10.
acc[0] = 1;
11.
}
12.
}
13.
);
14.
}
15.
);
16.
q.wait();
17.
18. }
19.
20. int main(int argc, char *argv[]) {21.
sycl::queue q;
22.
sycl::buffer<int, 1> buf_zero ( 0 );23.
24.
fprintf(stderr, "buf_zero.count() = %zu\n", buf_zero.get_count());
25.
fill<false>(buf_zero, q);26.
fprintf(stdout, "PASS\n");27.
28.
return 0;
29. }

213

インテル® oneAPI プログラミング・ガイド

アプリケーションが実行中にサイズがゼロのオブジェクトに遭遇すると、プログラムはアボートし、エラーメッセージが出力されます。
$ dpcpp zero.cpp$./a.out
buf_zero.count() = 0
submit...
terminate called after throwing an instance of 'cl::sycl::invalid_object_error'
what(): SYCL buffer size is zero. To create a device accessor, SYCL buffer size must be
greater than zero. -30 (CL_INVALID_VALUE)
Aborted (core dumped)

プログラマーは、デバッガーで例外をキャッチし、エラーを招いたソース行のバックトレースを調査することで、プログラ
ミングの問題を特定できます。
6.3.3.7.2.

例: 不正な NULL ポインターでの SYCL* スロー

以下のコードについて考えてみます。
deviceQueue.memset(mdlReal, 0, mdlXYZ \* sizeof(XFLOAT));deviceQueue.memcpy(mdlImag, 0, mdlXYZ \* sizeof(XFLOAT)); // コーディング・エラー

コンパイラーは、deviceQueue.memcpy で指定された不正な (NULL ポインター) 値のフラグをセットしません。このエラーは、実行されるまでキャッチされません。
terminate called after throwing an instance of 'cl::sycl::runtime_error'
what(): NULL pointer argument in memory copy operation.-30 (CL_INVALID_VALUE)
Aborted (core dumped)

次のコード例は、NULL ポインターのエラーを示すプログラムに実装された、特定キューでの実行時の例外出力が検出された際に、ユーザーが例外出力の形式を制御する方法を示しています。
1. #include "stdlib.h"
2. #include <stdio.h>
3. #include <cmath>
4. #include <signal.h>
5. #include <fstream>
6. #include <iostream>
7. #include <vector>
8. #include <CL/sycl.hpp>
9.
10. #define XFLOAT float
11. #define mdlXYZ 1000
12. #define MEM_ALIGN 64
13.
14. int main(int argc, char *argv[]) {15.
XFLOAT *mdlReal, *mdlImag;16.
17.
cl::sycl::property_list propList =18.
cl::sycl::property_list{cl::sycl::property::queue::enable_profiling()};19.
cl::sycl::queue deviceQueue(cl::sycl::gpu_selector { },20.
[&](cl::sycl::exception_list eL) {214インテル® oneAPI プログラミング・ガイド

21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.

bool error = false;for (auto e : eL) {try {std::rethrow_exception(e);} catch (const cl::sycl::exception& e) {auto clError = e.get_cl_code();bool hascontext = e.has_context();
std::cout << e.what() << "CL ERROR CODE : " << clError << std::endl;
error = true;
if (hascontext) {std::cout << "We got a context with this exception" << std::endl;}}}
if (error) {throw std::runtime_error("SYCL errors detected");}}, propList);
mdlRealmdlImag= sycl::malloc_device<XFLOAT>(mdlXYZ, deviceQueue);= sycl::malloc_device<XFLOAT>(mdlXYZ, deviceQueue);deviceQueue.memset(mdlReal, 0, mdlXYZ * sizeof(XFLOAT));deviceQueue.memcpy(mdlImag, 0, mdlXYZ * sizeof(XFLOAT)); // コーディング・エラー
deviceQueue.wait();exit(0);49. }6.3.3.8.

リソース

SYCL* API の誤った使用による SYCL* 例外をデバッグするガイド付きのアプローチについては、「ガイド付き行列乗算の例外のサンプル」 (英語) を参照してください。
リソースをオフロードする拡張機能を備えた OpenMP* または SYCL* API を使用するアプリケーションのトラブル
シューティングは、「高度な並列アプリケーションのトラブルシューティング」 (英語) のチュートリアルを参照してください。

6.3.4 オフロードのパフォーマンスを最適化
オフロード・パフォーマンスの最適化は、3 つの作業に要約できます:1.

デバイス上のカーネルの実行時間を最大化しつつ、デバイス間とのデータ転送回数とサイズを最小化します。

2.

可能であれば、デバイス上の計算とデバイスとのデータ転送をオーバーラップさせます。

3.

デバイス上のカーネルのパフォーマンスを最大化します。

OpenMP* オフロードと SYCL*, の両方でデータ転送を明示的に制御することができますが、これを自動的に行うこともできます。また、ホストとオフロードデバイスはほとんど非同期に動作するため、データ転送を制御しようとしても転送が期待どおりに行われず、予想よりも時間を要することがあります。デバイスとホストの両方でアクセスされるデータが215インテル® oneAPI プログラミング・ガイド

統合共有メモリー (USM) に格納されている場合、パフォーマンスに影響する透過的な別のレイヤーでデータ転送が行われる可能性があります。
リソース:

oneAPI GPU 最適化ガイド

インテル® oneAPI ツールキット向け FPGA 最適化ガイド (英語)

6.3.4.1.

バッファー転送時間と実行時間

オフロードデバイス間とのデータ転送には比較的コストがかかり、ユーザー空間でのメモリー割り当て、システムコール、およびハードウェア・コントローラーとのインターフェイスが必要になります。統合共有メモリー (USM) は、ホストまたはオフロードデバイスのいずれかのメモリーの更新を同期するバックグラウンド・プロセスによるコストがかかります。
さらに、オフロードデバイス上のカーネルは、実行に必要なすべての入力および出力バッファーがセットアップされて利用可能になるまで待機する必要があります。
1 回のデータ転送でオフロードデバイスとやり取りする情報量にかかわりなく、このオーバーヘッドのコストはほぼ同じです。そのため、1 回に 1 つずつではなく、10 回分の転送をまとめて行うほうがはるかに高効率です。いずれにしても、すべてのデータ転送にはコストが生じるため、転送の総数を最小限にすることが重要です。例えば、複数のカーネルまたは同じカーネルの複数の呼び出しで必要とする定数がある場合、それらをカーネルを呼び出すたびに送信するのではな
く、一度だけオフロードデバイスに転送して再利用するようにします。最後に、単一の大量のデータ転送には、単一の少量のデータ転送よりも時間がかかります。
送信されるバッファーの数とサイズは式の一部にすぎません。データがオフロードデバイスに到達したら、カーネルが実行される時間を検討します。オフロードデバイスへのデータ転送よりも実行時間が短い場合、同一操作をホストで実行する時間が、カーネルの実行とデータ転送の合計時間よりも長くない限り、オフロードのメリットはありません。
最後に、あるカーネルの実行と次のカーネルの実行の間に、オフロードデバイスがアイドル状態になっている時間を調査します。長い待機時間は、データ転送やホスト上のアルゴリズムの特性が原因である可能性があります。前者は、データ転送とカーネル実行のオーバーラップを試す価値があります。
ホストでのコード実行、オフロードデバイスでのコード実行、およびデータ転送の関係は複雑です。これらの順番と時間は、単純なコードであっても直感的に理解できるものではありません。すべてのアクティビティーを視覚的に理解し、その情報を参考にしてオフロードコードを最適化するには、次のようなツールが必要になります。

6.3.4.2.

インテル® VTune™ プロファイラー

インテル® VTune™ プロファイラーは、ホスト上の詳しいパフォーマンス情報を提供するだけでなく、接続された GPUのパフォーマンスに関する詳細情報も提供できます。GPU 向けの設定に関する情報は、『インテル® VTune™ プロファイ
ラー・ユーザーガイド』をご覧ください。

216

インテル® oneAPI プログラミング・ガイド

インテル® VTune™ プロファイラーの GPU オフロードビューには、それぞれのカーネル間とのデータ転送に費やされた時間など、GPU 上のホットスポットに関するサマリーが表示されます。GPU 計算/メディア・ホットスポット・ビューでは、
動的命令カウントを使用して GPU カーネルのパフォーマンスのマイクロ解析など、GPU カーネルで何が起こっているか詳しく調査することができます。これらのプロファイル・モードでは、データ転送と計算が時間経過でどのように変化するか観察したり、カーネルを効率良く実行するのに十分なワークがあるか判断したり、カーネルが GPU メモリー階層をどのように利用するか調べたりできます。
これらの解析タイプの詳細については、『インテル® VTune™ プロファイラー・ユーザーガイド』を参照してください。
インテル® VTune™ プロファイラーを使用した GPU の最適化に関する詳細は、「インテル® VTune™ プロファイラーでインテル® GPU 向けのアプリケーションの最適化」 (英語) をご覧ください。
カーネルの実行時間を計測するには、インテル® VTune™ プロファイラーも使用できます。次のコマンドは、軽量プロ
ファイルの結果を示します:

収集‐

レベルゼロ・バックエンド$ vtune -collect-with runss -knob enable-gpu-level-zero=true -finalization-mode=none-app-working-dir <app_working_dir> <app>‐

OpenCL* バックエンド$ vtune -collect-with runss -knob collect-programming-api=true -finalization-mode=none -r<result_dir_name> -app-working-dir <app_working_dir> <app>



レポート

$ vtune --report hotspots --group-by=source-computing-task --sort-desc="Total Time" -r<result_dir_name>

6.3.4.3.

インテル® Advisor

インテル® Advisor は、計算を GPU にオフロードするパフォーマンスを向上させのに役立つ 2 つの機能を提供します。


オフロードのモデル化は、ホストの OpenMP* プログラムを調査して、GPU へのオフロードに適したコード領域を示します。また、多種多様なターゲット向けに GPU をモデル化できるため、ターゲットに適したオフロード
コード領域を特定できます。オフロード・アドバイザーは、オフロードのパフォーマンスを制限する可能性がある要因に関する詳細情報を提供します。

GPU ルーフライン解析は、GPU で実行されるアプリケーションを監視し、各カーネルが GPU のメモリー・サブシステムと計算ユニットをどの程度効率良く使用しているか視覚的に示します。これにより、カーネルが GPU にどれくらい最適化されているか知ることができます。

すでにオフロードを実装するアプリケーションでこのモードを使用するには、CPU 上の OpenCL* デバイスを解析ター
ゲットにするよう環境を設定する必要があります。手順は、『インテル® Advisor ユーザーガイド』 (英語) をご覧ください。

217

インテル® oneAPI プログラミング・ガイド

オフロードのモデル化では、GPU を使用するようにアプリケーションを変更する必要はありません。ホストコードで完全に機能します。
リソース:インテル® Advisor クックブック: GPU オフロード



オフロードのモデル化入門 (英語)GPU ルーフライン入門 (英語)

6.3.4.4.

オフロード API 呼び出しのタイムライン

インテル® VTune™ プロファイラーを使用して、データが GPU にコピーされるタイミング、およびカーネルが実行されるタイミングを調査したくない (またはできない) 場合、onetrace、ze_tracer、cl_tracer と OpenCL* アプリケーションのインターセプト・レイヤーでもこの情報を監視する方法が用意されています (ただし視覚的なランタイム情報が必要な場合、出力を視覚化するスクリプトを用意する必要があります)。詳細については、「oneAPI デバッグツール」、「オフロー
ド処理のトレース」、および「オフロード処理のデバッグ」をご覧ください。

6.4 パフォーマンス・チューニング・サイクル
パフォーマンス・チューニング・サイクルの目標は、対話型の応答時間やバッチジョブの経過時間など、問題解決までの時間を短縮することです。ヘテロジニアス・プラットフォームの場合、ホストと独立して実行されるデバイスで利用可能な計算サイクルがあります。これらのリソースを利用してパフォーマンスを向上させます。
パフォーマンス・チューニング・サイクルには、次のステップがあります。
1.

ベースラインの確定

2.

オフロードするカーネルの特定

3.

カーネルのオフロード

4.

最適化

5.

目標を達成するまで 1～4 を繰り返す

6.4.1 ベースラインの確定
経過時間、計算カーネル時間、1 秒あたりの浮動小数点演算などのメトリックを含むベースラインを確定します。これは、パフォーマンス向上の測定だけでなく、結果の正当性を検証する手段としても利用できます。
ベースラインを確定する簡単な方法は、C++ の chrono ライブラリー・ルーチンを使用して、ワークロードの実行前後でタイマー呼び出しを行い時間計測を行うことです。

218インテル® oneAPI プログラミング・ガイド

6.4.2 オフロードするカーネルの特定
ヘテロジニアス・プラットフォームのデバイスで利用可能な計算サイクルを最大限に活用するには、計算集約型で並列実行可能なタスクを特定することが重要です。CPU のみで実行されるアプリケーションを調査すると、GPU で実行するのに適したタスクが見つかることがあります。これは、インテル® Advisor (英語) のオフロードのモデル化機能で判別できます。
インテル® Advisor は、アクセラレーターで実行できる可能性があるワークロードのパフォーマンス特性を推測できます。ワークロードのプロファイル情報から、パフォーマンスを見積もり、高速化、ボトルネックの特性を評価して、さらにオ
フロードデータ転送を推測し、推奨事項を示します。
一般に、計算主体で、大規模なデータセットを持ち、限られたデータ転送を行うカーネルは、デバイスへのオフロードに適しています。
オフロードのモデル化を使用した手順については、『導入ガイド： GPU にオフロードにより大きな効果が得られる候補の特定』 (英語) を参照してください。GPU プラットフォームでのアプリケーションのモデル化のパフォーマンスに関する
その他のリソースについては、「インテル® Advisor ユーザー向けオフロードのモデル化のリソース」 (英語) を参照してく
ださい。

6.4.3 カーネルをオフロード
オフロードに適したカーネルを特定したら、SYCL* または OpenMP* を使用してカーネルをデバイスにオフロードします。詳細は前の節をご覧ください。

6.4.4 SYCL* アプリケーションの最適化
oneAPI は、CPU、GPU、FPGA など、複数のアクセラレーターで実行できるコードを生成します。ただし、コードはすべてのアクセラレーターで最適ではない可能性があります。パフォーマンスの目標を達成するには 3 段階の最適化を行う
ことを推奨します。
1.

アクセラレーター全体に適用される一般的な最適化を行います。

2.

優先するアクセラレーターに対して積極的に最適化を行います。

3.

ステップ 1 と 2 を組み合わせてホストコードを最適化します。

最適化とは、ボトルネック (ほかのコードセクションに比べて実行時間が長いコード領域) を排除する作業です。これらのセクションは、デバイスまたはホストで実行できます。最適化では、インテル® VTune™ プロファイラーなどのプロファ
イル・ツールを使用して、コード内のボトルネックを特定します。
ここでは、最初のステップであるアクセラレーター全体に適用される一般的な最適化を検討します。デバイス固有の最適化、デバイス固有のベスト・プラクティス (ステップ 2)、およびホストとデバイス間の最適化 (ステップ 3 ) については、『インテル® oneAPI ツールキット向け FPGA 最適化ガイド』 (英語) などのデバイス固有の最適化ガイドで詳しく説明されています。この節では、アクセラレーターにオフロードするカーネルがすでに決定されていること、および単独のアク219

インテル® oneAPI プログラミング・ガイド

セラレーターでワークが完了することを想定しています。このガイドは、ホストとアクセラレーター間、またはホストと複数の/異なるアクセラレーター間のワークの分割については考慮していません。
アクセラレーター全体に適用される一般的な最適化は次の 4 つに分類されます。
1.

高レベルの最適化

2.

ループ関連の最適化

3.

メモリー関連の最適化

4.

SYCL* 固有の最適化

次の節では上記の最適化のみをカバーします。これらの最適化を実際にコードに反映する方法の詳細は、オンラインや一般に入手できるコード最適化関連の資料で見付けることができます。ここでは、SYCL* 固有の最適化に関する詳細を示します。

6.4.4.1.

高レベルの最適化



並列ワークの量を増やします。処理要素を十分に活用するには、処理要素よりも多くのワークが必要です。



カーネルのコードサイズを最小化します。これにより、アクセラレーターの命令キャッシュにカーネルが保持されます。



カーネルのロードバランスを取ります。実行時間の長いカーネルはボトルネックとなり、ほかのカーネルのス
ループットに影響する可能性があるため、カーネル間の実行時間は大きく異ならないようにします。



高コストの関数は避けてください。実行時間が長い関数は、ボトルネックとなる可能性があるため呼び出さないでください。

6.4.4.2.

ループ関連の最適化



適切に構造化および構成された、単純な終了条件のループを使用します。単純な終了条件のループとは、出口が 1 つであり、整数上限値との比較で単一の終了条件を持つループです。



線形インデックスと定数上限値を持つループを優先します。例えば、配列への整数インデックスを使用し、コンパ
イル時に上限値が判明しているループなどです。



可能な限り深いスコープで変数を宣言します。これにより、メモリーまたはスタックの使用量を軽減できます。



ループ伝搬されるデータの依存関係を最小化または緩和します。ループ伝搬の依存関係により、並列化が制限されることがあります。可能な限り依存関係を排除します。排除できない場合は、依存関係の距離を最大化する
か、依存関係をローカルメモリー内に留めます。

pragma unroll でループをアンロールします。

220

インテル® oneAPI プログラミング・ガイド

6.4.4.3.

メモリー関連の最適化



可能な限り、メモリー使用よりも計算を優先します。メモリーのレイテンシーと帯域幅のほうが計算よりもボトルネックになる可能性があります。



可能であれば、グローバルメモリーよりもローカルおよびプライベート・メモリーを使用します。



ポインターのエイリアシングを避けます。



メモリーアクセスを結合します。メモリーアクセスをグループ化して個々のメモリー要求の数を減らし、キャッシュラインの利用率を高めます。



可能であれば、頻繁に実行されるコード領域の変数と配列をプライベート・メモリーに保持します。同時メモリー
アクセスに対するループアンロールの影響に注意してください。



別のカーネルが読み取るグローバルメモリーへの書き込みを避けます。代わりにパイプを使用します。



カーネルに [[intel::kernel_args_restrict]] 属性を適用することを検討してください。この属性により、コンパイラーはカーネルのアクセサー引数間の依存関係を無視できます。アクセサー引数の依存関係を無視
すると、コンパイラーはさらに積極的な最適化を行い、カーネルのパフォーマンスが向上する可能性があります。

6.4.4.4.

SYCL* 固有の最適化

可能であれば、work-group サイズを指定します。属性 [[cl::reqd_work_group_size(X, Y, Z)]] (X、Y、Z は Nd-range の整数次元) を使用して、work-group のサイズを設定できます。コンパイラーはこの情報を利用して積極的な最適化を行うことができます。



可能であれば、-Xsfp-relaxed オプションを使用してください。このオプションは、算術浮動小数点演算の順
序付けを緩和します。



可能であれば、-Xsfpc オプションの使用を検討してください。このオプションは、可能な場合は常に中間の浮動小数点丸め操作と変換を排除して、精度を維持するため追加ビットをキャリーします。

-Xsno-accessor-aliasing オプションの利用を検討してください。このオプションは、SYCL* カーネルのア
クセサー引数間の依存関係を無視します。

6.4.5 再コンパイル、実行、プロファイル、そして繰り返し
コードを最適化したら、パフォーマンスを測定することが重要です。以下を確認します。


メトリックは改善されましたか?



パフォーマンスの目標は達成できましたか?



利用可能な計算サイクルが残されていますか?

結果の正当性を確認します。数値結果を比較すると、コンパイラーの最適化やコード変更により異なる場合があります。
差異は許容範囲内ですか ? そうでなければ、最適化ステップに戻ります。

221インテル® oneAPI プログラミング・ガイド

6.5 oneAPI ライブラリーの互換性
oneAPI アプリケーションには、インテルのツール:のリリースバージョンとの互換性のため、動的ライブラリーが実行時に含まれる場合があります。インテル® oneAPI ツールキットとコンポーネント製品は、互換性を維持するためセマン
ティック・バージョニング (英語) を使用します。
次のポリシーが、インテル® oneAPI ツールキットで提供される API および ABI に適用されます。

注: oneAPI アプリケーションは、64 ビットのターゲットデバイスでサポートされます。



新しいインテル® oneAPI デバイスドライバー、インテル® oneAPI 動的ライブラリー、およびインテル® oneAPI コ
ンパイラーは、インテル® oneAPI ツールを使用してビルドされた展開済みのアプリケーションを破損することはありません。現在の API は、通知とメジャーバージョンの重複なしで削除および変更されることはありません。

oneAPI アプリケーションの開発者は、ヘッダーファイルとライブラリーのリリースバージョンが同じであることを確認する必要があります。例えば、アプリケーションで、インテル® oneMKL 2021.2 のヘッダーファイルをインテル® oneMKL 2021.1 で使用してはなりません。

インテル® コンパイラーで提供される新しい動的ライブラリーは、古いバージョンのコンパイラーで作成されたアプリケーションでも動作します (これは一般に下位互換と呼ばれます)。しかし、その逆は当てはまりません。
oneAPI 動的ライブラリーの新しいバージョンには、以前のバージョンでは提供されていないルーチンが含まれる場合があります。

oneAPI 対応のインテル® コンパイラーで提供される古い動的ライブラリーは、新しいバージョンのインテル®
oneAPI コンパイラーでは機能しません。

oneAPI アプリケーションの開発者は、oneAPI アプリケーションが互換性のある oneAPI ライブラリーとともに展開されていることを確認するため、完全なアプリケーションのテストを実施する必要があります。

6.6 SYCL* 拡張
SYCL* 拡張機能は、クロスアーキテクチャー・システムを促進する Khronos Group の SYCL* のようなオープンな標準化団体が、迅速に実験、革新、そして開発する好循環を確立できるようにます。インテル® oneAPI DPC++ コンパイラー
で動作する拡張機能については、GitHub* の SYCL* 拡張 (英語) を参照してください。

222

インテル® oneAPI プログラミング・ガイド

7

用語集

アクセラレーター (Accelerator)
操作のサブセットを迅速に実行する計算リソースを含む専用コンポーネント。CPU、GPU、または FPGA など。
「デバイス」も参照。
アクセサー (Accessor)
アクセスする場所 (ホスト、デバイス) とモード (read、write) 情報を通信します。
アプリケーション・スコープ (Application Scope)
ホスト上で実行されるコード。
バッファー (Buffers)
計算を行うためデバイスに送られる項目の数や型を通信するメモリー・オブジェクト。
コマンド・グループ・スコープ (Command Group Scope)
ホストとデバイス間のインターフェイスとして動作するコード。
コマンドキュー (Command Queue)
コマンドグループを同時に発行します。
計算ユニット (Compute Unit)
処理要素間で使用する共有要素を含み、デバイス上のほかの計算ユニットにあるメモリーよりも高速にアクセスするため、処理要素を「コア」にグループ化したもの。
デバイス (Device)
操作のサブセットを迅速に実行する計算リソースを含むアクセラレーターまたは専用コンポーネント。CPU はデバイスとして利用できますが、その場合、CPU はアクセラレーターとして使用されます。CPU、GPU、または FPGA など。
「アクセラレーター」も参照。
デバイスコード (Device Code)
ホストではなくデバイスで実行されるコード。デバイスコードは、ラムダ式、ファンクター、またはカーネルクラスを介して指定されます。

223

インテル® oneAPI プログラミング・ガイド

DPC++
SYCL* サポートを LLVM C++ コンパイラーに追加したオープンソース・プロジェクト。
ファットバイナリー (Fat Binary)
複数デバイス向けのデバイスコードを含むアプリケーション・バイナリー。バイナリーには、汎用コード (SPIR-V* 形式)とターゲット固有の実行可能コードの両方が含まれます。
ファット・ライブラリー (Fat Library)
複数デバイス向けのオブジェクト・コードを含むアーカイブまたはライブラリー。ファット・ライブラリーには、汎用オブジェクト (SPIR-V* 形式) とターゲット固有のオブジェクト・コードの両方が含まれます。
ファット・オブジェクト (Fat Object)
複数デバイス向けのオブジェクト・コードを含むファイル。ファット・オブジェクトには、汎用オブジェクト (SPIR-V* 形式)とターゲット固有のオブジェクト・コードの両方が含まれます。
ホスト (Host)
プログラムの主要部分、具体的にはアプリケーション・スコープとコマンド・グループ・スコープを実行する CPU ベースのシステム (コンピューター)。
ホストコード (Host Code)
ホスト・コンパイラーによってコンパイルされ、デバイスではなくホストで実行されるコード。
イメージ (Images)
組込み関数を介してアクセスされるフォーマット済みのあいまいなメモリー・オブジェクト。通常、RGB などの形式で保存されピクセルで構成される画像に関係します。
カーネルスコープ (Kernel Scope)
デバイス上で実行されるコード。
ND-range
1 次元、2 次元、または 3 次元の N 次元レンジ、カーネル・インスタンスのグループ、またはワーク項目の略。
処理要素 (Processing Element)
計算ユニットを構成する計算向けの個別のエンジン。

224

インテル® oneAPI プログラミング・ガイド

単一ソース (Single Source)
ホストとアクセラレーターで実行できる同じファイルのコード。
SPIR-V*
グラフィカル・シェーダー・ステージと計算カーネルを表現するバイナリー中間言語。
SYCL*
同一ソースファイルに含まれるアプリケーションのホストコードとカーネルコードと標準の ISO C++ を使用して、異種プロセッサーのコードを記述できるようにするクロスプラット・フォームの抽象化レイヤーの標準化。
ワークグループ (work-group)
計算ユニットで実行するワーク項目の集合。
ワーク項目 (work-item)
oneAPI プログラミング・モデルにおける計算の基本単位。処理要素で実行されるカーネルに関連付けられます。

225

インテル® oneAPI プログラミング・ガイド

8

著作権と商標について

インテルのテクノロジーを使用するには、対応したハードウェア、特定のソフトウェア、またはサービスの有効化が必要となる場合があります。
絶対的なセキュリティーを提供できるコンピューター・システムはありません。
実際の結果は異なる場合があります。
© Intel Corporation. Intel、インテル、Intel ロゴ、その他のインテルの名称やロゴは、Intel Corporation またはその子
会社の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
製品および性能に関する情報
性能は、使用状況、構成、その他の要因によって異なります。
詳細については、http://www.intel.com/PerformanceIndex/ (英語) を参照してください。
注意事項の改訂 #20201201
特に明記されない限り、このドキュメントのサンプルコードは MIT ライセンスの下に次の条件で提供されます。
© Intel Corporation
Permission is hereby granted, free of charge, to any person obtaining a copy of this software andassociated documentation files (the “Software”), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copiesof the Software, and to permit persons to whom the Software is furnished to do so, subject to thefollowing conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHTHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWAREOR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

226