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

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

目次
目次 ........................................................................................................................................................................ 2
著作権と商標について....................................................................................................................................... 5
はじめに ................................................................................................................................................................ 6
インテル® oneAPI プログラミングの概要....................................................................................... 7
インテル® oneAPI ツールキットの配布について ........................................................................... 8
本書について ........................................................................................................................................... 9
関連ドキュメント .................................................................................................................................... 9oneAPI プログラミング・モデル .................................................................................................................. 10
データ並列 C++（DPC++) ................................................................................................................. 10
簡単な DPC++ サンプルコード .......................................................................................... 11
その他の DPC++ のリソース ............................................................................................... 12
C/C++ または Fortran と OpenMP* オフロード・プログラミング・モデル .......................... 13
基本的な OpenMP* target 構造 ....................................................................................... 13
Map 変数 .................................................................................................................................. 14
OMP TARGET を使用するコンパイル .............................................................................. 15
OpenMP* オフロードの追加のリソース .......................................................................... 15
デバイスの選択 .................................................................................................................................... 16
ホストコードでの DPC++ デバイス選択 ........................................................................... 16
ホストコードでの OpenMP* デバイスの確認と選択 ..................................................... 17
oneAPI 開発環境の設定 ............................................................................................................................... 18
Windows* で setvars スクリプトを使用 .................................................................................. 19
Windows* で setvars.bat の設定ファイルを使用 .................................................. 22
Microsoft Visual Studio* で setvars.bat スクリプトを自動化 .......................... 26
Linux* または macOS* で setvars スクリプトを使用 .............................................................. 30
Linux* または macOS* で setvars.sh 設定ファイルを使用 ....................................... 33
Eclipse* で servars.sh スクリプトを自動化 .................................................................... 37
Linux* でモジュールファイルを使用 .............................................................................................. 39
oneAPI アプリケーションで CMake を使用 ................................................................................ 43
oneAPI プログラムのコンパイルと実行.................................................................................................... 45
単一ソースのコンパイル ................................................................................................................... 45
コンパイラーの起動 ............................................................................................................................ 45
インテル® oneAPI DPC++/C++ コンパイラーの標準オプション ........................................... 46
コンパイル例 ........................................................................................................................................ 46
コンパイルの手順 ................................................................................................................................ 50
CPU 手順............................................................................................................................................... 53
CPU コマンドの例 .................................................................................................................. 53
2

目次
CPU アーキテクチャー向けの最適化オプション ............................................................ 54
CPU 上のホストとカーネルのインタラクション .............................................................. 55
複数の CPU コア上でバイナリーの実行をコントロール ............................................... 55
GPU 手順 .............................................................................................................................................. 58
GPU コマンドの例 .................................................................................................................. 58
GPU 向けのオフラインコンパイル ..................................................................................... 58
FPGA 手順 ............................................................................................................................................ 59
FPGA 向けのコンパイルが特殊である理由 ..................................................................... 60
DPC++ FPGA コンパイルの種別 ....................................................................................... 60
FPGA コンパイルオプション ................................................................................................ 63
FPGA デバイスセレクター .................................................................................................... 65
FPGA 高速再コンパイル....................................................................................................... 66
FPGA BSP とボード ............................................................................................................... 70
複数の同種の FPGA デバイスをターゲットにする ......................................................... 72
複数のプラットフォームをターゲットにする .................................................................... 74
FPGA-CPU インタラクション .............................................................................................. 75
FPGA パフォーマンスの最適化........................................................................................... 77
FPGA 向けの静的ライブラリーを使用する ...................................................................... 77
IDE での FPGA ワークフロー .............................................................................................. 85
API ベースのプログラミング ........................................................................................................................ 86
インテル® oneAPI ライブラリーの概要 ......................................................................................... 86
インテル® oneAPI DPC++ ライブラリー（インテル® oneDPL) ............................................... 87
インテル® oneDPL ライブラリーの使い方 ....................................................................... 87
インテル® oneDPL サンプルコード ................................................................................... 88
インテル® oneAPI マス・カーネル・ライブラリー（インテル® oneMKL) ................................. 88
インテル® oneMKL の使い方 .............................................................................................. 88
インテル® oneMKL サンプルコード .................................................................................. 89
インテル® oneAPI スレッディング・ビルディング・ブロック（インテル® oneTBB) ............................. 93
インテル® oneTBB の使い方............................................................................................... 94
インテル® oneTBB サンプルコード ................................................................................... 94
インテル® oneAPI データ・アナリティクス・ライブラリー（インテル® oneDAL) ............................. 94
インテル® oneDAL の使い方 .............................................................................................. 95
インテル® oneDAL サンプルコード ................................................................................... 95
インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー（インテル® oneCCL) .................................................................................................................... 96
インテル® oneCCL の使い方 ............................................................................................... 96
インテル® oneCCL サンプルコード ................................................................................... 97
インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー（インテル® oneDNN) .................................................................................................................. 97
インテル® oneDNN の使い方 ............................................................................................. 98
インテル® oneDNN サンプルコード ................................................................................ 100
インテル® oneAPI ビデオ・プロセシング・ライブラリー（インテル® oneVPL).......................... 100
インテル® oneVPL の使い方 ............................................................................................. 101
インテル® oneVPL サンプルコード ................................................................................. 101
その他のライブラリー ....................................................................................................................... 104

3

ソフトウェア開発プロセス .......................................................................................................................... 105
DPC++ へのコードの移行 ............................................................................................................... 105
C++ から SYCL*/DPC++ への移行 ................................................................................. 105
CUDA* から DPC++ への移行 .......................................................................................... 105
OpenCL* コードから DPC++ への移行 .......................................................................... 106
CPU、GPU、および FPGA 間の移行 ................................................................................. 106
コンポーザビリティー ....................................................................................................................... 109
C/C++ OpenMP* および DPC++ のコンポーザビリティー ...................................... 109
OpenCL* コードの相互運用性 ......................................................................................... 112
DPC++ と OpenMP* オフロード処理のデバッグ..................................................................... 112
oneAPI デバッグツール...................................................................................................... 113
オフロード処理のトレース .................................................................................................. 121
オフロード処理のデバッグ ................................................................................................. 123
オフロードのパフォーマンスを最適化 ............................................................................. 135
パフォーマンス・チューニング・サイクル ....................................................................................... 138
ベースラインの確定 .............................................................................................................. 138
オフロードするカーネルの特定 ......................................................................................... 139
カーネルをオフロード .......................................................................................................... 139
最適化 ...................................................................................................................................... 139
再コンパイル、実行、プロファイル、そして繰り返し....................................................... 141
oneAPI ライブラリーの互換性 ...................................................................................................... 142
用語集 ............................................................................................................................................................... 143

4

著作権と商標について
インテルのテクノロジーを使用するには、対応したハードウェア、ソフトウェア、またはサービスの有効化が必要となる場合があります。
絶対的なセキュリティーを提供できるコンピューター・システムはありません。
実際の費用と結果は異なる場合があります。
© Intel Corporation. Intel、インテル、Intel ロゴ、その他のインテルの名称やロゴは、Intel Corporation またはその子会社の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
製品および性能に関する情報
性能は、使用状況、構成、その他の要因によって異なります。
詳細については、www.intel.com/PerformanceIndex/（英語）を参照してください。
注意事項の改訂 #20201201

特に明記されない限り、このドキュメントのサンプルコードは MIT ライセンスの下に次の条件で提供されます。
© 2021 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.

5

はじめに

1

現代のコンピューター・アーキテクチャーで高い計算パフォーマンスを達成するには、最適化され、電力効率に優れた、スケーラブルなコードが必要です。従来のハイパフォーマンス・コンピューティング（HPC）
を始めとして AI、ビデオ解析、データ解析においてハイパフォーマンスの需要は増え続けています。
現代のワークロードの多様性から、単一のアーキテクチャーですべてのワークロードに対応することは困難になっており、アーキテクチャーも多様化しています。必要とするパフォーマンスを達成するには、CPU、GPU、AI、および FPGA アクセラレーターに配置されたスカラー、ベクトル、行列、および空間（SVMS）
アーキテクチャーの組み合わせが求められます。
今日、CPU とアクセラレーター向けのコーディングには、異なる言語、ライブラリー、そしてツールを利用する必要があります。これは、それぞれのハードウェア・プラットフォームは完全に個別のソフトウェア資産を必要とし、異なるターゲット・アーキテクチャー全体ではアプリケーション・コードの再利用が制限されることを意味します。
oneAPI プログラミング・モデルは、データ並列 C++（DPC++）と呼ばれるオープンソース・プログラミン
グ言語と最新の C++ 機能を使用して並列処理を表現することにより、CPU とアクセラレーターのプログ
ラミングを簡素化します。DPC++ 言語は、単一のソース言語でホスト（CPU など）とアクセラレーター（GPU など）のコードの再利用を可能にし、実行とメモリーの依存関係を明確にします。DPC++ コード内のマッピング機能により、ハードウェアまたはハードウェア・セットに最適化されたワークロードを実行するためアプリケーションが移行されます。アクセラレーターを使用できないプラットフォームでも、ホストを利用することでデバイスコードの開発とデバッグを簡素化できます。
oneAPI は、既存の C/C++ または Fortran コードで OpenMP* オフロード機能を使用する CPU およびアクセラレーターのプログラミングもサポートします。
注：すべてのプログラムにおいて、oneAPI が提供する単一プログラミング・モデルの恩恵を得られるわけではありません。プログラムに適しているかどうかは、設計、実装、およびプログラムで使用する
oneAPI プログラム・モデルを理解する必要があります。
oneapi.com（英語）で oneAPI イニシアチブとプログラミング・モデルの詳細をご覧ください。このサイト
では、oneAPI 仕様、DPC++ 言語ガイドと API リファレンス、オープンソース・ライブラリーのドキュメン
トなど、その他のリソースが提供されています。

6

はじめに

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

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

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

•

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

1と GPU ターゲット向けにはオンラインとオフラインコンパイルがサポートされ、FPGA ターゲット向
けにはオフラインコンパイルのみがサポートされます。
•

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

•

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

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

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

製品のローカル・インストール：インテル® デベロッパー・ゾーンからインテル® oneAPI ツールキット
をインストールします。

•

コンテナーまたはリポジトリーからインストール：サポートされるコンテナーまたはリポジトリーからインテル® oneAPI ツールキットをインストールします。

•

事前インストールさ れた インテル® DevCloud：無料の開発サンドボックスを使用して、 最新のインテル® SVMS ハードウェアにアクセスし、インテル® oneAPI ツールを選択します。

これらの配布チャネルの詳細については、インテル® デベロッパー・ゾーンのインテル® oneAPI 製品ウェ
ブサイト（英語）をご覧ください。

8

はじめに

本書についてこのドキュメントは以下で構成されます。
•

oneAPI プログラミング・モデル：oneAPI プログラミング・モデルの紹介（プラットフォーム、実行、メ
モリー、およびカーネル・プログラミング）•

oneAPI プログラムのコンパイルと実行：各種アクセラレーター（CPU、FPGA など）向けのコードをコンパイルする詳細•

API ベースのプログラミング：共通 API と関連ライブラリーの簡単な紹介•

ソフトウェア開発手順：デバッガーやパフォーマンス・プロファイラーなど各種 oneAPI ツールを使用したソフトウェア開発手順の概要、および特定のアクセラレーター（CPU、FPGA など）向けのコードの最適化を紹介関連ドキュメント
次のドキュメントは、これから oneAPI プロジェクトを導入する開発者向けの入門資料として役立ちます。
•••

選択した oneAPI ツールキットの導入ガイド：•

インテル® oneAPI ベース・ツールキット導入ガイド（Linux* | Windows* | MacOS*（英語））•インテル® oneAPI HPC ツールキット導入ガイド（Linux* | Windows* | MacOS*（英語））•インテル® oneAPI IoT ツールキット導入ガイド（Linux* | Windows*）（英語）

oneAPI ツールキットのリリースノート：•

インテル® oneAPI ベース・ツールキット（英語）•インテル® oneAPI HPC ツールキット（英語）•インテル® oneAPI IoT ツールキット（英語）

言語リファレンス：•

DPC++ 言語ガイドと API リファレンス（英語）•SYCL* 仕様（バージョン 1.2.1）（英語）•SYCL* 仕様 (バージョン 2020)•

データ並列 C++ 書籍：Mastering DPC++ for Programming of Heterogeneous Systems
using C++ and SYCL（英語）•LLVM/OpenMP* 関連のドキュメント（英語）•OpenMP* 仕様（英語）9oneAPI プログラミング・モデル

2

ヘテロジニアス・コンピューティングでは、ホスト・プロセッサーはアクセラレーター・デバイスの利点を活用して、コードをより効率良く実行します。
oneAPI プログラミング・モデルは、データ並列 C++（DPC++）および OpenMP*（Fortran、C、C++）の 2
つのヘテロジニアス・コンピューティング方式をサポートします。
DPC++ は、最新の C++ と Khronos Group の SYCL* 言語に基づいたオープンソース言語であり、インテル社によりいくつかの拡張機能が追加されています。インテル® oneAPI DPC++/C++ コンパイ
ラーは、インテル® oneAPI ベース・ツールキットに含まれています。
OpenMP* は 20 年以上に渡り標準化されてきたプログラミング言語であり、インテルは OpenMP* 標
準のバージョン 5.0 を実装しています。OpenMP* のオフロード機能をサポートするインテル® oneAPI
DPC++/C++ コンパイラーは、インテル® oneAPI ベース・ツールキット、インテル® HPC ツールキット、そしてインテル® oneAPI IoT ツールキットに含まれます。OpenMP* オフロードをサポートするインテル®
Fortran コンパイラー・クラシックとベータ版インテル® Fortran コンパイラーは、インテル® oneAPI HPC
ツールキットで提供されます。
注：OpenMP* では FPGA デバイスをサポートしていません。
次のセクションでは、それぞれの言語について簡単に説明し詳細情報の参照先を示します。

データ並列 C++（DPC++)
データ並列 C++（DPC++）は、データ並列プログラミングの生産性向けに設計された高レベル言語です。
注：DPC++ の主な目的の 1 つは、ベースとなる OpenCL* C コードよりも高レベルのプログラミング言語を提供することです。OpenCL* プログラムに精通している開発者は、OpenCL* コードとの類似点と相違点に気付くでしょう。

10

oneAPI プログラミング・モデル
簡単な DPC++ サンプルコード
DPC++ の導入を示す最良の方法は、簡単なサンプルを使用することでしょう。DPC++ は最新の C++ をベースとしているため、この例ではラムダ関数や一様初期化など近年 C++ に追加されたいくつかの機能を使用しています。開発者がこれらの機能に精通していなくても、それらの意味と機能はサンプルのコン
テキストから明らかになります。DPC++ によるプログラミングの経験を積んでいくと、これらの新しいC++ 機能は自然に受け入れられるでしょう。
#include <CL/sycl.hpp>#include <iostream>
constexpr int num=16;
using namespace sycl;
int main() {auto r = range{num};buffer<int> a{r};queue{}.submit([&](handler& h) {accessor out{a, h};h.parallel_for(r, [=](item<1> idx) {out[idx] = idx;});});
host_accessor result{a};for (int i=0; i<num; ++i)
std::cout << result[i] << "\n";}次のサンプルコードは、a[0] = 0、a[1] = 1、... のように配列の各要素をそのインデックス値に設定します。
最初に気付くことは、ソースファイルが 1 つしかないことです。つまり、ホストコードとオフロードされるアクセラレーター・コードの両方がこの単一のソースファイルから生成されます。次に注目すべき点は、構文が標準の C++ であるということです。並列処理を表現する新しいキーワードやプラグマは使用されていません。代わりに、並列処理は C++ クラスを介して表現されています。例えば、8 行目にある buffer
クラスはデバイスにオフロードされるデータを表し、10 行目の queue クラスはホストからアクセラレー
ターへの接続を表します。
ロジックは次のように動作します。8 行目と 9 行目で、初期値を持たない 16 個の int 要素の bufferを作成します。この buffer は配列のように作用します。11 行目でアクセラレーター・デバイスに接続するキュー（queue）を作成します。この簡単な例では、暗黙的に DPC++ がデフォルトのアクセラレーター・
デバイスを選択しますが、アプリケーションによっては、システムのトポロジーを調査して特定のアクセラ
レーションを選択することもできます。キューが作成されると、この例では submit() メンバー関数を呼び出して、アクセラレーターにワークを送信します。この submit() 関数の引数はラムダ関数であり、ホスト上ですぐに実行されます。ラムダ関数は次の 2 つのことを行います。1 つは、12 行目でアクセサーを

11

2
作 成 し ま す 。 ア ク セ サ ー は バ ッ フ ァ ー の 要 素 を 書 き 込 む こ と が で き ま す 。 次 に 、 13 行 目 でparallel_for() 関数を呼び出してコードをアクセラレーターで実行します。
parallel_for() の呼び出しには 2 つの引数があります。1 つはラムダ関数で、もう 1 つはバッファー内の要素数を示す範囲オブジェクト "r" です。DPC++ は、ラムダ関数が範囲内のインデックスごとに一度（バッファー要素ごとに 1 回）、アクセラレーターで呼び出されるように調整します。ラムダは、12行目で作成された out アクセサーを使用してバッファー要素に値を割り当てるだけです。この簡単な例
では、ラムダ呼び出し間に依存関係がないため、DPC++ はアクセラレーターで最も効率良い方法で自由に並行して実行できます。
parallel_for() を呼び出した後、ホストのコードはアクセラレーターの完了を待たずに処理を続行します。ホストが次に行うことは、18 行目でバッファーの要素を読み取る host_accessor を作成することです。DPC++ は、このバッファーがアクセラレーターによって書き込まれたことを認識するため、
host_accessor コンストラクター（18 行目）は、parallel_for() によって送信されたワークが完了するまでブロックされます。アクセラレーターのワークが完了すると、ホストコードは 18 行目以降を続
行し、out アクセサーを使用してバッファーから値を読み取ります。

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

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

•

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

•「DPC++ エッセンシャル・トレーニング・ソース」（英語）は、インテル® DevCloud で Jupyter*
Notebook を使用するガイド付きの学習コースです。

•『データ並列 C++：C++ と SYCL* を使用したヘテロジニアス・システムのプログラミング向けに
DPC++ を習得』（英語）は、DPC++ に関連するプログラミングの概念と言語の詳細を紹介する書籍です。

12

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

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

基本的な OpenMP* target 構造
OpenMP* target 構造は、ホストからターゲットデバイスへ制御を移行するために使用されます。変数はホストとターゲットデバイスでマッピングされます。ホストスレッドは、オフロードされた計算が完了するまで待機します。ほかの OpenMP* タスクは、ホストで非同期に実行できます。それには、nowait 節を使用して、スレッドがターゲット領域の完了を待機しないようにします。
C/C++
この C++ のコードスニペットは、SAXPY 計算をアクセラレーターにオフロードします。
#pragma omp target map(tofrom:fa), map(to:fb,a)#pragma omp parallel for firstprivate(a)for(k=0; k<FLOPS_ARRAY_SIZE; k++)fa[k] = a * fa[k] + fb[k]配列 fa は、計算の入力と出力の両方で使用されるため、アクセラレーターの to と from にマップされます。配列 fb と変数 a は計算の入力であり変更されることがないため、その出力をコピーする必要はありません。変数 FLOPS_ARRAY_SIZE はアクセラレーターに暗黙にマップされます。ループ・インデック
ス k は、OpenMP* に従って暗黙的にプライベートです。
Fortran
この Fortran のコードのコードスニペットは、行列乗算をアクセラレーターにオフロードします。

13

2!$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 節はオプションです。

Map 変数ホストとアクセラレーター間のデータ共有を最適化するため、target data ディレクティブは変数をアクセ
ラレーターにマップし、変数はその領域の範囲内でターゲットのデータ領域に維持されます。この機能は、複数のターゲット領域にまたがって変数をマップするのに役立ちます。
C/C++#pragma omp target data [節 [[,] 節],…]構造化ブロック

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

節の使用例
device(scalar-integer-expression)map(alloc | to | from | tofrom: list)
if(scalar-expr)

target update ディレクティブを使用して、ホストの変数をデバイスの対応する変数と同期することがで
きます。

14

oneAPI プログラミング・モデル
OMP TARGET を使用するコンパイル
次のコマンドは、OpenMP* target を使用するアプリケーションをコンパイルする例を示します。
C/C++
icx -fiopenmp -fopenmp-targets=spir64 code.c

Fortranifx -fiopenmp -fopenmp-targets=spir64 code.f90

OpenMP* オフロードの追加のリソース•

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

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

•

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

•

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

•

OpenMP* オフロード機能の導入（英語）では、サポートされるオプションやサンプルコードなど、OpenMP* オフロードでインテル® コンパイラーを使用する方法を説明します。

•

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

•

openmp.org では豊 富 な サンプ ルコード が提 供さ れて いま す ： https://www.openmp.org/wpcontent/uploads/openmp-examples-4.5.0.pdf（英語）。例題ドキュメントの第 4 章では、アクセラ
レーターと target 構造に焦点を当てています。

•『Using OpenMP – the Next Step』は、OpenMP* の優れた参考書籍です。第 6 章では、ヘテロジニ
アス・システムにおける OpenMP* のサポートについて説明しています。この書籍の追加情報については、https://www.openmp.org/tech/using-openmp-next-step（英語）をご覧ください。

15

2

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

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

default_selector•

cpu_selector•

gpu_selector•

fpga_selector

default_selector が 使 用 さ れ る と 、 カ ー ネ ル は 利 用 可 能 な 計 算 デ バ イ ス （ す べ て 、 ま た は
SYCL_DEVICE_TYPE 環境変数の値に基づくサブセット）から選択するヒューリスティックに基づいて実行されます。
特定のデバイスタイプ（cpu_selector や gpu_selector）を使用する場合、指定されたデバイスタイ
プがプラットフォームで利用可能であるか、SYCL_DEVICE_FILTER で指定されるフィルターに含まれていなければなりません。指定したデバイスが利用できない場合、ランタイムシステムはデバイスが利用できないことを示す例外をスローします。このエラーは、事前コンパイル（AOT）したバイナリーが、指定するデバイスタイプを含まないプラットフォームで実行される場合にスローされることがあります。
注：DPC++ アプリケーションは、サポートされる任意のターゲット・ハードウェアで実行できますが、特定のターゲット・ハードウェアで最高のパフォーマンスを引き出すにはチューニングが必要です。例えば、
CPU 向けにチューニングされたコードは、チューニングなしでは GPU アクセラレーターでは高速に実行できない可能性があります。
SYCL_DEVICE_TYPE は、DPC++ ランタイムで使用されるランタイム、計算デバイスタイプ、および計算デバイス ID を、利用可能なすべての組み合わせのサブセットに制限することができる複雑な環境変数です。計算デバイス ID は、SYCL* API、clinfo または sycl-ls（1 から始まる番号）によって返される IDに対応し、その ID を持つデバイスが特定のタイプであるか、特定のランタイムをサポートするかは関係ありません。プログラムによる特定のセレクター（gpu_selector など）を使用してフィルターで除外されたデバイスを要求すると、例外がスローされます。使い方と設定可能な値の例については、GitHub* の環
境変数の説明をご覧ください。
https://github.com/intel/llvm/blob/sycl/sycl/doc/EnvironmentVariables.md（英語）16oneAPI プログラミング・モデル
デバイス選択に関する詳しい情報は、『DPC++ 言語ガイドと API リファレンス』（英語）で入手できます。

ホストコードでの 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 デバイスセレクター

17

oneAPI 開発環境の設定

3

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

インストール・ディレクトリー
Windows* システムでは、インテル® oneAPI 開発ツールは C:\Program Files (x86)\Intel\
oneAPI\ ディレクトリーにインストールされます（デフォルト）。
Linux* と macOS* システムでは、インテル® oneAPI 開発ツールは /opt/intel/oneapi/ ディレクト
リーにインストールされます（デフォルト）。
デフォルトのインストール先はインストール中に変更できます。
oneAPI インストール・ディレクトリー内には、開発システムにインストールされているコンパイラー、ライ
ブラリー、解析ツール、およびそのほかのツールを含むフォルダーが含まれます。正確なファイルは、インストールされるツールキットとインストール中に選択されるオプションによって異なります。oneAPI イン
ストール・ディレクトリー内のほとんどのフォルダーは、コンポーネント名に直結する分かりやすい名前が付いています。例えば、mkl フォルダーにはインテル® oneAPI マス・カーネル・ライブラリー（インテル®
oneMKL）が含まれ、ipp フォルダーにはインテル® インテグレーテッド・パフォーマンス・プリミティブ（インテル® IPP）ライブラリーが含まれます。

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

コンパイルとリンク処理の制御（PATH、CPATH、INCLUDE など）•

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

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

setvars と vars ファイル
インストールされるすべてのインテル® oneAPI ツールキットには、親スクリプト "setvars" と、ツール
固 有 の ス ク リ プ ト "vars" が 含 ま れ ま す （ setvars.sh と vars.sh は Linux* と macOS* 、

18

oneAPI 開発環境の設定
setvars.bat と vars.bat は Windows*）。これらのスクリプトが実行（または source）されると、各インテル® oneAPI 開発ツールに必要なローカル環境変数が設定されます。
次のセクションでは、インテル® oneAPI の setvars と vars スクリプトを使用して、インテル® oneAPI
開発環境を初期化する方法を詳しく説明します。
•

Windows* で setvars スクリプトを使用•

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

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

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

19

3

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

コマンドライン引数
setvars.bat スクリプトはいくつかのコマンドライン引数をサポートしており、--help オプションで引数の一覧を表示できます。
次に例を示します。
"C:\Program Files (x86)\Intel\oneAPI\setvars.bat" --help

有用なオプションとして、--config=file 引数を指定して setvars.bat スクリプトから呼び出される vars.bat スクリプトへの追加引数をインクルードする機能があります。
--config=file 引数は、特定のインテル® oneAPI コンポーネントの環境の初期化機能を提供するとともに、特定のバージョンの環境を初期化することもできます。例えば、インテル® インテグレーテッド・パフォーマンス・プリミティブ（インテル® IPP）ライブラリーとインテル® oneAPI マス・カーネル・ライブラ
リー（インテル® oneMKL）の環境のみを設定するには、setvars.bat スクリプトにこれら 2 つのインテル® oneAPI コンポーネントの環境変数のみを設定することを指示する設定ファイルを作成します。
詳細と利用例については、「Windows* で setvars.bat の設定ファイルを使用」をご覧ください。
setvars.bat のヘルプメッセージに記載されていないコマンドライン引数は、そのまま vars.bat ス
クリプトに渡されます。つまり、setvars.bat スクリプトが認識できない引数は、コンポーネントのvars.bat スクリプトで使用されるものとみなし、それらの引数をすべてのコンポーネントの vars.bat
スクリプトに渡します。最もよく使用される追加の引数は、ia32 と intel64 です。これらは、インテル®
コンパイラー、インテル® IPP、およびインテル® oneMKL ライブラリーでアプリケーションのターゲット・アーキテクチャーを示すために使用されます。
Visual Studio* 2017 と Visual Studio* 2019 の両方がインストールされている場合、vs2017 またはvs2019 引数を setvars.bat コマンドラインに追加することで、2 つの Visual Studio* 環境のどちらをインテル® oneAPI 環境の初期化に使用するかを指定できます。デフォルトでは、Visual Studio* の最新バージョンが使用されます。
個々の vars.bat スクリプトを調べて、受け入れるコマンドライン引数があればそれを決定します。

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

20

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

複数の実行
各コンポーネントの 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:: 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 initialized ::ONEAPI_ROOT 環境変数
ONEAPI_ROOT 環境変数は、スクリプトが実行されるときに最上位の setvars.bat によって設定されます。ONEAPI_ROOT 環境変数がすでに設定されている場合、setvars.bat はそれを上書きします。この変数は、oneapi-cli サンプルブラウザーと Microsoft Visual Studio* および Visual Studio* Code21

3
サンプルブラウザーによって使用され、インテル® oneAPI ツールとコンポーネントの検出、および
SETVARS_CONFIG 機能が有効である場合に setvars.bat スクリプトを検出するのに役立ちます。
SETVARS_CONFIG 機能の詳細については、「Microsoft Visual Studio* で setvars.bat スクリプトを自動化」をご覧ください。
Windows* システムでは、インストーラーは ONEAPI_ROOT 環境変数を追加するため、ユーザーアク
ションは必要ありません。

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

バージョンと構成
一部のインテル® oneAPI ツールは複数バージョンのインストールをサポートします。複数バージョンをサポートするツールのディレクトリー構造は次のようになります。
[コンポーネント] ディレクトリー- [1.0] バージョンのディレクトリー- [1.1] バージョンのディレクトリー- [1.2] バージョンのディレクトリー- [latest -> 1.2] シンボリック・リンクまたはショートカット

次に例を示します。

22

oneAPI 開発環境の設定

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

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

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

設定ファイルの例
以下に簡単な設定ファイルの例を示します。
最新のコンポーネントをすべてロード
mkl=1.1
dldt=exclude233
ただし以下のコンポーネントは除外
default=exclude
mkl=1.0
ipp=latest

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

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

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

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

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

•

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

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

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

24

oneAPI 開発環境の設定

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

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

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

setvars.bat は、インテル® oneMKL 2021.1-beta03 の 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-beta03
ipp=latest

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

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

•

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

•

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

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

26

oneAPI 開発環境の設定
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 設定ファイルの作成
setvars 設 定 フ ァ イ ル で 使 用す る新 規 の テキ スト フ ァ イ ル を 作 成 しま す。 こ の 例で は、 フ ァ イ ル
config.txt は、C:\Program Files (x86)\Intel\oneAPI ディレクトリーに配置されます。

27

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

SETVARS_CONFIG 環境変数の定義
1.
2.
3.

Windows キーを押しながら S キーを押して、検索ウィンドウを開きます。
検索ウィンドウで「詳細設定」と入力します。
[システムの詳細設定の表示] を選択します。

4.

[環境変数] ボタンをクリックします。

28

oneAPI 開発環境の設定

5.
6.
7.

[ユーザー環境変数] のリストから SETVARS_CONFIG を選択します。[編集] をクリックします。
SETVARS_CONFIG が [ユーザー変数] リストに表示されていない場合、[新規] をクリックします。
[変数名] フィールドに SETVARS_CONFIG と入力します。
[ファイルの参照] をクリックします。作成したテキストファイルを探してクリックします。

29

3

8.
9.
10.
11.

[開く] をクリックします。
[OK] をクリックして [ユーザー変数] ウィンドウを閉じます。
[OK] をクリックして [環境変数] ウィンドウを閉じます。
[OK] をクリックして [システムのプロパティ] ウィンドウを閉じます。

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

30

oneAPI 開発環境の設定ての <コンポーネント>/latest/env/vars.sh スクリプトが source されます。これらのスクリプトを
source した後、env コマンドを使用して環境変数を確認できます。
注：setvars.sh スクリプト（または個別の vars.sh スクリプト）により変更された環境は永続的ではありません。これらの変更は、setvars.sh 環境スクリプトが source されたターミナルセッションでのみ有効です。

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

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

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

31

3

注：csh など非 POSIX シェルを使用する場合、次のコマンドを使用します。
% bash -c ‘source <install-dir>/setvars.sh; exec csh’

または、modulefiles スクリプトを使用して開発環境を設定します。modulefiles スクリプトは、すべての Linux* シェルで機能します。

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

戻り値
SETVARS_COMPLETED=1

複数の実行
各コンポーネントの env/vars.sh スクリプトの多くは、PATH、CPATH、およびそのほかの環境変数に変更を加えるため、最上位の setvars.sh スクリプトは同じセッションで同じ vars.sh を複数回呼び出すことはできません。これは、特に $PATH 環境変数が原因で環境変数の文字数が長くなりすぎないよ
うにします。
これを強制するには、setvars.bat に --force オプションを指定します。この例では、ユーザーがsetvars.sh を 2 回実行しています。setvars.sh がすでに実行されているため、2 回目の実行は停止します。
> source <install-dir>/setvars.sh:: initializing environment ...
(SNIP: lot of output):: oneAPI environment initialized ::> source <install-dir>/setvars.sh:: 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:: initializing environment ...
(SNIP: lot of output):: oneAPI environment initialized ::32

oneAPI 開発環境の設定
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 変数を定義します。

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

バージョンと構成
一部の oneAPI ツールは複数バージョンのインストールをサポートします。複数バージョンをサポートするツールのディレクトリー構造は次のようになります。
[コンポーネント] ディレクトリー- [1.0] バージョンのディレクトリー- [1.1] バージョンのディレクトリー- [1.2] バージョンのディレクトリー- [latest -> 1.2] シンボリック・リンクまたはショートカット

33

3
次に例を示します。

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

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

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

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

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

34

oneAPI 開発環境の設定
設定テキストファイルは次の要件に従う必要があります。
•

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

•

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

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

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

•

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

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

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

35

3
/opt/intel/oneapi/mkl||-- 2021.1-beta03||-- env||-- include||-- interfaces||-- lib|`-- tools||-- 2021.1-beta04||-- env||-- include||-- interfaces||-- lib|`-- tools|`-- latest -> 2021.1-beta04|-- env|-- include|-- interfaces|-- lib`-- tools

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

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

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

36

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

oneAPI 開発環境の設定•

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-beta03
ipp=latest

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

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

•

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

•

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

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

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

未定義（SETVARS_CONFIG 環境変数が存在しない）

37

3
•

定義されているが空（値を含まないか空白である）•

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 設定ファイルの作成
setvars 設定ファイルで使用する新規のテキストファイルを作成します。この例では、home フォルダーに config.txt という名前で作成します。
"${HOME}"/config/.txt または ~/config/.txt

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

SETVARS_CONFIG 環境変数の定義
SETVARS_CONFIG 環境変数はインストール中に自動的に定義されないため、Eclipse* を起動する前に（前述の方法で）環境変数を追加する必要があります。SETVARS_CONFIG 環境変数には、次のようにさ
まざまな場所を定義できます。

38

oneAPI 開発環境の設定•/etc/environment•/etc/profile•~/.bashrc•など ...

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

Linux* でモジュールファイルを使用
ほとんどのインテル® oneAPI コンポーネントのフォルダーには、それぞれのコンポーネントに必要な環
境変数を設定するモジュールファイルのスクリプトが含まれています。モジュールファイルを使用して、setvars.sh スクリプトに代わって開発環境を設定できます。モジュールファイルでは引数がサポートされていないため、複数の設定（32 ビットや 64 ビットの設定など）をサポートする oneAPI およびライブラリーでは複数のモジュールファイルを使用します。
インテル® oneAPI のモジュールスクリプトは、それぞれのコンポーネント・ディレクトリーにある
modulefiles フォルダーにあります（個々の vars スクリプトの配置方法と同様）。例えば、デフォルトのインストールでは、ipp のモジュールスクリプトは、/opt/intel/ipp/latest/modulefiles/ ディ
レクトリーにあります。
インテル® oneAPI コンポーネントのフォルダーがどのように展開されているかにより、 インテル®
openAPI モジュールファイルをインストール先で直接使用することが難しい場合があります。そのため、
oneAPI インストール・フォルダーには特殊な modulefiles-setup.sh スクリプトが用意されており、
oneAPI モジュールファイルの操作を簡単にできます。デフォルトのインストールでは、設定スクリプトは/opt/intel/oneapi/modulefiles-setup.sh に配置されます。
modulefiles-setup.sh スクリプトは、インテル® oneAPI のインストールに含まれるすべてのモ
ジュールスクリプトを検索し、それらのフォルダーを単一ディレクトリーに保存します。これらのフォル
ダーには、1 つ以上のモジュールファイルが含まれ、インストールされているインテル® oneAPI コンポー
ネントごとに名前が付けられます。
コンポーネントの名前が付けられたそれぞれのフォルダーには、そのインテル® oneAPI コンポーネントが提供するすべてのモジュールファイルを指すシンボリック・リンクが含まれます。シンボリック・リンクは、モジュールファイルのバージョンごとに編成されます。各コンポーネント・フォルダーには、少なくとも"latest"（最新）バージョンのモジュールファイルが含まれ、バージョンを指定しなくてもデフォルトで最新のコンポーネントをロードできます。
インテル® oneAPI モジュールファイルの最上位のディレクトリーのデフォルト名は modulefiles であり、これは oneAPI インストール・フォルダーにあります（例：/opt/intel/oneapi/modulefiles）。

39

3モジュールファイルのディレクトリーを作成
modulefiles-setup.sh スクリプトを実行します。
注：modulefiles-setup.sh スクリプトは、インテル® oneAPI ツールキットのインストール先にフォルダーを作成する必要があるため、root または sudo 権限で実行する必要があります。
modulefiles-setup.sh スクリプトが実行されると、次のような階層が最上位の modulefiles
フォルダーに作成されます。
[oneapi_root]- [modulefiles]- [compiler]- [1.0] -> [oneapi_root/compiler/1.0/modulefiles/compiler] # symlink
named 1.0 point to compiler modulefile- [compiler32]- [1.0] -> [oneapi_root/compiler/1.0/modulefiles/compiler32] # symlink
named 1.0 point to compiler32 modulefile- [ipp]- [1.1] -> [oneapi_root/ipp/1.1/modulefiles/ipp]- [1.2] -> [oneapi_root/ipp/1.1/modulefiles/ipp]- [ipp32]- [1.1] -> [oneapi_root/ipp/1.1/modulefiles/ipp32]- [1.2] -> [oneapi_root/ipp/1.1/modulefiles/ipp32]
etc...

ここで、MODULEFILESPATH を更新して、新しい modulefiles フォルダーを指すようにします。

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

tclsh のローカルコピーが新しいものであることを確認します（この時点では、バージョン 8.4 以降が必要です）。
$ tclsh% puts $tcl_version
8.6% exit40

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

注：ボーンシェル互換の初期化は、上記の source コマンドで機能するはずです。それ以外のシェル固有の init スクリプトは、/usr/share/modules/init/ フォルダーにあります。詳細については、各フォルダーと man module の初期化セクションをご覧ください。
init スクリプト（.../modules/init/sh）で module エイリアスを source して、モジュールコマン
ドが利用できるようにします。これにより、システムは次のセクションに示すモジュールコマンドを使用できます。

modulefiles-setup.sh スクリプト入門
次のことが前提とされています。
•

Linux* 開発システムに tclsh がインストールされている•システムに環境モジュール・ユーティリティー（module など）がインストールされている•

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

oneAPI 開発に必要なインテル® oneAPI ツールキットがインストールされている$ cd <oneapi-root-folder>$ ./modulefiles-setup.sh$ module use modulefiles$ module avail$ module load tbb$ module list
$ module unload tbb$ module list
module# cd to the oneapi_root install directory# run the modulefiles setup script# use the modulefiles folder created above# will show tbb/X.Y, etc.
# loads tbb/X.Y module# should list the tbb/X.Y module you just loaded# removes tbb/X.Y changes from the environment# should no longer list the tbb/X.Y env var

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

41

3

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

バージョン管理インテル® oneAPI ツールキットのインストーラーは、それぞれのツールまたはライブラリーの最上位
ディレクトリーでバージョン管理されたサブディレクトリー形式で、個々のインテル® oneAPI ツールおよびライブラリーのバージョンフォルダーを作成します。このようにバージョン管理されたコンポーネント・フォルダーは、モジュールファイルのバージョンを管理するために使用されます。これは基本的にmodulefiles-setup.sh ス ク リ プ ト に よ っ て 行 わ れ ま す 。 上 位 レ ベ ル の[$(ONEAPI_ROOT)/modulefiles] フォルダーに作成されるシンボリック・リンクは [<モジュール
ファイル名>/バージョン] として構成されるため、module コマンドを使用してバージョンごとのmodulefiles を参照できます。
$ module avail---------------- modulefiles ----------------ipp/1.1 ipp/1.2 compiler/1.0 compiler32/1.0

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

oneAPI で使用するモジュールファイルの記述法を理解する
シンボリック・リンクは modulefiles-setup.sh スクリプトによって使用され、すべてのツールとライ
ブラリー・モジュール・ファイルを oneAPI の上位レベルの modulefiles フォルダーに集約します。これは、インテル® oneAPI の modulefiles は移動または変更されないことを意味します。この結果、${ModulesCurrentModulefile} 変数は、それぞれのインストール・フォルダーにある実際のモ
ジュールファイルではなく、各モジュールファイルへのシンボリック・リンクを指します。そのため、これらのモジュールファイルは、シンボリック・リンクの影響でモジュールファイルのコンポーネント・フォルダー
内のフォルダーやファイルを参照できません。
このため、インテル® oneAPI の各モジュールファイルは、次のような形式を使用して、それぞれのインス
トール・ディレクトリーにある元の modulefile への参照を取得します。
[ file readlink ${ModulesCurrentModulefile} ]42

oneAPI 開発環境の設定
さらに詳しく理解するには、インストールに含まれる modulefiles を確認してください。ほとんどの場
合、実際のファイルへのシンボリック・リンク参照を解決するコメントと、バージョン番号（およびバージョン・ディレクトリー）の解析が含まれます。また、インストールされた TCL が適切なバージョンであることを確認するチェックと、同じモジュールファイルの異なるバージョンを誤ってロードしないようにする
チェックも含まれています。

modulefiles による module load コマンドの使用
modulefiles のいくつかは、module load コマンドを使用して依存関係のあるモジュールもロードできます。依存関係のあるモジュールファイルのバージョンチェックは行われません。これは、依存関係のあるモジュールを必要とするモジュールをロードする前に、その依存関係モジュールを手動で事前ロードできることを意味します。依存関係があるモジュールを事前ロードしない場合、最新バージョンがロードされます。
これは、環境を柔軟にコントロールできるようにする設計によるものです。例えば、以前のバージョンのコンパイラーで更新されたバージョンのライブラリーをテストするためインストールすると仮定します。
更新されたライブラリーにはバグ修正があり、更新されたライブラリー内の他のモジュールには興味がないという可能性もあります。依存するモジュールファイルが、ライブラリーの特定のバージョンを使用するようにハード・コーディングされている場合、このテストは機能しません。
注：依存関係のあるモジュールのロード条件を満たせない場合、モジュールのロードは終了し環境は変更されません。

関連情報
modulefiles の詳細については、以下をご覧ください。
•

http://www.admin-magazine.com/HPC/Articles/Environment-Modules（英語）•https://support.pawsey.org.au/documentation/display/US/Sample+modulefile+for+Environ
ment+Modules（英語）•https://www.chpc.utah.edu/documentation/software/modules-advanced.php（英語）oneAPI アプリケーションで CMake を使用
インテル® oneAPI 製品で提供される CMake パッケージを使用すると、 CMake プロジェクトでWindows* または Linux* 上の oneAPI ライブラリーを簡単に利用できます。このパッケージを使用する
ことで、他のシステム・ライブラリーが CMake プロジェクトと統合する方法と同様の体験ができます。
CMake プロジェクトのターゲットに応じて、依存関係が生じたり、他のビルド変数が必要になることがあ43

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

Linux*：•

システム：/usr/local/lib/cmake•

ユーザー： ~/lib/cmake

Windows*：
HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\CMake\Packages

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

44

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

4

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

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

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

•

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

•

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

コンパイラーの起動
インテル® oneAPI DPC++/C++ コンパイラーを起動するには、DPC++ アプリケーション向けには
dpcpp を、OpenMP* オフロードを使用する C++ アプリケーション向けには icpx -fiopenmp（Linux*）または icx /Qiopenmp（Windows*）を使用します。詳細については、『インテル® oneAPI
DPC++/C++ コンパイラー・デベロッパー・ガイドとリファレンス』の「コンパイラーの起動」を参照してください。
dpcpp コンパイラー・ドライバーは、OS ホストごとに互換性が異なります。Linux* では GCC スタイルのコマンドライン・オプションが提供され、Windows* では Microsoft Visual C++* 互換の機能が提供され
ます。

45

4
•

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

•

Windows* コマンドライン・オプション（「/」で開始）を認識し、Microsoft Visual Studio* ベースのプ
ロジェクトで使用できます。

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

•

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

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

API ベースのコード
次のコードは、インテル® oneAPI マス・カーネル・ライブラリーの oneapi::mkl::blas::axpy 関数を使用して、浮動小数点数のベクトル全体に対して a と x を乗算して y を加算する API 呼び出し（a * x + y）の使用法を示しています。このサンプルコードは、oneAPI プログラミング・モデルを利用して、アクセラレーターで加算を実行します。

46

oneAPI プログラムのコンパイルと実行#include <vector> // std::vector()#include <cstdlib> // std::rand()#include <CL/sycl.hpp>#include "oneapi/mkl/blas.hpp"
int main(int argc, char* argv[]) {double alpha = 2.0;
int n_elements = 1024;
int incx = 1;
std::vector<double> x;x.resize(incx * n_elements);for (int i=0; i<n_elements; i++)x[i*incx] = 4.0 * double(std::rand()) / RAND_MAX - 2.0;// -2.0 から 2.0 の範囲の rand 値
int incy = 3;
std::vector<double> y;y.resize(incy * n_elements);for (int i=0; i<n_elements; i++)y[i*incy] = 4.0 * double(std::rand()) / RAND_MAX - 2.0;// -2.0 から 2.0 の範囲の rand 値
cl::sycl::device my_dev;
try {my_dev = cl::sycl::device(cl::sycl::gpu_selector());} catch (...) {std::cout << "Warning, failed at selecting gpu device. Continuing on
default(host) device.\n";}// 非同期例外をキャッチ
auto exception_handler = [] (cl::sycl::exception_list
exceptions) {for (std::exception_ptr const& e : exceptions) {try {std::rethrow_exception(e);} catch(cl::sycl::exception const& e) {std::cout << "Caught asynchronous SYCL exception:\n";std::cout << e.what() << std::endl;}}};
cl::sycl::queue my_queue(my_dev, exception_handler);
cl::sycl::buffer<double, 1> x_buffer(x.data(), x.size());
cl::sycl::buffer<double, 1> y_buffer(y.data(), y.size());// y = alpha*x + y を計算
try {oneapi::mkl::blas::axpy(my_queue, n_elements, alpha, x_buffer,incx, y_buffer, incy);
}

47

4
catch(cl::sycl::exception const& e) {std::cout << "\t\tCaught synchronous SYCL exception:\n"<< e.what() << std::endl;}

std::cout << "The axpy (y = alpha * x + y) computation is complete!" <<std::endl;// y_buffer をプリント
auto y_accessor = y_buffer.template
get_access<cl::sycl::access::mode::read>();std::cout << std::endl;
std::cout << "y" << " = [ " << y_accessor[0] << " ]\n";
std::cout << "[ " << y_accessor[1*incy] << " ]\n";
std::cout << "[ " << "... ]\n";
std::cout << std::endl;
return 0;}

アプリケーション（axpy.cpp として保存）をコンパイルするには、次の操作を行います。
1.

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

2.

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

Windows*：
dpcpp -I${MKLROOT}/include /EHsc -c axpy.cpp /Foaxpy.obj

48

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

次のコマンドでアプリケーションをリンクします。
Linux*：
dpcpp 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*：
dpcpp 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

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

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

49

4

コンパイルの手順
オフロードを行うプログラムを作成する場合、コンパイラーはホストとデバイス向けの両方のコードを生成する必要があります。oneAPI は、この複雑な作業を開発者から見えないようにします。開発者は、
dpcpp を使用して DPC++ アプリケーションをコンパイルするだけで（一度のコンパイルコマンドで）、ホ
ストとデバイス向けのコードを生成できます。コンパイラーは、dpcpp ホストコードを生成しデバイス
コードを生成してから、デバイスコードをホストバイナリーに組込みます。バイナリーが起動されると、オ
ペレーティング・システムはホスト・アプリケーションを実行します。オフロードコードが組込まれている
場合、DPC++ ランタイムはデバイスコードをデバイスにロードし、デバイス上でアプリケーションを起動します。
デバイスコードの実行にはジャストインタイム（JIT：Just-in-Time）コンパイルと事前（AOT：Ahead-ofTime）コンパイルの 2 つのオプションがありますが、JIT がデフォルトです。このセクションでは、ホスト
コードのコンパイル方法と、デバイスコードを生成する 2 つの方法を説明します。詳しくは、『データ並列
C++ の書籍』（英語）の 13 章をご覧ください。

伝統的なコンパイル手順
従来のコンパイル手順は、C、C++、またはそのほかの言語で利用される標準のコンパイル方法です。

コンパイル手順を次の図に示します。
1.
2.
3.
4.
5.

50

フロントエンドは、ソースを中間表現に変換し、バックエンドに渡します。
バックエンドは、中間表現をオブジェクト・コードに変換してオブジェクト・ファイル（Windows* では host.obj、Linux* では host.o）を出力します。
1 つ以上のオブジェクト・ファイルがリンカーに渡されます。
リンカーは実行ファイルを生成します。
これで、アプリケーションを実行できます。

oneAPI プログラムのコンパイルと実行JIT のコンパイル手順
JIT コンパイルは、C、C++、またはそのほかの言語で使用される標準のコンパイルと同じように開始されますが、デバイスコード生成の手順が追加されます。アプリケーションが起動されると、ランタイムは利用可能なデバイスを判別してそのデバイス固有のコードを生成します。これにより、AOT（事前）コンパイル手順よりも、アプリケーションの実行環境とパフォーマンスの柔軟性が高まります。しかし、アプリケー
ションの実行時にコンパイル（JIT）が行われるため、アプリケーションの実行時間が増加する可能性があります。大量のデバイスコードを持つ大規模なアプリケーションでは、パフォーマンスへの影響が顕著に表れることがあります。
注：JIT コンパイラーは、FPGA デバイスではサポートされません。
コンパイル手順を次の図に示します。

1.
2.
3.
4.

ホストコードは、バックエンドでオブジェクト・コードに変換されます。
デバイスコードは SPIR-V* 形式に変換されます。
リンカーは、ホスト・オブジェクト・コードとデバイス SPIR-V* を組み合わせた、（SPIR-V* が埋め込
まれた）ホスト実行コードを含むファットバイナリーを生成します。
実行されると次のように処理されます。
a.
b.

5.

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

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

AOT のコンパイル手順
AOT（事前）コンパイルは、C、C++、またはそのほかの言語で使用される標準のコンパイルと同じように開始されますが、デバイスコード生成の手順が追加されます。JIT 手順とは異なり、AOT 手順では実行ファイルが作成される前にデバイスバイナリーに変換されます。AOT 手順では、コンパイル時にターゲッ

51

4
トデバイスを決定する必要があるため、JIT 手順よりも柔軟性は低くなります。しかし、実行ファイルの起動時間は JIT 手順よりも短くなります。
ヒント：AOT 手順では、デバッグサイクルが高速化されるため、アプリケーションをデバッグする際の利用が推奨されます。
コンパイル手順を次の図に示します。

1.
2.
3.
4.
5.
6.

ホストコードは、バックエンドでオブジェクト・コードに変換されます。
デバイスコードは SPIR-V* 形式（SPIR-V.obj）に変換されます。
デバイスの SPIR-V* は、コマンドラインでユーザーが指定したデバイス向けのデバイス・コード・オ
ブジェクトに変換されます。
リンカーは、ホスト・オブジェクト・コードとデバイス・オブジェクト・コードを組み合わせた、デバイス
バイナリーが埋め込まれたホスト実行コードを含むファットバイナリーを生成します。
実行時に、デバイスバイナリーはデバイスへロードされます。
アプリケーションは、ホストと指定されたデバイスで実行されます。

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

52

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

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

•

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

CPU：ELF（Linux*）、PE（Windows*）•

GPU：ELF（Windows*、Linux*）•

FPGA：ELF（Linux*）、PE（Windows*）

CPU 手順
DPC++ は、CPU ターゲットのオンラインおよびオフラインのコンパイルモードをサポートしています。
オンラインコンパイルは、ほかのすべてのターゲットと同様です。

CPU 向けのオンラインコンパイル
CPU ターゲットの指定はありません。次のコマンドは、SPIR-V* イメージを含むファットバイナリーを生成します。これは、CPU を含む互換性のあるデバイスでオンラインコンパイルして実行できます。
dpcpp a.cpp b.cpp -o app.out

CPU 向けのオフラインコンパイル
注：これは、機能が制限された実験的な試みです。
このコマンドを使用して、x86 デバイスでのみ実行可能な app.out を生成します。
dpcpp -fsycl-targets=spir64_x86_64-unknown-linux-sycldevice a.cpp b.cpp -o
app.out

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

53

4

注：動的ライブラリーとのリンクはサポートされていません。
デバイスコードを使用してファット・オブジェクトを生成します。
dpcpp -c static_lib.cpp

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

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

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

CPU アーキテクチャー向けの最適化オプション
オフライン・コンパイル・モードでは、最適化オプションを使用して、特定の CPU アーキテクチャーでの実行を改善するコードを生成できます。これらは、dpcpp の -fsycl-target-backend オプションを介して渡されます。
Linux*：
dpcpp -fsycl-targets=spir64_x86_64-unknown-linux-sycldevice \-Xsycl-target-backend=spir64_x86_64-unknown-linux-sycldevice “<CPU optimization
flags>”\
a.cpp b.cpp -o app.out

Windows*：
dpcpp -fsycl-targets=spir64_x86_64-unknown-linux-sycldevice ^-Xsycl-target-backend=spir64_x86_64-unknown-linux-sycldevice “<CPU optimization
flags>” ^a.cpp b.cpp -o app.out

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

54

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

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

CPU 上のホストとカーネルのインタラクション
ホストコードは、OpenCL* データバッファーの cl::sycl::accessor オブジェクトまたは cl_mem
オブジェクトで示されるカーネル・パラメーターとデータバッファーを介してデバイスコードと対話します。

複数の CPU コア上でバイナリーの実行をコントロール
環境変数
次の環境変数は、プログラムの実行中に複数の CPU コアでの DPC++ スレッドの配置をコントロールし
ます。

環境変数

説明

DPCPP_CPU_CU_AFFINITY

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

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

この環境変数は、OpenMP* の OMP_PROC_BIND 環境変数に似ています。
デフォルト：未設定
DPCPP_CPU_SCHEDULE

スケジューラーが work-group をスケジュールするアルゴリズムを指定します。
現在、DPC++ は TBB のスケジューラーを使用しています。この値は、インテル®
TBB スケジューラーが使用するパーティショナーを選択します。以下を指定でき
ます。
•
•

•

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

デフォルト：dynamic

55

4

DPCPP_CPU_NUM_CUS

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

DPCPP_CPU_PLACES

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

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

例 1：ハイパースレッディング有効
2 ソケットで、ソケットごとに 4 つの物理コアがあり、それぞれの物理コアには 2 つのハイパースレッドがあるマシンを想定します。
•

S<num> リストで指定される 8 つのコアを持つソケット番号を示します。

•

T<num> TBB スレッドの番号を示します。

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

56

oneAPI プログラムのコンパイルと実行
DPCPP_CPU_NUM_CUS=16
export DPCPP_CPU_PLACES=sockets
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_PLACES=cores
DPCPP_CPU_CU_AFFINITY=close:
S0:[T0 T8 T1 T9 T2 T10 T3 T11]
DPCPP_CPU_CU_AFFINITY=spread:
S0:[T0 T8 T2 T10 T4 T12 T6 T14]
DPCPP_CPU_CU_AFFINITY=master:S0:[T0 T1 T2 T3 T4 T5 T6 T7]

S1:[T4 T12 T5 T13 T6 T14 T7 T15]
S1:[T1 T9 T3 T11 T5 T13 T7 T15]
S1:[T8 T9 T10 T11 T12 T13 T14 T15]

export DPCPP_CPU_PLACES=threads
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:[]

例 2：ハイパースレッディング無効
2 ソケットで、ソケットごとに 4 つの物理コアがあり、それぞれの物理コアには 2 つのハイパースレッドがあるマシンを想定します。
•

S<num> リストで指定される 8 つのコアを持つソケット番号を示します。

•

T<num> TBB スレッドの番号を示します。

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

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:[ - - - - ]57

4

GPU 手順GPU 手順は CPU 手順に似ていますが、異なるバックエンドとターゲットトリプル（表現形式）が使用される点が異なります。GPU オフライン・コンパイラーのターゲットトリプルは、spir64_gen-unknownlinux-sycldevice です。
注：現在、GPU オフラインコンパイルでは、ターゲットの GPU アーキテクチャーを指定するオプションが
必要です。

関連情報
インテル® oneAPI GPU 最適化ガイド（英語）GPU コマンドの例
次の例は、Linux* でデバイスコードを使用して静的ライブラリーを作成し、使用する方法を示します。
注：動的ライブラリーとのリンクはサポートされていません。
デバイスコードを使用してファット・オブジェクトを生成します。
dpcpp -c static_lib.cpp

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

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

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

GPU 向けのオフラインコンパイル
次のコマンドは、特定の GPU ターゲット向けに app.out を生成します。

58

oneAPI プログラムのコンパイルと実行Linux*：
dpcpp -fsycl-targets=spir64_gen-unknown-linux-sycldevice \-Xsycl-target-backend=spir64_gen-unknown-linux-sycldevice "-device skl" a.cpp b.cpp -o
app.out

Windows*：
dpcpp -fsycl-targets=spir64_gen-unknown-linux-sycldevice ^-Xsycl-target-backend=spir64_gen-unknown-linux-sycldevice "-device skl" a.cpp b.cpp -o
app.out

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

デバイスコード

ホストではなくデバイスで実行される SYCL* ソースコード。デバイスコードは、ラムダ式、ファンクター、またはカーネルクラスを介して指定されます（例、カーネルコード）。

ホストコードホスト・コンパイラーによってコンパイルされ、デバイスではなくホストで実行される
SYCL* ソースコード。

デバイスイメージ

デバイスコードをバイナリー（または中間）表現にコンパイルした結果のファイル。デバ
イスイメージは、（ファット）オブジェクトまたは実行ファイル内でホスト・オブジェクトと結合されます。「コンパイル手順」を参照してください。

FPGA エミュレーター・

FPGA エミュレーター向けにコンパイルされたデバイスイメージ。「FPGA エミュレー

イメージ

ター」を参照してください。

FPGA 初期イメージ

初期コンパイルステージによるデバイスイメージ。「FPGA 最適化レポート」を参照してください。

59

4

FPGA ハードウェア・

ハードウェア・イメージのコンパイルステージによるデバイスイメージ。「FPGA 最適化

イメージレポート」と「FPGA ハードウェア」を参照してください。

注 ： FPGA プ ロ グ ラ ミ ン グ の 詳 細 は 、 https://link.springer.com/chapter/10.1007/978-1-48425574-2_17（英語）から入手できるデータ並列 C++ の書籍からも学ぶことができます。

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

DPC++ FPGA コンパイルの種別
以下の表に、FPGA コンパイルの要約を示します。
DPC++ FPGA コンパイルの種別
デバイス・イメージ・タイプ

コンパイル時間説明

FPGA エミュレーター

数秒

FPGA デバイスコードは CPU 向けにコンパイルされます。
FPGA エミュレーターを使用して、SYCL* コードが正しく機能することを確認します。

FPGA 初期イメージ

数分

FPGA デバイスコードは部分的にハードウェア向けにコンパ
イルされます。コンパイラーは、FPGA で生成される構造とパフォーマンスのボトルネックを特定し、リソース利用率を推測して最適化レポートを生成します。

60

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

FPGA ハードウェア・

数時間

イメージ

ターゲットの FPGA プラットフォームで実行する FPGA ビッ
トストリームを生成します。

一般的な FPGA 開発ワークフローでは、これらの各ステージで手順を繰り返し、それぞれのステージからもたらされるフィードバックを反映してコードを改良します。可能な限りエミュレーションと FPGA 最適化レポートを活用することを推奨します。
ヒント：FPGA エミュレーション向けにコンパイルしたり、FPGA 最適化レポートを生成するには、
インテル® oneAPI ベース・ツールキットのみが必要です。FPGA ハードウェアのコンパイルには、oneAPI
ベース・ツールキット対応のインテル® FPGA アドオン（英語）が必要です。アドオンのインストール手順の詳細は、『インテル® oneAPI ツールキット・インストール・ガイド』（英語）をご覧ください。

FPGA エミュレーターFPGA エミュレーターの活用は、コードの正当性を検証する最速の手法です。CPU 上でデバイスコードを実行しますが、FPGA パイプや fpga_reg などすべての拡張機能がサポートされます。詳細については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』の「パイプ拡張」（英語）と「カーネル変数」（英語）を参照してください。
次に FPGA エミュレーターを使用する際に覚えておくべき重要事項を示します。
•

パフォーマンスは代表的なものではない

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

未定義の動作は異なる可能性があります

FPGA エミュレーターと FPGA ハードウェア向けにコンパイルしたコードの結果が異なる場合、コードに未定義の動作が含まれる可能性があります。未定義の動作は言語仕様では指定されておらず、ターゲッ
トごとに振る舞いが異なる可能性があります。
ヒント：FPGA エミュレーター・デバイスをターゲットにする場合、-O2 コンパイルオプションを使用して最適化を有効にしてエミュレーターを高速化します。（デバッグを容易にするため）最適化をオフにするには -O0 オプションを指定します。

61

4
FPGA 最適化サポート
完全な FPGA コンパイルは次のステージで行われ、最適化レポートは両方のステージの後に出力されま
す。
ステージ

説明

最適化レポートの情報

FPGA 初期イメージ

SYCL* デバイスコードは最適化され、これには、コンパイラーが SYCL* デバイ（コンパイルには数

Verilog レジスター転送レベル（RTL）

スコードから FPGA 設計に変換した手法

分かかります）（FPGA の低レベルの設計入力言語）で指定に関する重要な情報が含まれています。

される FPGA 設計に変換されます。これにレポートには次の情報が含まれます。

より、実行形式ファイルではない FPGA 初•

報期イメージが生成されます。
このステージで生成される最適化レポート

FPGA で生成された構造の可視化情•パフォーマンスと予期されるパフォー
マンスのボトルネックに関する情報

は、静的レポートと呼ばれることがありま

リソースの利用状況を推測す。

•

FPGA ハードウェア・

設計回路のトポロジーを指定する Verilog

リソースと fmax 数に関する正確な情報がイメージ

RTL は、インテル® Quartus® Prime ソフト

含まれます。レポートの解析に関する詳（コンパイルには数

ウェアによって FPGA のプリミティブ・ハー

細は、『インテル® oneAPI DPC++ FPGA

時間を要します）ドウェア・リソースにマッピングされます。コ

最適化ガイド』の「設計の解析」（英語）をンパイルステージに必要なインテル®

参照してください。

Quartus® Prime ソフトウェアは、oneAPI
ベース・ツールキット用インテル® FPGA ア
ドオン（英語）に含まれています。 結果は、
FPGA ビットストリーム（またはバイナリー）を含む FPGA ハードウェア・イメージです。

FPGA ハードウェア
これは FPGA ハードウェア・イメージへの完全なコンパイルです。インテル® プログラマブル・アクセラ
レーション・カード（インテル® Arria® 10 GX FPGA 搭載版）、インテル® FPGA PAC D5005（インテル®
FPGA プログラマブル・アクセラレーション・カード D5005）、またはカスタムボードをターゲットにできます。
インテル® PAC またはカスタムボードを使用する詳細については、「FPGA BSP とボード」を参照してください。

62

oneAPI プログラムのコンパイルと実行
FPGA コンパイルオプション
FPGA コンパイルオプションは、インテル® oneAPI DPC++/C++ コンパイラーがターゲットとする FPGA
イメージタイプをコントロールします。
# FPGA emulator image
dpcpp -fintelfpga fpga_compile.cpp# FPGA early image (with optimization report): default board
dpcpp -fintelfpga -Xshardware -fsycl-link fpga_compile.cpp# FPGA early image (with optimization report): explicit board
dpcpp -fintelfpga -Xshardware -fsycl-link -Xsboard=intel_s10sx_pac:pac_s10
fpga_compile.cpp# FPGA hardware image: default board
dpcpp -fintelfpga -Xshardware fpga_compile.cpp -c -o fpga_compile.fpga# FPGA hardware image: explicit board
dpcpp -fintelfpga -Xshardware -Xsboard=intel_s10sx_pac:pac_s10 fpga_compile.cpp

以下は、3 つの FPGA イメージタイプをターゲットとするインテル® oneAPI DPC++/C++ コンパイラーのコマンド例です。
注：プリフィクス -Xs を使用して、引数を FPGA バックエンドに渡します。
次の表は上記のコマンド例で使用するオプションを説明しています。
FPGA コンパイルオプション
オプション

説明

-fintelfpga

FPGA 向けに（オフライン）コンパイルします。

-Xshardware

FPGA ハードウェアをターゲットにすることをコンパイラーに指示します。このオプションが省略されると、コンパイラーはデフォルトの FPGA エミュレー
ターをターゲットにします。

-fsycl-link

FPGA 初期イメージ（および関連する最適化レポート）を作成して停止するようコンパイラーに指示します。

-Xsboard=<bsp:variant>[オプションの引数] FPGA ボードバリアントと BSP を指定します。省略されると、コンパイラーは intel_a10gx_pac BSP から、デフォルトのpac_a10 FPGA ボードバリアントを選択します。詳細については、「FPGABSP とボード」を参照してください。

63

4

警告：dpcpp コンパイルコマンドの出力は、同じ出力名を持つ以前のコンパイル出力を上書きします。そのため、一意の出力名（-o で指定）を使用することを推奨します。失ったハードウェア・イメージの再生成には数時間を要することがあるため、FPGA コンパイルでは注意する必要があります。
上記のコンパイルオプションに加えて、dpcpp コマンドの出力詳細レベル、コンパイルで使用するスレッ
ド数をコントロールするオプションも用意されています。次のセクションでは、これらのオプションについて簡単に説明します。

コンパイラーでサポートされるそのほかの SYCL* FPGA オプション
インテル® oneAPI DPC++/C++ コンパイラーには、カーネルのコンパイルプロセスをカスタマイズする
オプションが用意されています。次の表にコンパイラーがサポートするそのほかのオプションをまとめています。
そのほかの FPGA オプション
オプション名説明-fsycl-help=fpga

dpcpp コマンドの FPGA 固有のオプションを出力します。

-fsycl-link=early-fsycl-link=image•-fsycl-link=early と -fsycl-link は同じ意味です。どちらも、
FPGA 初期イメージ（および関連する最適化レポート）を作成して停止するようコンパイラーに指示します。

•-fsycl-link=image は、デバイスリンクのコンパイル手順で使用さ
れ、FPGA ハードウェア・イメージを生成するようにコンパイラーに指示します。詳細については、「FPGA 高速再コンパイル」をご覧ください。

-reuse-exe=<exe_file>

既存の実行形式ファイルから FPGA ハードウェア・イメージを抽出して、新[Linux* のみ]

しい実行形式ファイルにパッケージするようにコンパイラーに指示します。
これにより、デバイスコンパイル時間を節約します。このオプションは、ハードウェア向けにコンパイルする際に役立ちます。詳細については、「FPGA
高速再コンパイル」をご覧ください。

-Xsv

FPGA バックエンドは、コンパイルの進行状況を示すレポートを生成します。

-Xsemulator

エミュレーション・デバイス・イメージを生成します。これは、デフォルトの動作です。

-Xsparallel=<num_threads>

FPGA ビットストリーム・コンパイルで使用される並列レベルを設定します。
<num_threads> 値には使用する並列スレッドの数を指定します。推奨される最大値は利用可能なコア数です。このオプションは任意です。デフォル

64

oneAPI プログラムのコンパイルと実行
トでは、インテル® Quartus® Prime ソフトウェアは利用可能なすべてのコアを使用して並列コンパイルを行います。
-Xsseed=<value>

FPGA ビットストリームを生成する際にインテル® Quartus® Prime ソフト
ウェアが使用するシードを設定します。値は符号なし整数で、デフォルト値
は 1 です。

-Xsfast-compile

最短時間で FPGA ビットストリームのコンパイルを実行します。このオプ
ションを指定すると、コンパイル時間が短縮されますが、コンパイルされた
FPGA ハードウェア・イメージのパフォーマンスは低下します。このオプショ
ンは、開発時間を短縮したい場合にのみ使用してください。製品レベルの品
質は期待できません。

FPGA の最適化オプションに関する詳細は、『インテル® oneAPI DPC++ FPGA 最適化ガイド』の「最適化オプション」（英語）を参照してください。

FPGA デバイスセレクター
ホストコードで正しい SYCL* デバイスセレクターを使用して、FPGA エミュレーターまたは FPGA ハー
ドウェアのターゲットを選択します。次のコード例は、セレクターを使用してコンパイル時にターゲットデ
バイスを指定する方法を示しています。
// FPGA デバイスセレクターは、パイプや fpga_reg などすべての// FPGA 拡張機能とともにユーティリティー・ヘッダーで定義されます#include <CL/sycl/INTEL/fpga_extensions.hpp>
int main() {// 次のいずれかを選択://- FPGA エミュレーター・デバイス (CPU で FPGA をエミュレーション)// - FPGA デバイス (実際の FPGA)#if defined(FPGA_EMULATOR)INTEL::fpga_emulator_selector device_selector;#else
INTEL::fpga_selector device_selector;#endifqueue q(device_selector);
...
}

65

4

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

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

FPGA 高速再コンパイルインテル® oneAPI DPC++/C++ コンパイラーは、FPGA ハードウェアでは事前（AOT）コンパイルのみをサポートします。FPGA ハードウェア・イメージは、コンパイル時に生成されます。FPGA ハードウェア・イ
メージの生成には、コンパイルが完了するまで数時間かかる場合があります。ホストコードにのみ影響する変更を行った場合、FPGA ハードウェア・イメージを再利用して、時間のかかるデバイスコンパイルを回避しホストコードのみを再コンパイルします。
インテル® oneAPI DPC++/C++ コンパイラーは、デバイスコードとホストコードのコンパイルを分離する
次の機能をサポートします。
•-reuse-exe=<exe_name> オプション（Linux* のみ）を指定して、既存の FPGA ハードウェア・イ
メージを再利用するようコンパイラーに指示します。

•

ホストとデバイスのコードを別々のファイルに分離します。コードの変更がホストファイルにのみ影響する場合、FPGA ハードウェア・イメージは生成されません。

次のセクションでは、この 2 つの機能について詳しく説明します。

66

oneAPI プログラムのコンパイルと実行-reuse-exe オプションを使用
前回のコンパイル以降、デバイスに影響するデバイスコードとオプションが変更されていない場合、-reuse-exe=<exe_name> オプションを指定して FPGA ハードウェア・イメージを既存の実行形式
ファイルから抽出して、新しい実行形式ファイルにパッケージするようにコンパイラーに指示します。これ
により、デバイスコンパイル時間を節約します。
使用例：# 最初のコンパイル
dpcpp -fintelfpga -Xshardware <files.cpp> -o out.exe

最初のコンパイルで FPGA ハードウェア・イメージを生成しますが、これには数時間かかります。ここで、ホストコードに変更を加えます。
# その後のコンパイル
dpcpp <files.cpp> -o out.exe -reuse-exe=out.exe -Xshardware -fintelfpga

コマンドにより次のいずれかのアクションが実行されます。
•

out.exe が存在しない場合、-reuse-exe オプションは無視され、FPGA ハードウェア・イメージが再生成されます。これは、プロジェクトを初めてコンパイルする場合、常にあてはまります。

•

out.exe が存在すると、コンパイラーは FPGA デバイスコードに影響する変更が前回のコンパイル以降に行われていないか確認します。デバイスコードに影響する変更が行われていない場合、コンパ
イラーは既存の FPGA ハードウェア・イメージを再利用してホストコードのみを再コンパイルします。
再コンパイルには数分かかります。

注：FPGA ハードウェア・イメージを安全に再利用できるか確認するため、デバイスコードが部分的に再コンパイルされます。

デバイスリンクを使用
プログラムが main.cpp と kernel.cpp で構成され、kernel.cpp ファイルのみがデバイスコード
を含むと仮定します。
通常のコンパイル手順では、FPGA ハードウェア・イメージの生成はリンク時に行われます。
# 通常のコンパイルコマンド
dpcpp -fintelfpga -Xshardware main.cpp kernel.cpp -o fpga_compile.exe

main.cpp または kernel.cpp のどちらかを変更すると、FPGA ハードウェア・イメージの再生成がトリガーされます。

67

4
ホストコードを繰り返し処理し、FPGA デバイスのコンパイル時間が長くならないようにするには、デバイ
スリンクを使用してデバイスとホストのコンパイルを分離することを検討してください。デバイスリンクは次の 3 つのステップからなります。
1.

デバイスコードをコンパイルします。
dpcpp -fintelfpga -Xshardware -fsycl-link=image kernel.cpp -o dev_image.a

入力ファイルには、デバイス上で実行されるソースコード（カーネルなど）を含むすべてのファイルを含める必要があります。このステップには数時間かかります。
2.

ホストコードをコンパイルします。
dpcpp -fintelfpga main.cpp -c -o host.o

入力ファイルには、ホストコードのみを対象とするすべてのソースファイルを含める必要があります。
これには、デバイスで実行されるソースコードを含めることはできませんが、コマンドライン・オプ
ションの解釈や結果レポートなどのセットアップ・コードとティアダウン・コードを含めることができます。このステップには数秒かかります。
3.

デバイスリンクを作成します。
dpcpp -fintelfpga host.o dev_image.a -o fast_recompile.exe

このステップには数秒かかります。入力には、1 つ以上のホスト・オブジェクト・ファイル（.o）と 1 つのデバイスファイル（.a）を含める必要があります。静的ライブラリー（.a ファイル）を使用する場合、
必ず静的ライブラリーをリンクしてください。これ以外ではライブラリー関数は破棄されます。静的
ラ イ ブ ラ リ ー に 関 す る 詳 細 は 、 https://eli.thegreenplace.net/2013/07/09/library-order-instatic-linking（英語）を参照してください。
ヒント： この 3 つのステップを少なくとも一度実行していると、デバイスコードを変更しない限り、ステップ 1は省略できます。
 次のように、ステップ 2 と 3 を 1 つにまとめることができます。
dpcpp -fintelfpga main.cpp dev_image.a -o fast_recompile.exe

68oneAPI プログラムのコンパイルと実行
次の図はデバイスのリンク手順を示します。
FPGA デバイスリンク

デバイスリンクの使い方については、「インテル® oneAPI サンプルブラウザー」（英語）の「fast_recompile」（英語）チュートリアルを参照してください。

どの機能を使用するか?
前述の 2 つの機能では、デバイスリンクよりも -reuse-exe オプションを使用する方が容易です。このオプションを使用すると、ホストとデバイスのコードを単一ソースとして記述することができます。これは小規模なプログラムに適しています。大規模で複雑なプロジェクトでは、デバイスリンクにはコンパイ
ラーの動作を細かくコントロールできる利点があります。
しかし、個別のファイルをコンパイルするのと比較すると -reuse-exe オプションにはいくつかの欠点もあります。以下に -reuse-exe オプションを使用する際の注意点を示します。
•

コンパイラーは、影響するソースの変更がないことを確認するため、デバイスコードを部分的に再コンパイルする時間が必要です。

•

コンパイラーがデバイスコードの再コンパイルが必要であると誤って判断した場合、偽陽性となることがあります。単一のソースコードでは、ホストとデバイスコードが混在するため、ホストコードに変更を加えるとコンパイラーによるデバイスコードのビューが変わる可能性があります。コンパイラーは常に保守的であり、以前の FPGA バイナリーの再利用が安全であると確認できない場合、完全な再コンパイルをトリガーします。

69

4
FPGA BSP とボード
「DPC++ FPGA コンパイルの種別」で説明したように、FPGA ハードウェア・イメージを生成するには、「oneAPI ベース・ツールキット用インテル® FPGA アドオン」（英語）が必要です。これには、RTL からFPGA のプリミティブ・ハードウェア・リソースに設計をマッピングするインテル® Quartus® Prime ソフト
ウェアが用意されています。さらに、このアドオンパッケージは、FPGA ハードウェアへのコンパイルに必要な基本的なボード・サポート・パッケージ（BSP）を提供します。

ボードとは?
GPU と同様に、FPGA はサーバーまたはデスクトップ・コンピューターに搭載されるカードまたはマウン
トされる集積回路です。FPGA ボードは、メモリー、電力、熱管理、およびほかのデバイスと通信する物理
インターフェイスを提供します。

BSP とは?
BSP は、ソフトウェア・レイヤーと FPGA ハードウェア・スキャホールド・デザインで構成されており、インテル® oneAPI DPC++/C++ コンパイラーを介して FPGA をターゲットにできます。コンパイラーによって生成された FPGA デザインは、BSP で提供されるフレームワークに組込まれています。

ボードバリアントとは?
BSP は 、 さ ま ざ ま な 機 能 を サ ポ ー ト す る 複 数 の ボ ー ド バ リ ア ン ト を 提 供 で き ま す 。 例 え ば 、
intel_s10sx_pac BSP には、統合共有メモリー（USM）のサポート方法が異なる 2 つのバリアントがあります。USM の詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドとリファレンス』の「統合共有メモリー（USM）」（英語）を参照してください。
注：ボードが複数の BSP をサポートし、BSP は複数のボードバリアントをサポートする場合があります。
oneAPI ベース・ツールキット用インテル® FPGA アドオンは、2 つのボード BSP を提供し、この BSP に
よってサポートされるボードバリアントは dpcpp コマンドで次のオプションを使用して選択できます。
ボード

BSP

オプション

USM サポート

インテル® プログラマブル・

intel_a10gx_pac-Xsboard=intel_a10gx_pac:
pac_a10

明示的な USM

アクセラレーション・カード（インテル® Arria® 10 GXFPGA 搭載版）

70

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

インテル® FPGA PAC

intel_s10sx_pac

D5005（インテル® FPGA プ
ログラマブル・アクセラレー
ション・カード D5005）-Xsboard=intel_s10sx_pac:
pac_s10

明示的な USM-Xsboard=intel_s10sx_pac:
pac_s10_usm

明示的な USM
制限付き USM（旧名称：インテル® Stratix®
10 SX FPGA 搭載版）

注：
 インテル® oneAPI DPC++/C++ コンパイラー（インテル® oneAPI ベース・ツールキットに含まれます）
は、FPGA の初期イメージを生成するのに十分な部分的な BSP を提供します。対照的に、oneAPI
ベース・ツールキット用インテル® FPGA アドオンは、FPGA ハードウェア・イメージの生成に必要な完全な BSP を提供します。
 FPGA ボードで DPC++ の実行形式ファイルを実行する場合、実行形式ファイルがターゲットのボー
ドバリアント向けに FPGA ボードを初期化したことを確認する必要があります。FPGA ボードの初期化については、「FPGA ボードの初期化」を参照してください。
 制限付き USM に適用可能な FPGA の最適化については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』（英語）の「事前固定（プリピニング）」（英語）と「ゼロコピーのメモリーアクセス」（英語）を参照してください。

カスタム BSP
上記の BSP に加えて、ボードベンダーが提供するカスタム BSP を使用することもできます。カスタム
BSP でインテル® oneAPI DPC++/C++ コンパイラーを使用するには、次の手順に従ってください。
1.

2.
3.

カスタム BSP に必要なバージョンのインテル® Quartus® Prime 開発ソフトウェアを含む、
インテル® カスタム・プラットフォーム・パッケージ向けのインテル® FPGA アドオンをインストール
します。詳細については、『インテル® oneAPI ツールキット・インストール・ガイド』（英語）を参照してください。
アドオンのインストール先ディレクトリー（intelfpgadpcpp/latest/board) に完全なカスタ
ム BSP を配置します。
BSP ベンダーが提供するインストール手順に従ってください。

FPGA ボードの初期化
FPGA ハードウェア・イメージを含む DPC++ 実行形式を実行する前に、次のコマンドを使用して FPGA
ボードを初期化する必要があります。
aoclinitialize<board id> <board variant>

71

4
説明：
パラメーター説明<board_id>

aocl diagnose コマンドから取得したボード ID。例：ac10、ac11 など。

<board variant>

DPC++ 実行形式のコンパイル時に -Xsboard オプションで指定されたボードバリアントの名前。例：pac_s10_usm。

例えば、システムに 1 台のインテル® FPGA PAC D5005（インテル® FPGA プログラマブル・アクセラ
レーション・カード D5005）（旧名称：インテル® Stratix® 10 SX FPGA 搭載版）が搭載され、次のコマンドで DPC++ 実行形式ファイルをコンパイルすると仮定します。
dpcpp -fintelfpga -Xshardware -Xsboard=intel_s10sx_pac:pac_s10_usm kernel.cpp

この場合、次のコマンドでボードを初期化する必要があります。
aocl initialize acl0 pac_s10_usm

初期化が完了すると、次のいずれかを実行する場合を除き、ボードを再び初期化することなく DPC++ 実
行形式ファイルを実行できます。
•

ホストの電源をオンにした後、初めて DPC++ ワークロードを実行する。

•

FPGA で DPC++ ワークロード以外を実行した後に DPC++ ワークロードを実行する。

•-Xsboard オプションで別のボードバリアントでコンパイルされた DPC++ ワークロードを実行する。

複数の同種の FPGA デバイスをターゲットにする
インテル® oneAPI DPC++/C++ コンパイラーは、単一ホスト CPU から複数の同種の FPGA デバイスをターゲットにすることをサポートします。これにより、複数の FPGA でプログラムを並列化して実行することで、設計のスループットを向上できる可能性があります。
複数コンテキストでは、OpenCL* レイヤーのバッファーをコンテキスト間でコピーする必要があり、オーバーヘッドが発生して全体のパフォーマンスに影響を及ぼすため、複数のデバイスキューを使用して単一のコンテキストを作成することを推奨します。ただし、設計が単純でオーバーヘッドが全体のパフォーマ
ンスに影響しない場合は、複数コンテキストを使用できます。
次のいずれかの方法で複数の FPGA デバイスをターゲットにします。

72

oneAPI プログラムのコンパイルと実行
複数のデバイスキューで単一のコンテキストを作成
次の手順を実行して、単一のコンテキストで複数の 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) {...});}

それぞれのデバイスキュー向けにコンテキストを作成（複数コンテキスト)
次の手順を実行して、複数のコンテキストで複数の 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);

}

73

4
3.

利用可能なすべての FPGA デバイスに、同一または異なるデバイスコードを送信します。すべてのデバイスのサブセットをターゲットにする場合、不要なデバイスを除外するため最初にデバイスの選択を実行する必要があります。
for (unsigned int i = 0; i < queueList.size();i++) { queueList[i].submit([&](handler& cgh){...});}

制限事項
複数の FPGA デバイスをターゲットにする場合、次の制限事項を考慮してください。
•

すべての FPGA デバイスは同じ FPGA ビットストリームを使用します。

•

使用するすべての FPGA デバイスは、同一の FPGA カードである必要があります（同じ -Xsboard
target）。

複数のプラットフォームをターゲットにする（異なるデバイスセレクターを使用して）複数のターゲット・デバイス・タイプを対象とする設計をコンパイ
ルするには、次のコマンドを実行します。

エミュレーション・コンパイル
FPGA エミュレーター・ターゲットの SYCL* コードのコンパイルには、次のコマンドを使用します。
dpcpp -fsycl-targets=spir64-unknown-unknown-sycldevice \jit_kernel.cpp -c -o jit_kernel.o
dpcpp -DFPGA_EMULATOR \-fsycl-targets=spir64_fpga-unknown-unknown-sycldevice fpga_kernel.cpp \-c -o fpga_kernel.o
dpcpp -DFPGA_EMULATOR \-fsycl-targets=spir64_fpga-unknown-unknown-sycldevice,spir64-unknown-unknownsycldevice \main.cpp jit_kernel.o fpga_kernel.o -o emulator.out

この例は、FPGA カーネル（AOT 手順）と CPU カーネル（JIT 手順）およびライブラリーを使用します。
dpcpp -DFPGA_EMULATOR -fsycl \-fsycl-targets=spir64_fpga-unknown-unknown-sycldevice,spir64-unknown-unknownsycldevice main.cpp
jit_kernel.o fpga_kernel.o -o emulator.out

74

oneAPI プログラムのコンパイルと実行
具 体 的 に は 、 main.cpp フ ァ イ ル に main 関 数 が 含 ま れ 、 CPU （ jit_kernel.cpp ） と FPGA
（fpga_kernel.cpp）の両方のカーネルを必要とします。
サンプルの jit_kernel.cpp ファイル：
sycl::cpu_selector device_selector;
queue deviceQueue(device_selector);
deviceQueue.submit([&](handler &cgh) {// CPU カーネル関数});

サンプルの fpga_kernel.cpp ファイル：#ifdef FPGA_EMULATORINTEL::fpga_emulator_selector device_selector;#else
INTEL::fpga_selector device_selector;#endifqueue deviceQueue(device_selector);
deviceQueue.submit([&](handler &cgh) {// FPGA カーネル関数});

FPGA ハードウェア・コンパイル
FPGA ハードウェア・ターゲット向けにコンパイルするには、-DFPGA_EMULATOR オプションの代わりに -Xshardware オプションを指定します。
dpcpp -fsycl -fsycl-targets=spir64-unknown-unknown-sycldevice \jit_kernel.cpp -c -o jit_kernel.o
dpcpp -fsycl -fsycl-targets=spir64_fpga-unknown-unknown-sycldevice \fpga_kernel.cpp -c -o fpga_kernel.o -Xshardware
dpcpp -fintelfpga main.cpp jit_kernel.o fpga_kernel.o -Xshardware

FPGA-CPU インタラクション
FPGA の設計におけるパフォーマンスに影響する主な要因の 1 つは、FPGA で実行されるカーネルが
CPU ホストとどのような相互作用を持つかです。

ホストとカーネルのインタラクション
FPGA デバイスは PCIe* を介してホスト（CPU）と通信します。

75

4

これは、FPGA をターゲットにする SYCL* プログラムのパフォーマンスに影響する重要な要素です。さらに、特定のDPC++ プログラムを初めて実行する場合、FPGA をハードウェア・ビットストリームで構成する必要があり、これには数時間かかります。

データ転送
通常、FPGA ボードには、独自のプライベート DDR（英語）メモリーが搭載されます。CPU は、カーネルが
FPGA ローカル DDR メモリーにアクセスして使用するすべてのデータを一括転送するか、ダイナミック・
メモリー・アクセス（DMA）を行う必要があります。カーネルは操作を完了すると、結果を DMA 経由でCPU に転送する必要があります。転送速度は PCIe* リンクと DMA の効率によって制限されます。例えば、
インテル® プログラマブル・アクセラレーション・カード（インテル® Arria® 10 GX FPGA 搭載版）には、PCIe* Gen 3 x 8 リンクがあり、転送は通常 6 から 7 GB/秒に制限されます。
データ転送時間は次のように管理されます。
•

DPC++ では、バッファーに読み取り専用または書き込み専用のタグを付けることができ、不要な転送を排除できます。

•

同時操作数を最大化することでシステム全体の効率を改善できます。PCIe* は逆方向への同時転送をサポートし、PCIe* 転送はカーネルの実行に干渉しないため、ダブル・バッファリングなどの手法を利用できます。これらの手法の詳細については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』の「カーネル呼び出しキューを利用するダブル・バッファリング・ホスト」（英語）と、「double_buffering」（英語）チュートリアルを参照してください。

•

制限付き USM をサポートするボードバリアントにシステムメモリーを事前に固定することで、データ転送スループットを向上させます。詳細については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』の「事前固定（プリピニング）」（英語）を参照してください。

コンフィギュレーション時間
コンフィギュレーションと呼ばれる手順で、FPGA デバイスのハードウェア・ビットストリームをプログラムします。コンフィギュレーションは、FPGA デバイスとの通信に数秒間を要する操作です。SYCL* ランタ
イムはコンフィギュレーションを自動的に管理します。ランタイムは、コンフィギュレーションが行われる
タイミングを決定します。例えば、カーネルが最初に起動されたときにコンフィギュレーションがトリガーされることがありますが、ビットストリームは変更されていないため、同じカーネルを以降に起動す76

oneAPI プログラムのコンパイルと実行る際にはコンフィギュレーションがトリガーされないことがあります。したがって、開発中は、FPGA のコ
ンフィギュレーション後にカーソルの実行時間を計測することを推奨します。例えば、カーネルの実行時間を計測する前に、カーネルをウォームアップ実行します。ウォームアップ・コードは、実際のコードでは削除します。

複数のカーネル呼び出し
SYCL* プログラムが同じカーネルを SYCL* キューに複数回送信する場合（ループ内での single_task
呼び出しなど）、1 つのカーネル呼び出しのみがアクティブになります。それ以降のカーネル呼び出しでは、前のカーネルが実行を完了するのを待機します。

関連情報インテル® oneAPI DPC++ FPGA 最適化ガイド（英語）インテル® プログラマブル・アクセラレーション・カード（インテル Arria® 10 GX FPGA 搭載版）
インテル® FPGA PAC D5005（インテル® FPGA プログラマブル・アクセラレーション・カード D5005）

FPGA パフォーマンスの最適化
前述の FPGA 手順では、FPGA 向けの DPC++ コンパイルの基本を説明しましたが、設計時にパフォー
マンス向上について習得すべきことはまだたくさんあります。インテル® oneAPI DPC++/C++ コンパイ
ラーは、改善すべき領域を特定するツール、設計およびコンパイラーの動作を制御するさまざまなオプ
ション、属性、そして拡張機能を提供します。これらの情報はすべて、『インテル® oneAPI DPC++ FPGA
最適化ガイド』（英語）に記載されています。設計時の最適化に関する手法を理解したい開発者はこのガイドを参照してください。

FPGA 向けの静的ライブラリーを使用する
静的ライブラリーは複数の関数を含む単一のファイルです。静的ライブラリー・ファイルは、 SYCL*、
OpenCL*、高位合成（HLS）ソース、またはレジスター転送レベル（RTL）を使用して作成できます。次に、このライブラリー・ファイルをインクルードして、SYCL* カーネル内で関数を使用します。
HLS でライブラリー関数を開発する詳細については、『インテル® HLS コンパイラー・リファレンス・マ
ニュアル』（英語）を参照してください。

77

4

サードパーティーのライブラリーを使用したり、独自のライブラリーを作成することもできます。静的ライ
ブラリーを使用するのに、ハードウェアの設計やライブラリー・プリミティブの実装に関する深い知識は必要ありません。
SYCL* で使用するライブラリーを生成するには、次のファイルを用意する必要があります。
SYCL* で使用するライブラリーを作成
ファイルまたはコンポーネント

説明

RTL モジュール
RTL ソースファイル

RTL コンポーネントを定義する、Verilog、System Verilog、または VHDL ファ
イル。
インテル® Quartus® Prime IP ファイル（.qip）、Synopsys Design
Constraints ファイル（.sdc）、Tcl スクリプトファイル（.tcl）などの追加ファ
イルは許可されません。

eXtensible マークアップ言語

RTL コンポーネントのプロパティーを記述します。インテル® oneAPI

ファイル（.xml）

DPC++/C++ コンパイラーは、これらのプロパティーを使用して RTL コンポー
ネントを SYCL* パイプラインに統合します。

ヘッダーファイル（.hpp）

有効な SYCL* カーネル言語を含み、RTL コンポーネントによって実装される関数のシグネチャーを宣言するヘッダーファイルです。

エミュレーション・モデル・

エミュレーションでのみ使用される RTL コンポーネントの C または C++ モ

ファイル（OpenCL* またはデルを提供します。ハードウェア向けの完全なコンパイルには RTL ソースファ

HLS ベース）

イルを使用します。

制限事項：SYCL* ではエミュレーター・モデルを記述できません。

78

oneAPI プログラムのコンパイルと実行SYCL* 関数SYCL* ソースファイル（.cpp）

SYCL* 関数の定義を含みます。これらの関数は、エミュレーションおよび完全なハードウェア・コンパイルで使用されます。

ヘッダーファイル（.hpp）

SYCL* 構文で SYCL* から呼び出される関数を記述するヘッダーファイル。

OpenCL* 関数
OpenCL* ソースファイル（.cl）

OpenCL* 関数の定義を含みます。これらの関数は、エミュレーションおよび完
全なハードウェア・コンパイルで使用されます。

ヘッダーファイル（.hpp）

SYCL* 構文で SYCL* から呼び出される関数を記述するヘッダーファイル。

HLS 関数HLS ソースファイル（.cpp）

HLS 関数の定義を含みます。これらの関数は、エミュレーションおよび完全なハードウェア・コンパイルで使用されます。

ヘッダーファイル（.hpp）

SYCL* 構文で SYCL* から呼び出される関数を記述するヘッダーファイル。

注：RTL とほかのライブラリー関数で使用されるヘッダーファイルに違いはありません。1 つのライブラ
リーには、サポートされる任意のソースを含めることができます。各種ソース（SYCL*、OpenCL*、HLS ま
たは RTL）から、次の製品を対象とするライブラリーを作成できます。
 インテル® oneAPI DPC++/C++ コンパイラー
 インテル® FPGA SDK for OpenCL* オフライン・コンパイラー
 インテル® HLS コンパイラー
ライブラリー・ファイルの形式は、ソースコードをコンパイルするオペレーティング・システムと同じ形式を使用し、ライブラリー情報を伝達する追加のセクションを持ちます。
•

Linux* プラットフォームでは、ライブラリーは .a アーカイブファイルで .o オブジェクト・ファイルを
含みます。

•

Windows* プラットフォームでは、ライブラリーは .lib アーカイブファイルで .obj オブジェクト・
ファイルを含みます。

ライブラリー内部の関数のハードウェアの設計や実装の詳細を理解していなくても、カーネルからライブ
ラリーの関数を呼び出すことができます。カーネルをコンパイルする際にライブラリーを dpcpp コマン
ドラインに追加します。

79

4
ライブラリーの作成は 2 段階のプロセスからなります。
1.

2.

各オブジェクト・ファイルは、fpga_crossgen コマンドにより入力ソースファイルから作成されます。
•

オブジェクト・ファイルは、コードの CPU 形式と FPGA 形式の両方からなるソースコードの中間
表現です。

•

オブジェクト・ファイルは、同一のインテル® HLS 設計製品でのみ使用することが想定されています。複数の HLS 設計製品を使用する場合、対象の製品ごとに個別のオブジェクトを作成する必要があります。

オブジェクト・ファイルは fpga_libtool コマンドでライブラリー・ファイルに結合します。すべてのオブジェクトが同一の HLS 設計製品を対象とする場合、各種タイプのソースコードから生成されたオブジェクトをライブラリーに統合できます。
ライブラリーにはツールチェーンのバージョン番号が自動的に割り当てられるため、同じバージョンの HLS 設計製品でのみ利用します。

ソースコードからライブラリー・オブジェクトを作成
ソースコードのオブジェクト・ファイルからライブラリーを作成することができます。SYCL* ベースのオブジェクト・ファイルには、ホストで使用する CPU を取得するハードウェア実行とカーネルのエミュレー
ションで使用する CPU コードが含まれています。
ライブラリーには複数のオブジェクト・ファイルを含めることができます。同じソースコードから、異なるインテル® HLS 設計ツールで使用するオブジェクト・ファイルを作成できます。対象とするインテル® HLS
設計ツールによっては、ツール固有のデータ型や構造をサポートするためソースコードの調整が必要になることがあります。

80

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

製品

説明

インテル® oneAPI

コードを使用してコンパイラー・ライブラリーのオブジェクトを作成する場合、

DPC++/C++ コンパイラー

SYCL* および OpenCL* ソースコードで新たに行うべき作業はありません。

インテル® FPGA SDK for
OpenCL* オフライン・コンパ
イラーインテル® HLS コンパイラー

SYCL* は、C++ でネイティブサポートされていない言語構造をサポートしま
す。それらの言語構造をサポートするため、コンポーネントの変更が必要な場
合があります。ライブラリー関数の呼び出しには、SYCL* データ型のパラメー
ターを使用することを推奨します。

制限事項：SYCL* ライブラリー・オブジェクトで使用するコンポーネン
トでは、タスクのシステムを利用することはできません。

ソースコードからオブジェクト・ファイルを作成
fpga_crossgen コマンドを使用して、ソースコードからライブラリー・オブジェクトを作成します。ソースコードから作成されたオブジェクトには、オブジェクト内の関数のエミュレートとオブジェクト関数のハードウェア合成に必要な情報が含まれています。
注：fpga_crossgen コマンドを使用する SYCL* 向けの HLS ライブラリーのインポートは、Linux* でのみサポートされています。
fpga_crossgen コマンドは、1 つの入力ソースファイルから 1 つのオブジェクト・ファイルを作成します。作成されたオブジェクトは、同じインテル® HLS 設計ツールを対象とするライブラリーでのみ利用できます。オブジェクトもまたバージョン管理されます。それぞれのオブジェクトには、コンパイラーのバー
ジョン番号が割り当てられ、同一バージョンのインテル® HLS 設定ツールでのみ使用されます。
次のコマンドを使用してライブラリー・オブジェクトを作成します。
fpga_crossgen <source_file> [--source (sycl|ocl|hls)]--target (sycl|ocl|hls) [-o <object_file>]81

4
次の表でパラメーターについて説明します。
パラメーター

説明<source_file>

SYCL*、OpenCL*、HLS、または RTL ソースファイルを使用できます。

--source

オプション。sycl、hls、および ocl オプションをサポートします。
•

ソースファイルの拡張子が .cpp である場合、デフォルトのオプションは hlsです。

•

ソースファイルの拡張子が .cl である場合、デフォルトのオプションは ocl です。

•

RTL ソースファイルの場合、--source オプションはエミュレーション・モデル
を参照します。

--targetライブラリー用のインテル® HLS 設計ツール（sycl、ocl、または hls）を対象とします。オブジェクトは、fpga_libtool を使用して SYCL* ライブラリー・アーカイ
ブに統合されます。

-oオプション。このオプションは、オブジェクト・ファイル名を指定するのに役立ちます。このオプションを指定しないと、オブジェクト・ファイル名はソースコードのファ
イル名と同じ名前になりますが、拡張子は .o や .obj になります。

コマンドの例を示します。
fpga_crossgen lib_hls.cpp --source hls --target sycl -o lib_hls.o
fpga_crossgen lib_ocl.cl --source ocl --target sycl -o lib_ocl.o
fpga_crossgen lib_rtl_spec.xml --emulation_model lib_rtl_model.cpp--target sycl -o lib_rtl.o
fpga_crossgen lib_sycl.cpp --source sycl --target sycl -o lib_sycl.o

オブジェクト・ファイルをライブラリー・ファイルにパッケージ化
ほかの開発者がライブラリーをプロジェクトに組込んで、ライブラリー内のオブジェクトに含まれる関数を呼び出すことができるように、オブジェクト・ファイルをライブラリー・ファイルに集約します。オブジェク
ト・ファイルをライブラリーとしてパッケージ化するには、fpga_libtool コマンドを使用します。
オブジェクト・ファイルをライブラリーにパッケージ化する前に、ライブラリーに含めるすべてのオブジェ
クト・ファイルのパス情報があることを確認してください。
パッケージ含めるすべてのオブジェクトは、同じバージョンでなければなりません。fpga_libtool コマ
ンドは、オ ペレーティング・システム 固有のアーカイブファイル のライブラリー （Linux* では .a、

82

oneAPI プログラムのコンパイルと実行
Windows* では .lib）を作成します。使用するオペレーティング・システムとは異なるオペレーティング・
システムで実行されているインテル® HLS 設計製品と一緒に使用することはできません。
次のコマンドを使用してライブラリー・ファイルを作成します。
fpga_libtool file1 file2 ... fileN --target (sycl|ocl|hls) --create<library_name>

コマンド・パラメーターは次のように定義されます。
パラメーター説明file1 file2 ... fileN

ライブラリーに含めるオブジェクト・ファイルを指定できます。

--target (sycl|ocl|hls)

このライブラリーはカーネル開発を対象とします。sycl オプションでは、--target は、インテル® oneAPI DPC++/C++ コンパイラーで使用するライブラリーを準備します。

--create <library_name>

ライブラリー・アーカイブ・ファイルの名前を指定できます。Linux* プラット
フォーム向けのライブラリーでは、ファイル拡張子 .a を指定します。

コマンド例：
fpga_libtool lib_hls.o lib_ocl.o lib_rtl.o lib_sycl.o --target sycl --create
lib.a

このコマンドは、HLS、OpenCL*、RTL、および SYCL* ソースコードから作成されたオブジェクトを
lib.a という SYCL* ライブラリーにパッケージ化します。
ヒ ン ト ： 詳 細 に つ い て は 、 「 Linux* 上 の イ ン テ ル ® oneAPI サ ン プ ル ブ ラ ウ ザ ー 」 （ 英 語 ） ま た は「Windows* 上のインテル® oneAPI サンプルブラウザー」（英語）の FPGA チュートリアル・サンプルにある「ライブラリーを使用する」を参照してください。

静的ライブラリーの使用
次のコマンドに示すように、コンパイルコマンドにはソースファイルとともに静的ライブラリーを指定することができます。
dpcpp -fintelfpga main.cpp lib.a83

4
RTL サポートの制限と制約
SYCL* カーネル内で使用する RTL モジュールを作成する場合、RTL モジュールが次の制限下で動作す
ることを確認する必要があります。
•

RTL モジュールは、単一入力のインテル® Avalon® ストリーミング・インターフェイスを使用しなければなりません。つまり、準備ができた有効なロジックのペアで、すべての入力をコントロールする必要があります。必要とするインテル® Avalon® ストリーミング・インターフェイス・ポートを提供するオプ
ションもありますが、RTL モジュールをストールなしとして宣言する必要があります。この場合、インテル® oneAPI DPC++/C++ コンパイラーがモジュールのラッパーを作成するため、特定のストー
ル動作を実装する必要はありません。詳細については、「RTL モジュールのオブジェクト・マニフェス
ト・ファイル構文」（英語）を参照してください。
注：RTL モジュールに内部状態がある場合、ivalid 信号を適切に処理する必要があります。詳細は、「ストールなしの RTL」（英語）を参照してください。

•

RTL モジュールは、カーネルクロック周波数に関係なく適切に動作しなければなりません。

•

RTL モジュールは、外部 I/O 信号に接続できません。すべての入力と出力信号は SYCL* カーネルに由来する必要があります。

•

RTL モジュールには、クロックポート、リセットポート、およびインテル® Avalon® ストリーミング・イ
ンターフェイスの入力ポートと出力ポート（ivalid、ovalid、iready、oready）が必要です。ここで示すようにポートに名前を付けます。

•

外部メモリーと通信を行う RTL モジュールには、対応するカスタム・プラットフォーム・パラメーターと一致するインテル® Avalon® メモリー・マップド・インターフェイス・ポートのパラメーターが必要です。インテル® oneAPI DPC++/C++ コンパイラーは、幅やバーストの適用を行うことはありません。

•

外部メモリーと通信を行う RTL モジュールは、次のように動作しなければなりません。
•

バースト境界を越えてバーストすることはできません。

•

クロックサイクルごとに要求を行い、アービトレーション・ロジックを占有してハードウェアをストールさせることはできません。RTL モジュールは、ほかのロードユニットやストアユニットが操作を実行できるよう、要求を定期的にポーズする必要があります。

•

RTL モジュールは、スタンドアロンの SYCL* カーネルとしては動作できません。RTL モジュールはヘルパー関数としてのみ使用でき、カーネルのコンパイル中に SYCL* カーネルと統合できます。

•

RTL モジュールのインスタンス化に対応するすべての関数呼び出しは、ほかのインスタンスから完全に独立しており、ハードウェアの共有もありません。

•

カーネルコードを SYCL* ライブラリー・ファイルに組込んではなりません。カーネルコードを SYCL*
ライブラリー・ファイルに組込むと、オフライン・コンパイラーはエラーメッセージを出力します。ヘルパー関数はライブラリー・ファイルに組込んでも問題ありません。

84

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

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
ファイルのフラットリストを作成する必要があります。
ヒント：単独では正しく動作するにもかかわらず、SYCL* カーネルの一部として適切に機能しない
RTL モジュールをデバッグするのは非常に困難です。<RTL モジュール記述ファイル名>.xml ファイ
ルの「ATTRIBUTES エレメント」（英語）下にあるすべてのパラメーターを確認してください。

•

すべてのコンパイラー領域推測ツールは、RTL モジュール領域が 0 であると想定します。現在、コンパイラーは RTL モジュール領域モデルを指定する機能をサポートしていません。

IDE での FPGA ワークフロー
インテル® oneAPI ツールは、サードパーティー統合開発環境（IDE）と統合して、Linux*（Eclipse*）およびWindows*（Visual Studio*）でソフトウェア開発にシームレスな GUI 環境を提供します。詳細は、「サードパーティー IDE でのインテル® oneAPI DPC++ FPGA ワークフロー」（英語）を参照してください。
Linux* で Visual Studio* Code を使用した FPGA の開発については、「インテル® oneAPI DPC++FPGA 開発（Linux* で Visual Studio* Code 向けのサンプルブラウザーを使用）」（英語）を参照してください。

85

API ベースのプログラミング

5

最適化されたアプリケーション向けの特殊 API を提供することで、プログラミング・プロセスを簡素化す
るインテル® oneAPI ツールキットのライブラリーを利用できます。この章では、サンプルコードを含むライブラリーの基本的な情報と、特定の利用ケースでどのライブラリーが最も有効であるか判断するのに役立つ情報を提供します。利用可能な API など、それぞれのライブラリーの詳細は、ライブラリーのドキュメントをご覧ください。

インテル® oneAPI ライブラリーの概要
インテル® oneAPI ツールキットには、次のライブラリーが含まれます。
ライブラリー

使用法

インテル® oneAPI DPC++ ライブラリー

ハイパフォーマンスの並列アプリケーションで使用します。

インテル® oneAPI マス・カーネル・ライブ

高度に最適化および並列化された数学ルーチンをアプリケーショ

ラリー

ンで利用できます。

インテル® oneAPI スレッディング・ビル

マルチコア CPU でのインテル® TBB ベースの並列処理と、アプリ

ディング・ブロック

ケーションでの DPC++ デバイス高速並列処理を組み合わせます。

インテル® oneAPI データ・アナリティク

ビッグデータ解析アプリケーションと分散計算を高速化します。

ス・ライブラリー
インテル® oneAPI コレクティブ・コミュ

ディープラーニングとマシンラーニングのワークロードを処理す

ニケーション・ライブラリー

るアプリケーションで使用します。

インテル® oneAPI ディープ・ニューラル・

インテル® アーキテクチャーのプロセッサーおよびインテル® プロ

ネットワーク・ライブラリー

セッサー・グラフィックス向けに最適化された、ニューラル・ネット
ワークを使用するディープラーニング・アプリケーションで使用します。

インテル® oneAPI ビデオ・プロセシン
グ・ライブラリー86

アプリケーションのビデオ処理を高速化します。

API ベースのプログラミング

インテル® oneAPI DPC++ ライブラリー（インテル® oneDPL)
インテル® oneAPI DPC++ ライブラリー（インテル® oneDPL）は、インテル® oneAPI DPC++.C++ コン
パイラーと連携して生産性の高い API を提供します。これらの API を使用して、ハイパフォーマンスな並列アプリケーション向けに、デバイス全体でデータ並列 C++（DPC++）プログラミングの労力を最小限に抑えることができます。
インテル® oneDPL は次のコンポーネントで構成されます。
••

Parallel STL•

Parallel STL の使用手順•

マクロライブラリー・クラスと関数の追加セット（このドキュメントでは拡張 API と呼びます）•

並列アルゴリズム•

イテレーター•

関数オブジェクト・クラス•

範囲ベースの API•

テスト済みの標準 C++ API•

乱数ジェネレーター

関連情報
インテル® oneAPI DPC++ ライブラリー・ガイド（英語）インテル® oneDPL ライブラリーの使い方
インテル® oneDPL を使用するには、インテル® oneAPI ベース・ツールキット（英語）をインストールします。
Patallel STL と拡張 API を使用するには、必要なヘッダーファイルをソースコードでインクルードします。
すべてのインテル® oneDPL ヘッダーファイルは oneapi/dpl ディレクトリーにあります。それらをインクルードするには、#include <oneapi/dpl/…> を使用します。インテル® oneDPL には、大部分のクラスと関数対する名前空間 oneapi::dpl があります。テスト済みの C++ 標準 API を使用するには、対応する C++ ヘッダーファイルをインクルードし、std 名前空間を使用する必要があります。

87

5インテル® oneDPL サンプルコード
イ ン テ ル ® oneDPL の サ ン プ ル コ ー ド は 、 https://github.com/oneapi-src/oneAPI-samples/tree/
master/Libraries/oneDPL（英語）から入手できます。それぞれのサンプルには、ビルド手順が説明された Readme が含まれています。

インテル® oneAPI マス・カーネル・ライブラリー（インテル® oneMKL)
インテル® oneAPI マス・カーネル・ライブラリー（インテル® oneMKL）は、最大限のパフォーマンスを必要とするアプリケーション向けに最適化され、広範囲に並列化されたルーチンの数学計算ライブラリーです。インテル® oneMKL には、C/Fortran プログラミング言語インターフェイスを備えた CPU アーキテ
クチャー向けのインテル® マス・カーネル・ライブラリー（インテル® MKL）のハイパフォーマンスな最適化が含まれており、各種 CPU アーキテクチャーとインテル® グラフィックス・テクノロジーでパフォーマンス
を高めるデータ並列 C++（DPC++）プログラミング言語インターフェイスが追加されています。CPU と
GPU アーキテクチャー向けの最適化を備えた新しい DPC++ インターフェイスには、次のような計算向けの機能が追加されています。
•

BLAS と LAPACK 密線形代数ルーチン•

スパース BLAS スパース線形代数ルーチン•

乱数生成器（RNG）•

ベクトルの数学演算用に最適化されたベクトル数学（VM）ルーチン•

高速フーリエ変換（FFT）

関連情報
データ並列 C++ 対応インテル® oneAPI マス・カーネル・ライブラリー導入ガイド（英語）データ並列 C++ 対応インテル® oneAPI マス・カーネル・ライブラリー・デベロッパー・リファレンス（英語）インテル® oneAPI マス・カーネル・ライブラリー（Linux* 版）デベロッパー・ガイド（英語）インテル® oneAPI マス・カーネル・ライブラリー（Windows* 版）デベロッパー・ガイド（英語）インテル® oneMKL の使い方
DPC++ プログラミング言語インターフェイスを使用する場合、考慮すべきことがあります。
•

88

インテル® oneMKL は、インテル® oneAPI DPC++/C++ コンパイラーおよびインテル® oneAPI
DPC++ ライブラリーに依存しています。アプリケーションは、インテル® oneAPI DPC++/C++ コンパ
イラーでビルドされ、 DPC++ ヘッダーを利用しており、 DPC++ リンカーを使用してインテ ル®
oneMKL とリンクされている必要があります。

API ベースのプログラミング•

インテル® oneMKL の DPC++ インターフェイスは、入力データ（ベクトル、行列など）にデバイスのアクセスが可能な統合共有メモリー（USM）ポインターを使用します。

•

インテル® oneMKL の一部の DPC++ インターフェイスは、入力データ向けのデバイスへのアクセスが可能な USM（Unified Shared Memory）ポインターのほかに、sycl::buffer オブジェクトのア
クセスもサポートしています。

•

インテル® oneMKL の DPC++ インターフェイスは、浮動小数点型に基づいてオーバーロードされます。標準ライブラリー・タイプ std::complex<float>、std::complex<double> を使用する、単精度実数引数（float）、倍精度実数引数（double）、半精度実数引数（half）、および異なる精度の複素数引数を受け入れる汎用行列乗算 API があります。

•

インテル® oneMKL の 2 レベルの名前空間構造が DPC++ インターフェイスに追加されます。
名前空間

説明

oneapi::mkl

oneMKL の各種ドメイン間の共通要素が含まれます。

oneapi::mkl::blas

密ベクトル-ベクトル、行列-ベクトル、および行列-行列の低レベル操作が含まれます。

oneapi::mkl::lapack

行列因数分解や固有値ソルバーなど高レベルの密行列演算が含まれます。

oneapi::mkl::rng

各種確率密度関数の乱数生成器が含まれます。

oneapi::mkl::stats

単精度および倍精度の多次元データセットの基本的な統計予測値が含まれます。

oneapi::mkl::vm

ベクトル数学ルーチンが含まれます。

oneapi::mkl::dft

高速フーリエ変換操作が含まれます。

oneapi::mkl::sparse

スパース行列ベクトル乗算、スパース三角ソルバーなどのスパース行列演算が含まれます。

インテル® oneMKL サンプルコード
DPC++ インターフェイスと oneMKL の一般的なワークフローを示すため、次のサンプルコードは、GPUデバイスで倍精度の行列 - 行列乗算を行います。
注：次のコード例では、行中のコメントで示されるように、コンパイルと実行に追加のコードが必要です。

89

5// 標準 SYCL* ヘッダー
#include <CL/sycl.hpp>// STL クラス#include <exception>#include <iostream>// インテル® oneAPI マス・カーネル・ライブラリーの DPC++ API の宣言#include "oneapi/mkl_sycl.hpp"
int main(int argc, char *argv[]) {//// ユーザーは、m、n、k、ldA、ldB、ldC の設定と A、B、C 行列のデータを取得//// A、B、および C は、data() と size() メンバー関数を含む std::vector などの// コンテナーに格納します//// 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;}}};// 例外ハンドラーがアタッチされた 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 mkl::blas::gemm を実行キューに追加し、同期例外をキャッチ
try {using oneapi::mkl::blas::gemm;
using oneapi::mkl::transpose;90

API ベースのプログラミング
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;}// 続行する前に、キャッチされた非同期例外を処理
my_queue.wait_and_throw();//// 後処理の結果//// 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;}

倍精度値行列 A（サイズ m x k）、B（サイズ k x n）、C（サイズ m x n）は、ホストマシンの配列（次元 ldA、
ldB、ldC）に格納されると想定します。スカラー倍精度 alpha と beta を指定し、行列-行列乗算（mkl::blas::gemm）を計算します。
C = alpha * A * B + beta * C
標準 SYCL* ヘッダーと対象の mkl::blas::gemm API 宣言を含むインテル® oneMKL DPC++ 固有
ヘッダーをインクルードします。
// 標準 SYCL* ヘッダー
#include <CL/sycl.hpp>// STL クラス#include <exception>#include <iostream>// インテル® oneAPI マス・カーネル・ライブラリーの DPC++ API の宣言#include "oneapi/mkl_sycl.hpp"

次に、通常のようにホストマシンで行列データをロードまたはインスタンス化し、GPU デバイスを作成して非同期例外ハンドラーを作成し、最後に例外ハンドラーでデバイスキューを作成します。ホストで発生する例外は、標準 C++ 例外メカニズムでキャッチできます。ただし、デバイスで発生する例外は非同期エラーとして見なされ、例外リストに保存されて、ユーザー定義の例外ハンドラーによって処理されます。

91

5// 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;}}};

これで、行列データが DPC++ バッファーにロードされ、ターゲットのデバイスにオフロードして、完了後にホストに戻すことができます。最後に、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 mkl::blas::gemm を実行キューに追加し、同期例外をキャッチ
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;}

92API ベースのプログラミング
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 がスコープ外になるまでアクセサーを介してのみ利用できます。

インテル® oneAPI スレッディング・ビルディング・ブロック（インテル® oneTBB)
インテル® oneAPI スレッディング・ビルディング・ブロック（インテル® oneTBB）は、ホスト上でタスクベースの、共有メモリー並列プログラミングを可能にする、広く使用されている C++ ライブラリーです。
このライブラリーは、SYCL* および ISO C++ で利用可能な機能のほかに、CPU 上での並列プログラミ
ング向けに次のような機能を提供します。
•

汎用並列アルゴリズム•

コンカレント・コンテナー•

スケラーブル・メモリー・アロケーター•

ワークスチール・タスク・スケジューラー•

低レベル同期プリミティブ

インテル® oneTBB はコンパイラーに依存せず、さまざまなプロセッサーとオペレーティング・システムで利用できます。CPU 向けのマルチスレッド並列処理を実現するため、ほかのインテル® oneAPI ライブラ
リー（インテル® oneAPI マス・カーネル・ライブラリー、インテル® oneAPI ディープ・ニューラル・ネット
ワーク・ライブラリーなど）で使用されています。

関連情報インテル® oneAPI スレッディング・ビルディング・ブロック導入ガイド（英語）935インテル® oneAPI スレッディング・ビルディング・ブロック・ドキュメント（英語）インテル® oneTBB の使い方
インテル® oneTBB は、ほかの C++ コンパイラーでもインテル® oneAPI DPC++ コンパイラーと同じ方
法で使用できます。詳細は、「oneTBB ドキュメント」（英語）をご覧ください。
現在、インテル® oneTBB はアクセラレーターを直接サポートしません。ただし、DPC++ 言語とほかのインテル® oneAPI ライブラリーを組み合わせて、利用可能なすべてのハードウェア・リソースを効率良く使用するプログラムを構築できます。

インテル® oneTBB サンプルコード•

2 つの基本的なインテル® oneTBB サンプルコードが、https://github.com/oneapi-src/oneAPIsamples/tree/master/Libraries/oneTBB（英語）から入手できます。これらのサンプルコードは、
CPU と GPU 向けに記述されています。

•

tbb-async-sycl は、インテル® oneTBB フローグラフ非同期ノードと機能ノードを使用し、計算カーネルを分割して CPU と GPU 間で実行する方法を示します。フローグラフ非同期ノードは、
SYCL* を使用して機能ノードが計算の CPU 部分を実行する間に、GPU で実装された計算を実行します。

•

tbb-task-sycl は、2 つのインテル® oneTBB タスクが同じ計算カーネルを実行する方法を示します。1 つのタスクが SYCL* コードを実行し、もう一方はインテル® oneTBB コードを実行します。

インテル® oneAPI データ・アナリティクス・ライブラリー（インテル® oneDAL)
インテル® oneAPI データ・アナリティクス・ライブラリー（インテル® oneDAL）は、データ解析のすべてのステージ（前処理、変換、解析、モデリング、検証、意思決定）で、バッチ、オンライン、および分散処理モードで計算を実行する、高度に最適化されたアルゴリズムのビルディング・ブロックを提供することで、ビッグデータ解析の高速化を支援するライブラリーです。
アルゴリズムの計算だけでなくデータの取り込みを最適化し、スループットとスケーラビリティーを向上します。C++ および Java* API に加えて、Spark* や Hadoop* などの一般的なデータソースへのコネク
ターが含まれます。インテル® oneDAL の Python* ラッパーは、インテル® ディストリビューション for
Python*（英語）に含まれます。
さらに従来の機能に加えて、インテル® oneDAL は従来の C++ インターフェイスに DPC++ API 拡張機能を提供し、一部のアルゴリズムで GPU も利用できるようにします。

94

API ベースのプログラミング
このライブラリーは、分散計算では特に有用です。通信レイヤーから独立した分散アルゴリズムのビル
ディング・ブロックの完全なセットを提供します。これにより、ユーザーは利用したい通信基盤を使って、高速でスケーラブルな分散アプリケーションを構築できます。
一般的な情報は、oneDAL GitHub* ページ（英語）でご覧いただけます。完全な機能とドキュメントについては、インテル® oneAPI データ・アナリティクス・ライブラリーの公式ウェブサイト（英語）で入手できます。コミュニティー・サポート付きの無料のオープンソース・バージョンと、プレミアサポート付きの有料バージョンを利用できます。

関連情報インテル® oneAPI データ・アナリティクス・ライブラリー導入ガイド（英語）インテル® oneAPI データ・アナリティクス・ライブラリー・ドキュメント（英語）インテル® oneDAL の使い方
アプリケーションをビルドしてインテル® oneDAL とリンクするのに必要な依存関係に関する情報は、「インテル® oneAPI データ・アナリティクス・ライブラリーのシステム要件」（英語）を参照してください。
インテル® oneDAL ベースのアプリケーションは、適切なデバイスセレクターを選択することで、CPU ま
たは GPU でアルゴリズムをシームレスに実行できます。新機能により次のことが可能になります。
•

数値テーブルから DPC++ バッファーを抽出してカスタムカーネルに渡す。

•

DPC++ バッファーから数値テーブルを作成する。

アルゴリズムは、DPC++ バッファーを再利用して GPU データを保持し、GPU と CPU 間でデータを繰り返しコピーする過負荷を排除するように最適化されています。

インテル® oneDAL サンプルコード
インテル® oneDAL のサンプルコードは GitHub* リポジトリーから入手できます。次のサンプルコード
は、インテル® oneDAL 固有の機能を示す分かりやすい例です。
https://github.com/oneapi-src/oneDAL/tree/master/examples/oneapi/dpc/source/svm（英語）955インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー（インテル® oneCCL)
インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー（インテル® oneCCL）は、ディープラー
ニング（DL）、およびマシンラーニング（ML）ワークロード向けのスケーラブルでハイパフォーマンスな通信ライブラリーです。インテル® Machine Learning Scaling Library に由来するアイデアを発展させて、新しい機能と利用ケースを実現するため設計と API を拡張しています。
インテル® oneCCL は次の機能を備えています。
•

低レベルの通信ミドルウェア上に構築された MPI と libfabrics。

•

通信パフォーマンスに対する計算の生産的なトレードオフを可能にすることで、通信パターンのス
ケーラビリティーを促進する最適化。

•

優先順位、永続的な操作、アウトオブオーダー実行など、一連の DL 固有の最適化。

•

CPU や GPU など各種ハードウェア・ターゲットで実行する DPC++ API。

•

さまざまなインターコネクトで動作：インテル® Omni-Path アーキテクチャー（インテル® OPA）、
InfiniBand*、イーサネット

関連情報
インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー導入ガイド（英語）インテル® oneAPI コレクティブ・コミュニケーション・ライブラリー・ドキュメント（英語）インテル® oneCCL の使い方
MPI やインテル® oneAPI DPC++/C++ コンパイラーなど、ハードウェアとソフトウェアの依存関係に関する完全なリストについては、「インテル® oneAPI コレクティブ・コミュニケーション・ライブラリーのシス
テム要件」（英語）を参照してください。
SYCL* 対応 API は、インテル® oneCCL のオプション機能です。インテル® oneCCL ストリーム・オブジェ
クトを作成する場合、CPU と SYCL* バックエンドのどちらかを選択できます。
•

CPU バックエンド：最初の引数に ccl_stream_host を指定します。

•

SYCL* バックエンド：デバイスタイプに応じて ccl_stream_cpu または ccl_stream_gpu を指
定します。

96

API ベースのプログラミング•

SYCL* ストリームで動作する集合操作：•

C API では、インテル® oneCCL は通信バッファーが void* にキャストされた sycl::buffer
オブジェクトであると想定します。

•

C++ API では、インテル® oneCCL は通信バッファーが参照渡しされることを想定します。

使用法に関する詳しい説明は、https://oneapi-src.github.io/oneCCL/（英語）から入手できます。

インテル® oneCCL サンプルコード
イ ン テ ル ® oneCCL の サ ン プ ル コ ー ド は 、 https://github.com/oneapi-src/oneAPI-samples/tree/
master/Libraries/oneCCL（英語）から入手できます。コードをビルドして実行する手順を含む入門サン
プルは、同じ GitHub* リポジトリーから入手できます。

インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー（インテル® oneDNN)
インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー（インテル® oneDNN）は、ディープ
ラーニング・アプリケーション向けのオープンソースのパフォーマンス・ライブラリーです。このライブラ
リーには、インテル® アーキテクチャー・ベースのプロセッサーおよびインテル® プロセッサー・グラフィッ
クス向けに最適化さ れたニューラル・ネットワークの基本的な構成要素が含まれます。 インテ ル®
oneDNN は、インテル® アーキテクチャー・ベースのプロセッサーとインテル® プロセッサー・グラフィック
ス上でアプリケーションのパフォーマンス向上に注目するディープラーニング・アプリケーションおよび
フレームワーク開発者を対象としています。ディープラーニングでは、インテル® oneDNN を利用するア
プリケーションを使用すべきです。
インテル® oneDNN は、インテル® oneAPI DL フレームワーク・デベロッパー・ツールキット、インテル®
oneAPI ベース・ツールキットの一部として配布され、apt または yum チャネルから入手できます。
インテル® oneDNN は、C および C++ インターフェイス、OpenMP*、インテル® oneAPI スレッディング・
ビルディング・ブロック、OpenCL* ランタイムなど、DNNL で現在サポートされる機能を引き続きサポートします。インテル® oneDNN は、oneAPI プログラミング・モデルの DPC++ API とランタイムサポートを導入します。
詳細は、https://github.com/oneapi-src/oneDNN（英語）をご覧ください。

97

5
関連情報
インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー導入ガイド（英語）インテル® oneAPI ディープ・ニューラル・ネットワーク・ライブラリー・ドキュメント（英語）インテル® oneDNN の使い方
インテル® oneDNN は、インテル® 64 アーキテクチャーまたは互換プロセッサーをベースにするシステ
ムをサポートします。サポートされる CPU およびグラフィックス・ハードウェアのリストは、「インテル®
oneAPI Deep Neural Network ライブラリーのシステム要件」を参照してください。
インテル® oneDNN は実行時に命令セット・アーキテクチャー（ISA）を検出し、オンライン生成機能を使用して、サポートされる最新の ISA 向けに最適化されたコードを展開します。
アプリケーションが使用する CPU または GPU ランタイム・ライブラリーとの相互運用性を保証するため、オペレーティング・システムごとにいくつかのパッケージが提供されます。
設定

依存関係

cpu_dpcpp_gpu_dpcpp

DPC++ ランタイム

cpu_iomp

インテルの OpenMP* ランタイム

cpu_gomp

GNU* OpenMP* ランタイム

cpu_vcompMicrosoft Visual C++* OpenMP* ランタイム

cpu_tbb

インテル® oneAPI スレッディング・ビルディング・ブロックパッケージには必要なライブラリーが含まれていないため、ビルド時にインテル® oneAPI ツールキット
またはサードパーティーのツールを使用してアプリケーションで依存関係を解決する必要があります。
DPC++ 環境では、インテル® oneDNN は DPC++ ランタイムを介して CPU または GPU ハードウェアと対話します。インテル® oneDNN は DPC++ を使用するほかのコードを使用することもできます。これを可能にするため、インテル® oneDNN は基盤となる SYCL* オブジェクトと相互作用する API 拡張機能を提供します。
そのような状況の 1 つとして、インテル® oneDNN が提供しないカスタム操作を行うため DPC++ カー
ネルを実行する場合が考えられます。その場合、インテル® oneDNN はカーネルをシームレスに送信するのに必要な API を提供し、同じデバイスキューを使用して実行コンテキストをインテル® oneDNN と共
有します。

98

API ベースのプログラミング
相互運用性を提供する API は、次の 2 つのシナリオを想定します。
•

既存の DPC++ オブジェクトをベースとするインテル® oneDNN オブジェクトの構築•

既存のインテル® oneDNN オブジェクト向けの DPC++ オブジェクトへのアクセス

次の表にインテル® oneDNN オブジェクトと DPC++ オブジェクトのマッピングを示します。
インテル® oneDNN オブジェクト

DPC++ オブジェクトエンジン

cl::sycl::device および cl::sycl::context

ストリーム

cl::sycl::queue

メモリー

cl::sycl::buffer<uint8_t, 1> または統合共有メモリー（USM）ポインター

注：内部的にライブラリー・メモリー・オブジェクトは、1D uint8_t SYCL* バッファーを使用しますが、異なる型の SYCL* バッファーを介してメモリーを初期化およびアクセスできます。この場合、バッファーは異なる型の cl::sycl::buffer<uint8_t, 1> に再解釈されます。

インテル® oneDNN オブジェクト

DPC++ オブジェクトからの再構成

エンジン

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_desc,
engine, sycl_buf)

インテル® oneDNN オブジェクト

DPC++ オブジェクトの抽出

エンジン

dnnl::sycl_interop::get_device(engine)
dnnl::sycl_interop::get_context(engine)

ストリーム

dnnl::sycl_interop::get_queue(stream)

99

5

メモリー

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 は必要ありません。

インテル® oneDNN サンプルコード
インテ ル® oneDNN のサ ンプ ルコードは、 https://github.com/oneapi-src/oneAPI-samples/tree/
master/Libraries/oneDNN（英語）から入手できます。導入向けのサンプルは新規ユーザーを対象として
おり、ビルドコマンドと実行コマンドの例を含む readme ファイルが含まれています。

インテル® oneAPI ビデオ・プロセシング・ライブラリー（インテル® oneVPL)
インテル® oneAPI ビデオ・プロセシング・ライブラリー（インテル® oneVPL）は、CPU、GPU、およびそのほ
かのアクセラレーターでポータブルなメディア・パイプラインを構築する、ビデオデコードとエンコード、および処理をおこなうプログラミング・インターフェイスです。インテル® oneVPL API は、インテル® ハー
ドウェア・アクセラレーターを最大限に活用する、高品質で高いパフォーマンスのビデオ・アプリケーションを開発するために使用されます。メディア・セントリックのビデオ解析ワークロードにおけるデバイスの検出と選択、およびゼロコピーバッファー共有向けの API プリミティブを提供します。インテル® oneVPL
は、インテル® メディア SDK と下位互換性があり、アーキテクチャー間の互換性も提供するため、ソース
コードを変更することなく現在および将来のハードウェアで最適な実行が保証されます。
インテル® oneVPL はオープン仕様の API です。

関連情報インテル® oneVPL 導入ガイド（英語）100API ベースのプログラミング
インテル® oneVPL の使い方
アプリケーションはインテル® oneVPL を使用して、ビデオのエンコードとデコード、および画像処理コン
ポーネントをプログラムできます。インテル® oneVPL はアクセラレーターを使用する前に、リファレンス設計として使用できるデフォルトの CPU 実装を提供します。
インテル® oneVPL アプリケーションは、次のプログラミング・モデルの基本的な手順に従います。
1.
2.
3.
4.
5.
6.

インテル® oneVPL ディスパッチャーは、実行時に利用可能なすべてのアクセラレーターを自動検索します。
ディスパッチャーは、選択したアクセラレーター・コンテキストのセッションを初期化します。
インテル® oneVPL は、セッションの開始時にビデオ・コンポーネントを構成します。
インテル® oneVPL 処理ループが開始されます。処理ループは非同期で動作します。
アプリケーションがインテル® oneVPL に作業メモリーを管理させることを選択した場合、メモリー割り当ては処理ループ内のビデオ呼び出しによって暗黙的に管理されます。
作業が完了すると、インテル® oneVPL はクリア呼び出しによりすべてのリソースをクリーンアップ
します。

インテル® oneVPL API は、クラシックな C スタイルのインターフェイスで定義されており、C++ とDPC++ とも互換性があります。

インテル® oneVPL サンプルコード
インテル® oneVPL には、インテル® oneVPL API の使い方を示す豊富なサンプルコードが用意されています。サンプルコードはリリースパッケージに含まれており、GitHub* リポジトリーの「oneAPI-samples」（英語）からも入手できます。
例えば、「hello-decode」（英語）サンプルでは、HEVC 入力ストリームの簡単なデコード操作とインテル®
oneVPL プログラミング・モデルの基本的な手順を説明しています。
サンプルコードは次のような手順に分解できます。
注：以下の例は最新のサンプルとは異なる場合があります。最新のバージョンについては、リリースパッ
ケージまたはサンプルのリポジトリーを参照してください。
1.

ディスパッチャーでインテル® oneVPL セッションを初期化します。

101

5
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 に作業メモリーの管理を要求することを意味します。

102

API ベースのプログラミング
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);103

5
最後に、MFXUnload() が呼び出されインテル® oneVPL からリソースが再利用されます。これは、インテル® oneVPL ライブラリーがリソースを再利用するためアプリケーションが行うべき唯一の呼び出しです。
注：この例では、インテル® oneVPL プログラミング・モデルの主な手順について説明しています。入力と出力ユーティリティー関数については説明していません。

その他のライブラリー
その他のライブラリーは、各種インテル® oneAPI ツールキットに含まれます。各ライブラリーの詳細については、それぞれのライブラリーの公式ドキュメントをご覧ください。
•

インテル® インテグレーテッド・パフォーマンス・プリミティブ（インテル® IPP）•

インテル® MPI ライブラリー•

インテル® オープン・ボリューム・カーネル・ライブラリー

104

ソフトウェア開発プロセス

6

oneAPI プログラミング・モデルを使用したソフトウェア開発プロセスは、標準の開発プロセスをベースにしています。プログラミング・モデルは、アクセラレーターを使用してパフォーマンスを向上するため、この章ではその作業に固有の手順を説明します。これには以下のものがあります。
•

パフォーマンス・チューニング・サイクル•

コードのデバッグ•

ほかのアクセラレーター向けのコードの移行•

コードのコンポーザビリティー

DPC++ へのコードの移行
C++ または OpenCL* などほかのプログラミング言語で記述されたコードは、複数のデバイスで使用するため DPC++ コードへ移行できます。移行手順は、元の言語によって異なります。

C++ から SYCL*/DPC++ への移行
SYCL* は、C++ をベースとする「単一ソース」スタイルのプログラミング・モデルです。C++11 の機能を基に構築され、C++14 の追加サポートがあり、OpenCL* デバイスで C++17 Parallel STL プログラムの高速化を可能にします。サポートされる C++ 機能には、テンプレート、クラス、演算子のオーバーロード、ラ
ムダ式、静的ポリモーフィズムが含まれます。
OpenCL* デバイス上で既存の C++ アプリケーションを高速化する場合、大部分の C++ コードは変更する必要がないため、SYCL* はシームレスな統合を可能にします。デバイス側のコンパイルを可能にする
SYCL* の構造については、「oneAPI プログラミング・モデル」をご覧ください。

CUDA* から DPC++ への移行
インテル® DPC++ 互換性ツールは、インテル® oneAPI ベース・ツールキットに含まれます。このツールの目的は、NVIDIA CUDA* で記述された既存のプログラムから、DPC++ で記述されるプログラムへの移行を支援することです。このツールは、可能な限り DPC++ コードを自動生成し、インテル® oneAPI
DPC++ コンパイラーで正しくコンパイルできるようにします。しかし、すべてのコードが自動的に移行されるとは限らず、手動での変更が必要な場合があります。このツールには、IDE プラグインヘルプと、

105

6DPC++ への移行を完了するための『ユーザーガイド』（英語）が含まれます。手動での変更が完了したら、
DPC++ コンパイラーを使用して実行可能ファイルを作成します。

移行されたコード例、ツールのダウンロード手順などの説明は、インテル® DPC++ 互換性ツール・ウェブ
サイト（英語）でご覧いただけます。ツールの詳しい使用方法は、『インテル® DPC++ 互換性ツール・ユー
ザーガイド』（英語）を参照してください。

OpenCL* コードから DPC++ への移行
現在のバージョンの DPC++ では、ランタイムは並列処理を実現するため OpenCL* コードを採用しています。通常、DPC++ ではカーネルを実装するコードの行数と必要な API 関数やメソッドの呼び出しは少なくなります。ホストのソースコード行にデバイスのソースコードを埋め込むことで、OpenCL* プログラ
ムを作成できます。
ほとんどの OpenCL* アプリケーション開発者は、デバイスへのカーネルオフロードに伴うセットアップ・
コードの必要性を認識しているでしょう。DPC++ を使用すると、OpenCL* C コードに関連する大部分のセットアップ・コードなしで、シンプルで現代的な C++ ベースのアプリケーションを開発できます。これにより、習得の労力が軽減され、並列化の実装に集中できます。
さらに、OpenCL* アプリケーションの機能は、SYCL* API を介して引き続き利用できます。更新された
コードは、必要に応じて SYCL* インターフェイスを使用できます。

CPU、GPU、および FPGA 間の移行
DPC++ では、プラットフォームは CPU、GPU、FPGA、またはその他のアクセラレーターやプロセッサーなどのデバイス（なくてもかまいません）に接続されたホストデバイスで構成されます。
プラットフォームに複数のデバイスが存在する場合、一部または大部分のワークをデバイスへオフロードするようにアプリケーションを設計します。oneAPI プログラミング・モデルで複数のデバイスにワークを分散するには、いくつかの方法があります。

106

ソフトウェア開発プロセス
1.

2.

デバイスセレクターの初期化 - SYCL* ではセレクターと呼ばれるクラスが提供され、プラット
フォーム内のデバイスを手動で選択するか、oneAPI ランタイムのヒューリスティックがデバイスで利用可能な計算機能を判断してデフォルトデバイスを選択できるようになっています。
データセットの分割 - データに依存関係がない高い並列性を持つアプリケーションでは、データセットを明示的に分割して異なるデバイスで利用します。次のサンプルコードは、複数のデバイスにワークロードを分配する例です。dpcpp snippet.cpp コマンドでコードをコンパイルします。
int main() {int data[1024];
for (int i = 0; i < 1024; i++)data[i] = i;try {cpu_selector cpuSelector;
queue cpuQueue(cpuSelector);
gpu_selector gpuSelector;
queue gpuQueue(gpuSelector);
buffer<int, 1> buf(data, range<1>(1024));
cpuQueue.submit([&](handler& cgh) {auto ptr =buf.get_access<access::mode::read_write>(cgh);
cgh.parallel_for<class divide>(range<1>(512),[=](id<1> index) {ptr[index] -= 1;});});
gpuQueue.submit([&](handler& cgh1) {auto ptr =buf.get_access<access::mode::read_write>(cgh1);
cgh1.parallel_for<class offset1>(range<1>(1024),
id<1>(512), [=](id<1> index) {ptr[index] += 1;});});
cpuQueue.wait();gpuQueue.wait();}catch (exception const& e) {std::cout <<"SYCL exception caught: " << e.what() << '\n';return 2;}
return 0;}

3.

デバイス間で複数のカーネルをターゲットにする - アプリケーションに複数の独立したカーネルで並列処理可能なスコープがある場合、ターゲットデバイスごとに異なるキューを使用します。
SYCL* がサポートされるプラットフォームとプラットフォームごとのデバイスのリストは、
get_platforms() と platform.get_devices() を呼び出すことで取得できます。すべてのデバイスが特定されたら、デバイスごとにキューを作成し、異なるカーネルを異なるキューに配布します。次のサンプルコードは、複数の SYCL* デバイスにカーネルを配布する方法を示します。

107

6#include <stdio.h>#include <vector>#include <CL/sycl.hpp>
using namespace cl::sycl;
using namespace std;
int main(){size_t N = 1024;
vector<float> a(N, 10.0);
vector<float> b(N, 10.0);
vector<float> c_add(N, 0.0);
vector<float> c_mul(N, 0.0);{
buffer<float, 1> abuffer(a.data(), range<1>(N),{ property::buffer::use_host_ptr() });buffer<float, 1> bbuffer(b.data(), range<1>(N),{ property::buffer::use_host_ptr() });buffer<float, 1> c_addbuffer(c_add.data(), range<1>(N),{ property::buffer::use_host_ptr() });buffer<float, 1> c_mulbuffer(c_mul.data(), range<1>(N),{ property::buffer::use_host_ptr() });try {gpu_selector gpuSelector;
auto queue = cl::sycl::queue(gpuSelector);queue.submit([&](cl::sycl::handler& cgh) {auto a_acc = abuffer.template
get_access<access::mode::read>(cgh);auto b_acc = bbuffer.template
get_access<access::mode::read>(cgh);auto c_acc_add = c_addbuffer.template
get_access<access::mode::write>(cgh);
cgh.parallel_for<class VectorAdd>(range<1>(N), [=](id<1> it) {//int i = it.get_global();c_acc_add[it] = a_acc[it] + b_acc[it];});});cpu_selector cpuSelector;
auto queue1 = cl::sycl::queue(cpuSelector);queue1.submit([&](cl::sycl::handler& cgh) {auto a_acc = abuffer.template
get_access<access::mode::read>(cgh);auto b_acc = bbuffer.template
get_access<access::mode::read>(cgh);auto c_acc_mul = c_mulbuffer.template
get_access<access::mode::write>(cgh);
cgh.parallel_for<class VectorMul>(range<1>(N), [=](id<1> it) {c_acc_mul[it] = a_acc[it] * b_acc[it];
});
});
}
catch (cl::sycl::exception e) {/* In the case of an exception being throw, print theerror message and return 1. */std::cout << e.what();return 1;}}

108ソフトウェア開発プロセス
for (int i = 0; i < 8; i++) {std::cout << c_add[i] << std::endl;
std::cout << c_mul[i] << std::endl;}
return 0;}

コンポーザビリティー
oneAPI プログラミング・モデルは、開発ツールチェーン全体をサポートするエコシステムを実現します。
これには、CPU、GPU、FPGA など複数のアクセラレーターをサポートするコンパイラーとライブラリー、
デバッガーと解析ツールが含まれます。

C/C++ OpenMP* および DPC++ のコンポーザビリティー
oneAPI プログラミング・モデルは、OpenMP* オフロードをサポートする LLVM/Clang ベースの統合コンパイラーを提供します。これにより、OpenMP* 構造を使用してホスト側のアプリケーションを並列化
するか、ターゲットデバイスにオフロードする、シームレスな統合が可能になります。インテル® oneAPI
ベース・ツールキットで利用可能なインテル® oneAPI DPC++/C++ コンパイラーと、インテル® oneAPI
HPC ツールキットやインテル® oneAPI IoT ツールキットで利用可能なインテル® C/C++ コンパイラー・クラシックは、制限付きで OpenMP* と DPC++ の互換性を提供します。単一のアプリケーションでは、OpenMP* target 領域または DPC++/SYCL* 構造を使用して、さまざまな関数やコードセグメントなどのコード領域の実行を利用可能なデバイスにオフロードできます。
OpenMP* と DPC++ オフロード構造は、別々のファイル、同じファイル、または同じ関数（制限付き）で使用できます。OpenMP* および DPC++ オフロードコードは、実行可能ファイル、静的ライブラリー、またはさまざまな組み合わせで一緒にバンドルできます。
注：DPC++ は CPU でデバイスコードを実行する場合、インテル® TBB のランタイムを使用します。そのため、CPU で OpenMP* と DPC++ の両方を使用すると、スレッドのオーバーサブスクリプションが発生する可能性があります。システムで実行されるワークロードのパフォーマンスを解析することで、この問題が生じているか確認することができます。

制限事項
同じアプリケーションで OpenMP* と DPC++/SYCL* 構造を混在する場合、いくつかの考慮すべき制限があります。

109

6•

OpenMP* ディレクティブは、デバイスで実行される DPC++/SYCL* カーネル内では使用できません。
同様に、DPC++/SYCL* コードは、OpenMP* target 領域内では使用できません。ただし、ホスト CPU
で実行される OpenMP* コード内で SYCL* 構造を使用することはできます。

•

プログラム内の OpenMP* および DPC++/SYCL* デバイス領域は相互依存関係を持つことができません。例えば、デバイスコードの SYCL* 領域で定義された関数は、同じデバイスで実行されるOpenMP* コードから呼び出すことはできません（その逆も同様）。OpenMP* デバイス領域と SYCL*
デバイス領域は個別にリンクされ、個別のバイナリーとしてコンパイラーによって生成されるファット
バイナリーを構成します。

•

現時点では、OpenMP* と SYCL* ランタイム・ライブラリー間での直接的な相互作用はサポートされていません。例えば、OpenMP* API で生成されたデバイス・メモリー・オブジェクトは、DPC++ コード
か ら は ア ク セ ス で き ま せ ん 。 OpenMP* で 生 成 さ れ た デ バ イ ス ・ メ モ リ ー ・ オ ブ ジ ェ ク ト を
DPC++/SYCL* コードで使用すると、未定義の動作となります。

例
次のコードは、DPC++/SYCL* と OpenMP* オフロード構造を同じアプリケーションで使用する例を示し
ます。

110

ソフトウェア開発プロセス#include <CL/sycl.hpp>#include <array>#include <iostream>
float computePi(unsigned N) {float Pi;
#pragma omp target map(from : Pi)#pragma omp parallel for reduction(+ : Pi)
for (unsigned i = 0; i < N; ++i) {float T = (i + 0.5f) / N;
Pi += 4.0f / (1.0 + T * T);}return Pi / N;}void iota(float *A, unsigned N) {cl::sycl::range<1> R(N);cl::sycl::buffer<float, 1> AB(A, R);
cl::sycl::queue().submit([&](cl::sycl::handler &cgh) {auto AA = AB.template get_access<cl::sycl::access::mode::write>(cgh);
cgh.parallel_for<class Iota>(R, [=](cl::sycl::id<1> i) {AA[i] = i;
});
});
}
int main() {std::array<float, 1024u> Vec;
float Pi;
#pragma omp parallel sections{#pragma omp section
iota(Vec.data(), Vec.size());#pragma omp section
Pi = computePi(8192u);}
std::cout << "Vec[512] = " << Vec[512] <<std::endl; std::cout << "Pi = " << Pi << std::endl;
return 0;}

サンプルコードをコンパイルするには次のコマンドを使用します。
icpx -fsycl -fiopenmp -fopenmp-targets=spir64 offloadOmp_dpcpp.cpp
説明：•-fsycl オプションは DPC++ を有効にします。

•-fiopenmp -fopenmp-targets=spir64 オプションは OpenMP* オフロードを有効にします。

111

6
次はサンプルコードからの出力例となります。
./a.out
Vec[512] = 512
Pi = 3.14159

注：コードに OpenMP* オフロードが含まれておらず、通常の OpenMP* コードのみが含まれる場合、-fopenmp-targets を省いた次のコマンドを使用します。
icpx -fsycl -fiopenmp omp_dpcpp.cpp

OpenCL* コードの相互運用性
oneAPI プログラミング・モデルにより、開発者は SYCL* API のさまざまな部分からすべての OpenCL*
コードの機能を引き続き利用できます。SYCL* が提供する OpenCL* コードの相互運用性は、SYCL* が持つ高度なプログラミング・モデル・インターフェイスを利用しながら、従来の OpenCL* コードを再利用するのに役立ちます。この相互運用性モードには 2 つの主要機能があります。
1.

OpenCL* コードのオブジェクトから SYCL* オブジェクトを生成する。例えば、SYCL* バッファーは、
OpenCL* cl_mem から、または cl_command_queue の SYCL* キューから構築できます。
SYCL* オブジェクトから OpenCL* コードのオブジェクトを取得する。例えば、SYCL* アクセサーに関連付けられた暗黙の cl_mem を使用する OpenCL* カーネルを起動します。

2.

DPC++ と OpenMP* オフロード処理のデバッグ
ホスト・プラットフォーム向けにコードを記述、デバッグ、および最適化する場合、コードを改善する手順
はシンプルです。ビルド時に言語レベルのエラーに対処し、デバッガーで実行中のクラッシュや不正な結果をキャッチして原因を解決し、プロファイル・ツールを使用してパフォーマンスの問題を特定して修正します。
コードの一部分が DPC++ または OpenMP* オフロードにより別のデバイスで実行されるアプリケー
ションでは、コードの改善はかなり複雑になる可能性があります。
•

DPC++ または OpenMP* オフロードの誤った使い方は、接続されたオフロードデバイスでプログラ
ムが実行される際に、ジャストインタイム（JIT）コンパイルされるまで認識できないことがあります（この問題は、事前コンパイル（AOT）で確認できることがあります）。

•

プログラムの論理的なエラーによるクラッシュは、ホスト、オフロードデバイス、または各種計算デバ
イスを連携させるソフトウェア・スタックで予期しない動作として現れる可能性があります。原因を究明するには以下が必要です。

112ソフトウェア開発プロセス••

インテル® ディストリビューション for GDB などの標準デバッガーを使用して、ホスト上のコード
で何が起こっているかデバッグします。

•

デバイス固有のデバッガーを使用してオフロードデバイスの問題をデバッグします。ただし、デバイスのアーキテクチャー、計算スレッドを表現する規則、またはアセンブリーがホストとは異なることに注意してください。

•

カーネルとデータがデバイスとのやり取りを行う場合にのみ中間ソフトウェア・スタックで現れる問題をデバッグするには、デバイスとホスト間の通信、および処理中に報告されるエラーを監視する必要があります。

ホストとオフロードデバイスで発生する可能性がある一般的なパフォーマンスの問題に加えて、ホストとオフロードデバイスが連携するパターンは、アプリケーションのパフォーマンスに大きな影響を与えることがあります。これは、ホストとオフロードデバイス間の通信を監視する必要があるもう 1 つのケースです。

ここでは、オフロードプログラムの実行中に利用できる各種デバッグおよびパフォーマンス解析ツールとその用法について説明します。

oneAPI デバッグツール
次に示すツールは、DPC++ および OpenMP* オフロード処理のデバッグに役立ちます。
ツール

使用方法

環境変数

環境変数を使用して、プログラムを変更することなく、プログラ
ムの実行時に OpenMP* および DPC++ ランタイムから診断情報を収集できます。

GPU 向けのプロファイル・ツールである ze_tracer DPC++ および OpenMP* オフロードで oneAPI レベルゼロ・
ツール（GPU 向け PTI）
バックエンドを使用する場合、このツールを利用してバックエンドのエラーをデバッグし、ホストとデバイスの両方でパフォーマ
ンスのプロファイルを実行できます。
関連資料：• ze_tracer ツールの GitHub*（英語）• GPU 向け PTI のGitHub*（英語）OpenCL* アプリケーションのインターセプト・レイ DPC++ および OpenMP* オフロードで OpenCL* バックエンド
ヤーを使用する場合、このライブラリーを利用してバックエンドのエ
ラーをデバッグし、ホストとデバイスの両方でパフォーマンスのプロファイルを実行できます。
インテル® ディストリビューション for GDB

通常ホストおよびデバイス（CPU、GPU、FPGA エミュレーション）で、論理的なバグを調査する際にアプリケーションのソース
レベルのデバッグで使用されます。

113

6

インテル® Inspector

このツールは、オフロードの失敗につながる問題を含め、メモリーとスレッドの問題を検出してデバッグするのに役立ちます。
注：インテル® Inspector は、インテル® oneAPI HPC ツール
キットまたはインテル® oneAPI IoT ツールキットに含まれます。

アプリケーション・デバッグ

これらのツールとランタイムベースのアプローチに加えて、開発者は別のアプローチから問題を見つけることもできます。次に例を示します。
• カーネルの出力と期待される出力を比較• デバッグ用途の変数を作成して中間結果を確認• カーネル内で結果をプリント
注：DPC++ と OpenMP* では、どちらもオフロード領域内からの stdout への出力をサポートします。どの SIMD レーンまたはスレッドが出力しているか確認してください。

デバッグ環境変数
OpenMP* と DPC++ のオフロードランタイムは、ホストとオフロードデバイス間の通信を監視する環境変数を提供します。この環境変数を使用して、オフロード計算向けに選択されたランタイムを検出または制御できます。
OpenMP* オフロード環境変数
OpenMP* オフロードがどのように動作するかを理解し、バックエンドの制御に利用できるいくつかの環
境変数が用意されています。
注：OpenMP* は、FPGA デバイスではサポートされません。

114

ソフトウェア開発プロセス

環境変数

説明

LIBOMPTARGET_DEBUG

この環境設定は、OpenMP* オフロードランタイムからのデバッグ出力を有効にします。以下が報告されます。
•
•
•
•
•
•
•
•

検出および使用された利用可能なランタイム（1、2）
選択されたランタイムが開始および停止されたタイミング（1、2）使用されるオフロードデバイスの詳細（1、2）
ロードされたサポート・ライブラリー（1、2）すべてのメモリー割り当てと解放のサイズとアドレス（1、2）
デバイス間とのデータコピーに関する情報、また統合共有メモリーではデバイスマッピング（1、2）カーネルの起動と起動時の詳細情報（引数、SIMD 幅、グループ情報など）（1、2）
呼び出されたレベルゼロ/OpenCL* API 関数（関数名、引数/パラメーター）（2）値：（0、1、2）
デフォルト：0
LIBOMPTARGET_PLUGIN_PROFILE

この環境変数は、オフロードされた OpenMP* コードのパフォーマンス・
データの表示を有効にします。以下を表示します。
••••

合計データ転送時間（リードとライト）
データ割り当て回数
モジュールのビルド時間（ジャストイン・タイム・コンパイル）
各カーネルの実行時間。

値：
•
•
•

F - 無効化T - ミリ秒単位のタイミングで有効化
T,usec- マイクロ秒単位のタイミングで有効化

デフォルト：F
例：export LIBOMPTARGET_PLUGIN_PROFILE=T,usec
LIBOMPTARGET_PLUGIN

この環境変数を使用して OpenMP* オフロードの実行に使用するバッ
クエンドを選択できます。
注：レベルゼロ・バックエンドは GPU デバイスでのみサポートされま
す。
値：
•
•

LEVEL0 - レベルゼロ・バックエンドを使用します
OPENCL - OpenCL* バックエンドを使用します

デフォルト：
GPU オフロードデバイス：LEVEL0
CPU または FPGA オフロードデバイス：OPENCL115

6SYCL* と DPC++ 環境変数
DPC++ プログラムは、すべての標準 SYCL* 環境変数をサポートします。すべての環境変数については
GitHub*（英語）をご覧ください。デバッグで注目すべきは、次の SYCL* 環境変数と追加のレベルゼロ環
境変数です。
環境変数

説明

SYCL_DEVICE_FILTER

この複雑な環境変数を使用すると、DPC++ ランタイムで使用されるランタイム、計算デバイス ID を利用可能なすべての組み合わせのサブセットに制御できます。
計算デバイス ID は、SYCL* API、clinfo、または sycl-ls（1 から始まる番号）によって返される ID に対応します。その ID を持つデバイスが特定のタイプであった
り、特定のランタイムをサポートするかには関連性がありません。プログラムが特定のセレクター（gpu_selector など）を使用して、SYCL_DEVICE_FILTER のフィ
ルターで除外されたデバイスを要求すると、例外がスローされます。
詳細については、GitHub* にある環境変数の説明をご覧ください。
https://github.com/intel/llvm/blob/sycl/sycl/doc/EnvironmentVariables.md（英語）
次のような値を含みます。
• opencl:cpu - 利用可能なすべての CPU デバイスで OpenCL* ランタイムのみを使用します• opencl:gpu - 利用可能なすべての GPU デバイスで OpenCL* ランタイムのみを使用します• opencl:gpu:2 - GPU である 2 番目のデバイスでのみ OpenCL* ランタイムのみを使用します• level_zero:gpu:1 - GPU である最初のデバイスでのみレベルゼロランタイ
ムのみを使用します• opencl:cpu,level_zero - CPU デバイスでは OpenCL* ランタイムのみを使用し、サポートされる計算デバイスではレベルゼロランタイムを使用します
デフォルト：利用可能なすべてのランタイムとデバイスを使用します

SYCL_PI_TRACE

この環境設定は、DPC++ランタイムからのデバッグ出力を有効にします。
値：
•
•
•

1 – SYCL* プラグインとデバイスが検出され使用されたことを報告します
2 - 引数と結果の値を含む SYCL* API 呼び出しを報告します-1 - 利用可能なすべてのトレースを報告します

デフォルト：無効116

ソフトウェア開発プロセス
ZE_DEBUG

この環境変数は、DPC++ ランタイムが使用された際にレベルゼロ・バックエンドからのデバッグ出力を有効にします。以下が報告されます。
••

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

値：任意の値で定義された変数（有効）デフォルト：無効

サポート向けの診断情報を生成する環境変数
レベルゼロ・バックエンドは、動作を制御して診断を支援するいくつかの環境変数を提供します。
•

レベルゼロ仕様、コア・プログラミング・ガイド：
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* オ フロードと 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* オフロードや DPC++ オフロード・アプリケー
ションのパフォーマンスの問題が生じる場合、異なるコンパイラー・オプションを使用したり、デバッガーを使用するなど、IGC_ShaderDumpEnable を有効にして結果ファイルを提供する必要があります。互換性の詳細については、「oneAPI ライブラリーの互換性」を参照してください。

オフロード・インターセプト・ツール
オフロード・ソフトウェア自身に組み込まれているデバッガーと診断情報に加えて、オフロード・パイプラ
インを介して送信される API 呼び出しとデータを監視するのは有用です。OpenCL* では、OpenCL* 呼び
出しをインターセプトして報告するライブラリーを LD_LIBRARY_PATH に追加して、環境変数を設定し117

6
ファイルへの診断情報生成を制御できます。レベルゼロでは、アプリケーションは ze_tracer ツールの引数として実行されます。ze_tracer の呼び出し方に応じて、レベルゼロ API 呼び出しのさまざまな側面をインターセプトして報告します。
OpenCL* アプリケーションのインターセプト・レイヤー
このライブラリーは、DPC++ または OpenMP* オフロードのバックエンドとして OpenCL* が使用される場合にデバッグおよびパフォーマンス・データを収集します。OpenCL* が DPC++ または OpenMP*
オフロードのバックエンドである場合、このツールはバッファーのオーバーライト、メモリーリーク、ポイ
ンターの不一致を検出し、ランタイム・エラー・メッセージのより詳しい情報を提供します（CPU、FPGA、または GPU のいずれかが計算デバイスである場合にこれらの問題を診断できます）。OpenCL* バックエンドを使用するプログラムで ze_tracer を利用する場合や、レベルゼロ・バックエンドを使用するプログラムで 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 最適化ガイド』から入手できます。

ze_tracer
OpenCL* アプリケーションのインターセプト・レイヤーと同様に、このツールは、レベルゼロが DPC++
または OpenMP* バックエンドである場合にデバッグおよびパフォーマンス・データを収集します。レベルゼロは、GPU で実行される計算のバックエンドとしてのみ利用できることに注意してください（現時点
で 、 CPU と FPGA 向 け の レ ベ ル ゼ ロ ・ バ ッ ク エ ン ド は あ り ま せ ん ） 。 ze_tracer ツ ー ル は 、
https://github.com/intel/pti-gpu（英語）にある GPU 向けのプロファイル・ツール・インターフェイス（GPU 向け PTI）プロジェクトの一部です。OpenCL* バックエンドを使用するプログラムで ze_tracer を利用する場合や、レベルゼロ・バックエンドを使用するプログラムで OpenCL* アプリケーション・ライブ
ラリーのインターセプト・レイヤーを利用する場合には、あまり役立たないことに注意してください。

118

ソフトウェア開発プロセス
ze_tracer ツ ー ル は ソ ー ス と し て 配 布 さ れ て い ま す 。 ツ ー ル の ビ ル ド に 関 す る 手 順 は 、
https://github.com/intel/pti-gpu/tree/master/tools/ze_tracer（英語）を参照してください。このツー
ルは次の機能を提供します。
•

呼び出しのログ：このモードでは、すべての標準レベルゼロ（L0）API 呼び出しとその引数、およびタイ
ムスタンプ付きの戻り値をトレースできます。これにより、ホストプログラムが接続された計算デバイスを利用する際に発生する障害の補足情報が得られます。

•

ホストとデバイスのタイミング：すべての API 呼び出しの存続期間、カーネルの存続期間、およびアプ
リケーション全体の実行時間を提供します。

•

デバイス・タイムライン・モード：各デバイス・アクティビティーのタイムスタンプを提供します。すべてのタイムスタンプは、同じ（CPU）時間スケールで示されます。

•

ブラウザーの可視化：呼び出しトレースモードとデバイス・タイムライン・モードの結果をトレースファイル（JSON）に出力し、ブラウザーで視覚的に閲覧できます。

このデータはオフロードの障害やパフォーマンスの問題をデバッグするのに役立ちます。
追加のリソース：•

GPU 向けプロファイル・ツール・インターフェイス（GPU 向け PTI）GitHub プロジェクト（英語）•ze_tracer の GitHub ページ（英語）インテル® ディストリビューション for GDB
インテル® ディストリビューション for GDB は、プログラムの状態を調査および変更できるアプリケー
ション・デバッガーです。アプリケーションのホスト部分とデバイスにオフロードされたカーネルの両方を、同じデバッグセッションでシームレスにデバッグできます。このデバッガーは、CPU、GPU、および FPGA
エミュレーション・デバイスをサポートします。主な機能を以下に示します。
•

GPU デバイスに自動的に接続してデバッグイベントを監視します•

デバッグ用に JIT コンパイルされた、または動的にロードされたカーネルバイナリーを自動的に検出します•プログラムの実行を停止するブレークポイントの設定（カーネル内部と外部の両方）•スレッドのリスト表示、現在のスレッド・コンテキストへの切り替え•

アクティブな SIMD レーンのリスト表示、現在の SIMD レーンのコンテキストをスレッドごとに切り替
え•

複数のスレッドと SIMD レーン・コンテキストの式値の評価と出力•

レジスター値の調査と変更

119

6
•

マシン命令の逆アセンブル•

関数呼び出しスタックの表示とナビゲート•

ソースと命令レベルのステップ実行•

非停止およびすべて停止のデバッグモード•

インテル® プロセッサー・トレースを使用した実行の記録（CPU のみ）

インテル® ディストリビューション for GDB の詳細とドキュメントへのリンクは、「インテル® ディストリ
ビューション for GDB 導入ガイド（Linux* 版）」（英語）または「インテル® ディストリビューション for
GDB 導入ガイド（Windows* 版）」（英語）をご覧ください。

オフロード向けインテル® Inspector
インテル® Inspector は、シリアルおよびマルチスレッド・アプリケーションを開発するユーザー向けの動的メモリーおよびスレッドエラーを検出するツールです。動的に生成されたオフロードコードだけでなく、
アプリケーションのネイティブコードの正当性を検証するのに利用できます。
前述のツールや手法とは異なり、インテル® Inspector は GPU または FPGA と通信するオフロードコー
ドのエラーを検出することはできません。インテル® Inspector では、CPU をターゲットとしてカーネルを実行するように DPC++ または OpenMP* ランタイムを設定する必要があります。解析を実行する前に、次の環境変数を設定する必要があります。
•

CPU デバイスでカーネルを実行するように DPC++ アプリケーションを設定します。
Export SYCL_DEVICE_FILTER=opencl:cpu•

CPU デバイスでカーネルを実行するように OpenMP* アプリケーションを設定します。
export OMP_TARGET_OFFLOAD=MANDATORY
export LIBOMPTARGET_DEVICETYPE=cpu•

JIT コンパイラーまたはランタイムでコード解析とトレース有効にします。
export CL_CONFIG_USE_VTUNE=Trueexport 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-all120

ソフトウェア開発プロセス
DPC++ や OpenMP* オフロードプログラムが OpenCL* バックエンドに不正なポインターを渡したり、誤ったスレッドからバックエンドに不正なポインターを渡す場合、インテル® Inspector は問題を警告します。これにより、インターセプト・レイヤーやデバッガーを使用して問題を見つけるよりも容易な場合があります。
「インテル® Inspector ユーザーガイド（Linux* 版）」（英語）またはインテル® Inspector ユーザーガイド（Windows* 版）」（英語）で詳細を参照できます。

オフロード処理のトレース
GPU に計算をオフロードするプログラムが開始される場合、プログラムの実行に関連する多くのコン
ポーネントが動作します。マシン非依存のコードをマシン依存のコードにコンパイルし、データとバイナ
リーをデバイスにコピーして、結果を戻す必要があります。ここでは、「oneAPI デバッグツール」で説明したツールを使用して、すべてのアクティビティーをトレースする方法を示します。

カーネル設定時間
オフロードコードをデバイスで実行する前に、マシン非依存のカーネルをターゲットデバイス向けにコンパイルしてコードをデバイスにコピーする必要があります。このカーネルのセットアップ時間が考慮されていないと、ベンチマークを複雑にしたり歪めたりする可能性があります。ジャストイン・タイム・コンパイ
ルは、オフロード・アプリケーションのデバッグに遅延を引き起こすことがあります。
OpenMP* オフロードプログラムでは、LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を設定すると、オフロードコード "ModuleBuild" のビルドに必要な時間が報告されます。これをプログラムの実行時間全体と比較します。
DPC++ オフロードプログラムでは、カーネルのセットアップ時間を判断するのはさらに困難になります。
•

レベルゼロがバックエンドである場合、ze_tracer によって返されるデバイスのタイミングとタイムラ
インからカーネルのセットアップ時間を求められます。

•

OpenCL* がバックエンドの場合、OpenCL* アプリケーションのインターセプト・レイヤーを使用して情報を取得する際に、BuildLogging、KernelInfoLogging、CallLogging、
CallLoggingElapsedTime、KernelInfoLogging、HostPerformanceTiming、
HostPerformanceTimeLogging、ChromeCallLogging、またはCallLoggingElapsedTime フラグを設定できます。

この方法により、LIBOMPTARGET_PLUGIN_PROFILE=T によって戻される情報を補足できます。

121

6
バッファーの作成、サイズ、およびコピーの監視
バッファーが作成された時期、作成されたバッファーの数、およびそれらが再利用されるか、また常に作成および破棄されるかを知ることは、オフロード・アプリケーションのパフォーマンスを最適化する上での重要な鍵となります。しかし、それらは OpenMP* や DPC++ などの高レベル・プログラミング言語を使用する場合は、必ずしも明確でない可能性がありユーザーからバッファーの管理は隠匿されます。
高レベルでは、プログラムの実行時に LIBOMPTARGET_DEBUG および SYCL_PI_TRACE 環境変数を
使 用 し て 、 バ ッ フ ァ ー に 関 連 す る ア ク テ ィ ビ テ ィ ー を 追 跡 で き ま す 。 LIBOMPTARGET_DEBUG は 、
SYCL_PI_TRACE よりも多くの情報を提供します（作成されたバッファーアドレスとサイズをレポート）。
SYCL_PI_TRACE は、API 呼び出しをレポートするだけであり、バッファーアドレスやサイズに関する情報は含まれません。
低レベルでは、レベルゼロのバックエンドを使用する場合、ze_tracer の呼び出しログモードは引数を含むすべてのレベルゼロ API 呼び出しに関する情報を提供します。例えば、バッファー作成呼び出し（zeMemAllocDevice など）で、デバイスとの間で渡される結果バッファーのサイズを取得できるため役立つことがあります。ze_tracer は、デバイス・タイムライン・モードですべてのレベルゼロデバイス間とのアクティビティー（メモリー転送を含む）をダンプすることができます。アクティビティーごとに、追加（コマンドリストへ）、送信（キューへ）、開始と終了時間を取得できます。
OpenCL* がバックエンドの場合、OpenCL* アプリケーションのインターセプト・レイヤーを使用する際に、CallLogging、CallLoggingElapsedTime、および ChromeCallLogging フラグを設定して同様の情報を取得できます。

合計転送時間合計データ転送時間をカーネル実行時間と比較することは、接続されているデバイスへの計算のオフロードが有益であるか判断することが重要になることがあります。
OpenMP* オフロードプログラムでは、LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を設定すると、ビルド（"DataAlloc"）、オフロードデバイスの読み取り（"DataRead"）、および書き込み（"DataWrite"）に必
要な時間がレポートされます（ただし合計として）。
DPC++ プログラムのデータ転送時間を判断するのはさらに困難になります。
•

レベルゼロがバックエンドである場合、ze_tracer によって返されるデバイスのタイミングとタイムラ
インからデータ転送時間を求められます。

•

OpenCL* がバックエンドの場合、OpenCL* アプリケーションのインターセプト・レイヤーを使用して情報を取得する際に、BuildLogging、KernelInfoLogging、CallLogging、
CallLoggingElapsedTime、KernelInfoLogging、HostPerformanceTiming、
HostPerformanceTimeLogging、ChromeCallLogging、またはCallLoggingElapsedTime フラグを設定できます。

122ソフトウェア開発プロセス
カーネル実行時間
OpenMP* オフロードプログラムでは、LIBOMPTARGET_PLUGIN_PROFILE=T[,usec] を設定すると、オフロードされたすべてのカーネル（"Kernel#..."）の合計実行時間が報告されます。
DPC++ オフロードプログラム向け：•

レベルゼロ・バックエンドでは、ze_tracer のデバイス・タイミング・モードを使用してすべてのカーネルのデバイスでの実行時間を取得できます。

•

OpenCL* がバックエンドの場合、OpenCL* アプリケーションのインターセプト・レイヤーを使用して情報を取得する際に、CallLoggingElapsedTime、DevicePerformanceTiming、
DevicePerformanceTimeKernelInfoTracking、
DevicePerformanceTimeLWSTracking、DevicePerformanceTimeGWSTracking、
ChromePerformanceTiming、ChromePerformanceTimingInStages フラグを設定できます。

デバイスカーネルが呼び出され、スレッドが生成される場合
場合によってには、オフロードカーネルが作成され、実行を開始するかなり前にデバイスへ転送されることがあります（通常は、カーネルの実行に必要なすべてのデータと制御が転送された後にのみ）。
インテル® ディストリビューション for GDB を使用してデバイスカーネルにブレークポイントを設定できます。そして、カーネル引数の照会、スレッドの生成と破棄の監視、現在のスレッドとコード内の位置のリスト表示（"info thread" を使用）などを行えます。

オフロード処理のデバッグ
異なるランタイムまたは計算デバイスで実行
オフロードプログラムが正常に実行されなかったか、生成された結果が正しくない場合、比較的容易な
正 当 性 の 確 認 方 法 は 、 OpenMP* ア プ リ ケ ー シ ョ ン で は LIBOMPTARGET_PLUGIN とOMP_TARGET_OFFLOAD 環境変数を、また DPC++ アプリケーションでは SYCL_DEVICE_FILTER 環
境変数を使用して、別のランタイム（OpenCL* とレベルゼロ）または計算デバイス（CPU と GPU）でアプ
リケーションを実行することです。異なるランタイム間で再現されるエラーは、ほとんどの場合、ランタイ
ムの問題として排除できます。そしてデバイス間で再現されるエラーの大部分は、不良ハードウェアの問題を排除できます。

CPU 実行をデバッグ
オフロードコードを CPU で実行するには、"ホスト" 実装と "OpenCL* の CPU バージョン" という 2 つのオプションがあります。"ホスト" 実装は、オフロードコードのネイティブ実装であり、オフロードされない
コードと同じようにデバッグできます。"OpenCL* の CPU バージョン" は、OpenCL* ランタイムとコード
123

6
生成プロセスを通過しますが、最終的にインテル® TBB ランタイムで実行される通常の並列コードになります。繰り返しますが、これにより慣れ親しんだアセンブリーと並列処理メカニズムのデバッグ環境が提供されます。ポインターはスタック全体をアクセスでき、データを直接参照できます。また、オペレー
ティング・システム・プロセスの通常の上限を超えるメモリー制限はありません。
CPU オフロード実行のエラーを検出して修正すると、GPU オフロード実行で発生するエラーよりもはる
かに少ない労力でエラーを解決でき、GPU や他のアクセラレーターが接続されたシステムを利用する必要もなくなります。
OpenMP* アプリケーションで "ホスト" 実装を適用するには、"target" または "device" 構造を削除して、通常のホスト OpenMP* コードに置き換えます。LIBOMPTARGET_PLUGIN=OPENCL が設定され、GPU オフロードが無効化されると、オフロードコードは OpenMP* ランタイムで実行され、インテル®
TBB が並列処理を行います。
DPC++ アプリケーションで SYCL_DEVICE_FILTER=host を設定すると "ホスト" デバイスはシングル
スレッドで実行を行います。これは、データ競合やデッドロックなどスレッド化の問題が実行エラーの原因であるか判断するのに役立ちます。SYCL_DEVICE_FILTER=opencl:cpu に設定すると、CPU の
OpenCL* ランタイムが使用され、インテル® TBB が並列処理を行います。

インテル® ディストリビューション for GDB を使用して GPU 実行をデバッグ
インテル® ディストリビューション for GDB については、「インテル® ディストリビューション for GDB 導入ガイド（Linux* 版）」（英語）または「インテル® ディストリビューション for GDB 導入ガイド（Windows*版）」（英語） に詳しく記載されています。ただし、GDB を使用して GPU アプリケーションをデバッグする
方法は、ホストでの手順とは若干異なるため（一部のコマンドの使い方が異なり、見慣れない出力が表示されることがあります）、それらの違いの一部をここで紹介します。
「インテル® ディストリビューション for GDB を使用したデバッグのチュートリアル（Linux* 版）」（英語）では、DPC++ プログラムのデバッグセッションを開始し、カーネル内にブレークポイントを設定し、プログラムを実行して 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, all threads are displayed.
Options:-gidShow global thread IDs.

124

ソフトウェア開発プロセス
GDB でインフェリアー、スレッド、および SIMD レーンの参照
アプリケーションのスレッドは、デバッガーによって一覧表示できます。表示される情報には、スレッド IDとスレッドが停止している位置が含まれます。GPU スレッドの場合、デバッガーはアクティブな SIMD
レーンも表示します。
上記の例では、GDB の "info threads" コマンドでスレッドを表示していますが、見慣れない形式で情報が示されることがあります。
Id
1.1

Target Id
Thread <id omitted>

Frame<frame omitted>

1.2

Thread <id omitted><frame omitted>

2.1

Thread 1610612736(inactive)* 2.2:1

Thread 1073741824<frame> at array-transform.cpp:61

2.2:[3 5 7]

Thread 1073741824<frame> at array-transform.cpp:61

2.3:[1 3 5 7]

Thread 1073741888<frame> at array-transform.cpp:61

2.4:[1 3 5 7]

Thread 1073742080<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 つの "ネイティブ" インフェリアー（上記のインフェリアー 1）と、GPU デバイスを示すもう 1つの "リモート" インフェリアー（上記のインフェリアー 2）です。インテル® ディストリビューション for GDB は自動的に GPU インフェリアーを生成するため、特に操作は必要ありません。
式の値を出力すると、式は現在のスレッドの現在の SIMD レーンのコンテキストで評価されます。
"thread 3:4 "、"thread :6 "、または "thread 7 " などの "thread" コマンドを使用して、スレッドとSIMD レーンを切り替えることができます。最初のコマンドは、スレッド3 と SIMD レーン 4 に切り替えます。2 番目のコマンドは、現在のスレッドで SIMD レーン 6 に切り替えます。3 番目のコマンドは、スレッド 7 に切り替えます。選択されるデフォルトレーンは、以前に選択したレーン（アクティブであれば）、またはスレッド内で最初にアクティブになったレーンのどちらかになります。
"thread apply コマンド" は、同様に広域または集中的である可能性があります（これにより、変数を調査するコマンドからの出力を制限しやすくなります）。SIMD レーンのデバッグの詳細と例については、「インテル® ディストリビューション for GDB を使用したデバッグのチュートリアル（Linux* 版）」（英語）を参照してください。

125

6
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（英語）
スケジューラーの制御
デフォルトでは、スレッドがブレークポイントに到達すると、デバッガーはブレーク・ポイント・ヒット・イベ
ントをユーザーに通知する前にすべてのスレッドを停止します。これは GDB のすべて停止モードです。非停止モードでは、他のスレッドが実行される間、スレッドの停止イベントが表示されます。
すべて停止モードでは、スレッドが再開されると（例：continue コマンドで通常のように再開する、または next コマンドでステップ実行する場合）、他のすべてのスレッドも再開されます。スレッド化されたア
プリケーションで複数のブレークポイントが設定されていると、ブレークポイントに到達した次のスレッ
ドが続くスレッドではない可能性があるため、混乱を招く可能性があります。
set scheduler-locking コマンドを使用することで、現在のスレッドが再開された時に他のスレッドが再開されないように制御することができます。これは、現在のスレッドのみが命令を実行している時に、他のスレッドの介入を避けるのに有効です。help set scheduler-locking と入力すると利用可能なオプションが表示されます。詳細は、 https://sourceware.org/gdb/current/onlinedocs/gdb/
Thread-Stops.html（英語）をご覧ください。SIMD レーンは個別に再開できないことに注意してください。
これは、ベースとなるスレッドと共に再開されます。
非停止モードのデフォルトでは、現在のスレッドのみが再開されます。すべてのスレッドを再開するには、
continue コマンドで "-a" フラグを指定します。
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 element126ソフトウェア開発プロセス
ブレークポイント停止後の GPU コードのステップ実行
GPU にオフロードされたカーネル内で停止するには、カーネル内のソース行にブレークポイントを設定するだけです。GPU スレッドがそのソース行に到達すると、デバッガーは実行を停止してブレークポイン
トの到達を示します。ソース行単位でスレッドをステップ実行するには、step または next コマンドを使用します。step コマンドは関数にステップインし、next コマンドは関数呼び出しをステップオーバーします。
ステップ実行する前に、他のスレッドの介入を避けるため set scheduler-locking step を設定することを推奨します。
インテル® ディストリビューション for GDB で使用する DPC++ 実行形式をビルド
ホスト・アプリケーションのデバッグと同様に、GPU でデバッグ可能なバイナリーを作成するには、いくつかの追加フラグを指定する必要があります。詳細については、「インテル® ディストリビューション for
GDB 導入ガイド（Linux* 版）」（英語）をご覧ください。
JIT コンパイルを行う際にスムーズなデバッグを可能にするには、-g フラグを指定してコンパイラーのデバッグ情報生成を有効にし、アプリケーションのホストと JIT コンパイルカーネルの両方で -O0 フラ
グを指定して最適化を無効にします。カーネルのフラグはリンク時に適用されます。次に例を示します。
•

次のコマンドでプログラムをコンパイル：dpcpp -g -O0 -c myprogram.cpp•

次のコマンドでプログラムをリンク：dpcpp -g -O0 myprogram.oCmake を使用してプログラムをビルドする場合、CMAKE_BUILD_TYPE の Debug タイプを使用し、CMAKE_CXX_FLAGS_DEBUG 変数に -O0 を追加します。次に例を示します。
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
デバッグ向けにビルドされたアプリケーションは、通常の「リリース」ビルドで最適化されたアプリケー
ションよりも起動に時間がかかる場合があります。そのため、デバッガーで起動すると、プログラムの実行速度が遅くなったように感じられることがあります。これにより問題が生じる場合、大規模なアプリケー
ションの開発者は、プログラムの実行時ではなくビルド時に JIT オフロードコードを事前（AOT）コンパ
イルすることを推奨します（これには、-g -O0 を使用するとビルドに時間がかかる場合があります）。
詳細については、「コンパイル手順の概要」をご覧ください。
GPU 向けの事前コンパイルを行う場合、ターゲットデバイスに対応したデバイスタイプを指定する必要があります。次のコマンドを使用して、現在のマシンで利用可能な GPU デバイスオプションを確認できます。
ocloc compile --help

127

6
さらに、カーネルのデバッグモードを有効にします。次の 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

インテル® ディストリビューション for GDB で使用する OpenMP* 実行形式をビルド
プログラムのコンパイルとリンクに -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-optdisable"

事前（AOT）コンパイルは現在 OpenMP* をサポートしていません。

オフロード・インターセプト・ツールを使用して GPU 実行をデバッグ
オフロードプログラムの一般的な問題は、実行に失敗することがありますが、追加情報をほとんど持たな
い OpenCL* エラーが生成されることです。OpenCL* アプリケーションのインターセプト・レイヤーと
ze_tracer を使用して、このエラーに関する詳細情報を取得できます。これは、開発者が問題の原因を特定するのに役立ちます。
OpenCL* アプリケーションのインターセプト・レイヤー
このライブラリーを使用する場合、 Buildlogging、 ErrorLogging 、 および USMChecking=1 オプ
ションを使用してエラーの原因を特定できます。

128

ソフトウェア開発プロセス
1.

2.

3.

次のテキストを含む clintercept.conf ファイルをホーム・ディレクトリーに作成します。
SimpleDump
ProgramSou
rce=1
CallLoggin
g=1
LogToFile=1//KernelNa
meHashTracking=1
BuildLoggi
ng=1
ErrorLoggi
ng=1
USMChecking=1
次のように cliloader を使用してアプリケーションを実行します。
//ContextCallbackLogging=1// Profiling knobs<OCL_Intercept_Install_Dir>/bin/cliloader/cliloader -d ./<app_name>
KernelInfoLogging=1<app_args>
DevicePerformanceTimi
ng=1
DevicePerformanceTime~CLIntercept_Dump/<app_name> ディレクトリーで次の結果を確認します。
LWSTracking=1
DevicePerformanceTime•
clintercept_report.txt：プロファイルの結果
GWSTracking=1• clintercept_log.txt：OpenCL* の問題をデバッグする際に使用される OpenCL* 呼び出

しログ
次のテキストは、CL_INVALID_ARG_VALUE (-50) ランタイムエラーが発生したプログラムで生成されたログファイルの例の一部です。
...
<<<< clSetKernelArgMemPointerINTEL -> CL_SUCCESS>>>>
clGetKernelInfo( _ZTSZZ10outer_coreiP5mesh_i16dpct_type_1c0e3516dpct_type_602
57cS2_S2_S2_S2_S2_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_1c0e35
16dpct_type_60257cS2_
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 nodevice support shared system pointers! ERROR!
clSetKernelArgMemPointerINTEL returned CL_INVALID_ARG_VALUE (-50)<<<< clSetKernelArgMemPointerINTEL -> CL_INVALID_ARG_VALUE

129

6
この例は、次の値がエラーのデバッグに役立ちます。
•

ZTSZZ10outer_coreiP5mesh•

index = 3, value = 0x41995e0

このデータによりどのカーネルに問題があるか、またどの引数に問題があるかが分かり、その理由を特定できます。
ze_tracer
OpenCL* アプリケーションのインターセプト・レイヤーと同様に、ze_tracer ツールはレベルゼロのラン
タイムエラーの原因を検出するのに役立ちます。
ze_tracer を使用するには次の操作を行います。
1.

呼び出しログモードでアプリケーションを実行します。ツールの出力をファイルにリダイレクトすることを推奨します。
./ze_tracer –c ./<app_name> <app_args> [2> log.txt]

2.

呼び出しトレースを確認してエラーを特定します（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)
...

130

ソフトウェア開発プロセス
この例のログには次のデータが示されています。
• 問題の原因となるレベルゼロ API 呼び出し（zeKernelSetArgumentValue）• 問題の原因（ZE_RESULT_ERROR_INVALID_ARGUMENT）• 引数インデックス（argIndex = 1）
• 不正な値の場所（pArgValue = 0x7fff865b5458）• カーネルハンドル（hKernel = 0x55a68c790280）、この問題が検出されたカーネル名を示します（GEMM）“ファイルへのリダイレクト” オプションを省略して、すべての出力（アプリケーションの出力 + ツールの出力）を 1 つのストリームにダンプすることで、より多くの情報を取得できます。単一のストリームにダンプを行うことで、アプリケーションの出力に関連するエラーの原因を特定するのに役立つことがあります（例えば、アプリケーションの初期化と計算の最初のフェーズでエラーが発生しているなどが分かります）。
Level Zero Matrix Multiplication (matrix size: 1024 x
1024, repeats 4 times) Target device: Intel(R) 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

131

6
正当性
オフロードコードは、接続された計算デバイスで大量の情報を効率良く処理するカーネル、または一部の入力パラメーターから大量の情報を生成する際に利用されます。それらのカーネルがクラッシュすることなく実行されると、多くの場合、正しい結果が得られていないことはプログラム実行のかなり後で判明します。
そのような場合、どのカーネルが誤った結果を生成しているか特定するのは困難です。誤った結果を生成するカーネルを特定する方法として、プログラムを 2 回実行することが考えられます。最初はホストベースの実装を実行し、2 回目はオフロード実装を実行してすべてのカーネル（多くは個々のファイル）の入力と出力を取得します。次に、結果を比較して、どのカーネルが予期しない結果を生成しているか確認します（特定のイプシロンで、オフロード・ハードウェアの操作順序やネイティブの精度の違いにより、結果の最後の 1 桁もしくは 2 桁がホストコードと異なる可能性があります）。
誤った結果を生成するカーネルを特定したら、インテル® ディストリビューション for GDB を使用して原因を調査します。基本情報と詳細なドキュメントへのリンクについては、「インテル® ディストリビューショ
ン for GDB を使用したデバッグのチュートリアル（Linux* 版）」（英語）を参照してください。
DPC++ と OpenMP* はどちらもオフロードされたカーネル内で標準の print メカニズム（DPC++ とC++ OpenMP* では printf、Fortran OpenMP* オフロードでは print * など）を利用できます。これを使用して、実行中の動作を確認できます。スレッドと SIMD レーンの出力をプリントし、同期メカニズ
ムを追加して、プリントされた情報がプリント時に一貫性を持つようになることを検討してください。スト
リームクラスを使用した DPC++ で同様のことを行う例は、『oneAPI GPU 最適化ガイド』に記載されています。OpenMP* オフロード向けの DPC++ の説明を同様のアプローチを適用できます。
ヒント：DPC++ カーネルでは 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);

132

ソフトウェア開発プロセス
障害
DPC++ または OpenMP* オフロード言語の誤った用法が原因で JIT コンパイルが失敗すると、プログ
ラムはエラーで終了します。
DPC++ では 事前コンパイルされていることを判定できない場合、OpenCL* バックエンドを選択してOpenCL* アプリケーションのインターセプト・レイヤーを使用すると、構文エラーを持つカーネルを特定できることがあります。
ロジックエラーは、クラッシュや実行中のエラーメッセージを引き起こす場合があります。これには以下が含まれます。
•

誤ったコンテキストに属するバッファーをカーネルに渡す場合•"this" ポインターをクラス要素ではなくカーネルに渡す場合•

デバイスバッファーではなくホストバッファーを渡す場合•

カーネルで使用されなくても、初期化されていないポインターを渡す場合

インテル® ディストリビューション for GDB（またはネイティブ GDB）を使用して注意深く調査することで、生成されたすべてのコンテキストのアドレスを記録してオフロードカーネルに渡されるアドレスが正しい
コンテキストに属するか確認できます。同様に、変数のアドレスがそれを含むクラスでなく、変数自身のア
ドレスと一致するか確認できます。
OpenCL* 割り当て用のインターセプト・レイヤーまたは、ze_tracer を使用して、適切なバックエンドを選択する方がバッファーとアドレスをトレースするよりも簡単なことがあります。OpenCL* バックエンドを使用する場合、CallLogging、BuildLogging、ErrorLogging、および USMChecking を設定してプログラムを実行すると、コード内のどのエラーが OpenCL* エラーを生成したか明らかにする出力が生成されます。ze_tracer の呼び出しログやデバイス・タイムラインを参照すると、レベルゼロのバックエン
ドからのエラーの原因を理解するのに役だつ追加のエラー情報が得られます。これは、上記の論理エラーを検出するのに役立ちます。
レベルゼロ・バックエンドを使用してデバイスにオフロードする際にコードでエラーが発生する場合、OpenCL* バックエンドを試してみてください。プログラムが正常に機能する場合、レベルゼロ・バックエ
ンドにエラーをレポートしてください。デバイス向けの OpenCL* バックエンドでもエラーが再現する場
合、OpenCL* CPU バックエンドを試します。OpenMP* オフロードでは、OMP_TARGET_OFFLOAD を
CPU に設定することで指定できます。DPC++ では、SYCL_DEVICE_FILTER=opencl:cpu を設定します。CPU 上でのデバッグはかなり容易になり、データのコピーとプログラムのデバイスへの変換によって生じる複雑性も排除できます。
問題が発生する可能性があるロジックの例として、次の DPC++ コードで parallel_for を実装する際に使用されるラムダ関数でキャプチャーされる対象を考えます。

133

6class 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<classkernel_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 を使用します。"autofactor2 = factor" は "int factor2 = this->factor" になるため、ラムダ内で [=] を指定して factor2 を使用すると、"int" が取得されます。内部セクションを "kernel(data2, b, factor2,
LEN, item_ct1);" に変更します。
注：この問題は、CUDA* カーネルを移行する際によく発生します。同じ CUDA* カーネルの起動シグネ
チャーを保持し、コマンドグループとラムダをカーネル内に配置することで問題を解決することもできます。
OpenCL* 割り当てのインターセプト・レイヤーや ze_tracer を使用すると、カーネルが 2 つの同一アドレ
スで呼び出されることが分かり、拡張エラー情報を見ると、重要なデータ構造をオフロードデバイスにコピーしようとしていることが確認できます。
統合共有メモリー（USM）を使用しており、"MyClass" が USM に割り当てられる場合、上記のコードが動作することに注意してください。ただし、USM に "data" のみが割り当てられている場合、前述の理由からプログラムはクラッシュします。

134

ソフトウェア開発プロセス
この例では、カーネル呼び出しですべての変更する必要がないことから、ローカルスコープ内で同じ名前の変数を再宣言できることも留意してください。
インテル® Inspector は、このような障害の診断に役立ちます。次の環境変数を設定して、CPU デバイス
でオフロードコードのメモリー解析を実行すると、インテル® Inspector は上記の問題の多くを通知しま
す。
•

•

•

OpenMP*•

export OMP_TARGET_OFFLOAD=CPU•

export OMP_TARGET_OFFLOAD=MANDATORY•

export LIBOMPTARGET_PLUGIN=OPENCL

DPC++
•

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 -O[最適化レベル] を指定します。詳細については、『インテル® oneAPI DPC++/C++ コンパイラー・デベロッパー・ガイドおよびリファレンス』を参照してください。

オフロードのパフォーマンスを最適化
オフロード・パフォーマンスの最適化は、3 つのタスクに要約できます。
1.
2.
3.

デバイス上のカーネルの実行時間を最大化しつつ、デバイス間とのデータ転送回数とサイズを最小化します。
可能であれば、デバイス上の計算とデバイスとのデータ転送をオーバーラップさせます。
デバイス上のカーネルのパフォーマンスを最大化します。

OpenMP* オフロードと DPC++ の両方でデータ転送を明示的に制御することができますが、これを自動的に行うこともできます。また、ホストとオフロードデバイスはほとんど非同期に動作するため、データ転送を制御しようとしても転送が期待通りに行われず、予想よりも時間を要することがあります。デバイスとホストの両方でアクセスされるデータが統合共有メモリー（USM）に格納されている場合、パフォーマ
ンスに影響する透過的な別のレイヤーのデータ転送が行われる可能性があります。

135

6
リソース：
•

インテル® oneAPI GPU 最適化ガイド•

インテル® oneAPI FPGA 最適化ガイド（英語）バッファー転送時間と実行時間
オフロードデバイス間とのデータ転送には比較的コストがかかり、ユーザー空間でのメモリー割り当て、システムコール、およびハードウェア・コントローラーとのインターフェイスが必要になります。統合共有
メモリー（USM）は、ホストまたはオフロードデバイスのいずれかのメモリーの更新を同期するバックグラ
ウンド・プロセスによるコストがかかります。さらに、オフロードデバイス上のカーネルは、実行に必要なすべての入力および出力バッファーがセットアップされて利用可能になるまで待機する必要があります。
1 回のデータ転送でオフロードデバイスとやり取りする情報量に関わりなく、このオーバーヘッドのコストはほぼ同じです。そのため、1 回に 1 つずつではなく、10 回分の転送をまとめて行うほうがはるかに高効率です。いずれにしても、すべてのデータ転送にはコストが生じるため、転送の総数を最小限にすることが重要です。例えば、複数のカーネルまたは同じカーネルの複数の呼び出しで必要とする定数がある場合、それらはカーネルを呼び出すたびに送信するのではなく、一度オフロードデバイスに転送して再利用する
ようにします。単一の大量のデータ転送には、単一の少量のデータ転送よりも時間がかかります。
送信されるバッファーの数とサイズは式の一部にすぎません。データがオフロードデバイスに到達したら、カーネルが実行される時間を検討します。オフロードデバイスへのデータ転送よりも実行時間が短い場
合、同一操作をホストで実行する時間が、カーネルの実行とデータ転送の合計時間よりも長くない限り、オフロードのメリットはありません。
最後に、あるカーネルの実行と次のカーネルの実行の間に、オフロードデバイスがアイドル状態になっている時間を調査します。長い待機時間は、データ転送やホスト上のアルゴリズムの特性が原因である可能性があります。前者は、データ転送とカーネル実行のオーバーラップを試す価値があります。
ホストでのコード実行、オフロードデバイスでのコード実行、およびデータ転送の関係は複雑です。これらの順番と時間は、単純なコードであっても直感的に理解できるものではありません。すべてのアクティビ
ティーを視覚的に理解し、その情報を参考にしてオフロードコードを最適化するには、次のようなツールが必要になります。

インテル® VTune™ プロファイラー
インテル® VTune™ プロファイラーは、ホスト上の詳しいパフォーマンス情報を提供するだけでなく、接続された GPU のパフォーマンスに関する詳細情報も提供できます。GPU 向けの設定に関する情報は、『インテル® VTune™ プロファイラー・ユーザーガイド』をご覧ください。
インテル® VTune™ プロファイラーの GPU オフロードビューには、それぞれのカーネル間とのデータ転送に費やされた時間など、GPU 上のホットスポットに関するサマリーが表示されます。GPU 計算/メディ136

ソフトウェア開発プロセス
ア・ホットスポット・ビューでは、動的命令カウントを使用して GPU カーネルのパフォーマンスのマイクロ解析など、GPU カーネルで何が起こっているか詳しく調査することができます。これらのプロファイル・
モードでは、データ転送と計算が時間経過でどのように変化するか観察したり、カーネルを効率良く実行するのに十分なワークがあるか判断したり、カーネルが GPU メモリー階層をどのように利用するか調べたりできます。
これらの解析タイプの詳細については、『インテル® VTune™ プロファイラー・ユーザーガイド』を参照してください。インテル® VTune™ プロファイラーを使用した GPU の最適化に関する詳細は、「インテル®
VTune™ プロファイラーでインテル® GPU 向けのアプリケーションの最適化」（英語）をご覧ください。
カーネルの実行時間を計測するには、インテル® VTune™ プロファイラーも使用できます。次のコマンドは、軽量プロファイルの結果を示します。
•

Collect•

レベルゼロ・バックエンド：
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 -app-working-dir <app_working_dir> – <app>

•

レポート：
vtune --report hotspots --group-by=source-computing-task--sort-desc="Total Time" -r vtune-test

インテル® Advisor
インテル® Advisor は、計算を GPU にオフロードするパフォーマンスを向上させるのに役立つ 2 つの機能を提供します。
•

オフロードのモデル化は、ホストの OpenMP* プログラムを調査して、GPU へのオフロードに適した
コード領域を示します。また、さまざまな異なるターゲット向けに GPU をモデル化できるため、ターゲットに適したオフロードコード領域を特定できます。オフロード・アドバイザーは、オフロードのパフォーマンスを制限する可能性がある要因に関する詳細情報を提供します。

•

GPU ルーフライン解析は、GPU で実行されるアプリケーションを監視し、各カーネルが GPU のメモ
リー・サブシステムと計算ユニットをどの程度効率良く使用しているか視覚的に示します。これにより、カーネルが GPU にどれくらい最適化されているか知ることができます。

すでにオフロードを実装するアプリケーションでこのモードを使用するには、CPU 上の OpenCL* デバイ
スを解析ターゲットにするよう環境を設定する必要があります。手順は、『インテル® Advisor ユーザーズ
ガイド』（英語）をご覧ください。

137

6
オフロードのモデル化では、GPU を使用するようにアプリケーションを変更する必要はありません。ホス
トコードで完全に機能します。
リソース：•

インテル® Advisor クックブック：GPU オフロード•

オフロードのモデル化入門（英語）•GPU* ルーフライン入門（英語）OpenCL* アプリケーションのタイムライン向けの ze_tracer とインターセプト・レイヤー
インテル® VTune™ プロファイラーを使用して、データが GPU にコピーされるタイミング、およびカーネルが実行されるタイミングを調査したくない（またはできない）場合、ze_tracer と OpenCL* アプリケー
ションのインターセプト・レイヤーでもこの情報を監視する方法が用意されています（ただし視覚的なランタイム情報が必要な場合は、出力を視覚化するスクリプトを用意する必要があります）。詳細について
は「トレースとオフロードの手順」をご覧ください。

パフォーマンス・チューニング・サイクル
パフォーマンス・チューニング・サイクルの目標は、対話型の応答時間やバッチジョブの経過時間など、問題解決までの時間を短縮することです。ヘテロジニアス・プラットフォームの場合、ホストと独立して実行されるデバイスで利用可能な計算サイクルがあります。これらのリソースを利用してパフォーマンスを向上させます。
パフォーマンス・チューニング・サイクルには、次のステップがあります。
1.
2.
3.
4.
5.

ベースラインの確定
オフロードするカーネルの特定カーネルのオフロード
最適化
目標を達成するまで繰り返す

ベースラインの確定
経過時間、計算カーネル時間、1 秒あたりの浮動小数点演算などのメトリックを含むベースラインを確定します。これは、パフォーマンス向上の測定だけでなく、結果の正当性を検証する手段としても利用できます。

138ソフトウェア開発プロセス
ベースラインを確定する簡単な方法は、C++ のタイム・ライブラリー・ルーチンを使用して、ワークロードの実行前後でタイマー呼び出しを行うことです。

オフロードするカーネルの特定
ヘテロジニアス・プラットフォームのデバイスで利用可能な計算サイクルを最大限に活用するには、計算集約型で並列実行可能なタスクを特定することが重要です。CPU のみで実行されるアプリケーションを調査すると、GPU で実行するのに適したタスクが見つかることがあります。これは、インテル® Advisor（英語）のオフロードのモデル化機能で判別できます。
インテル® Advisor は、アクセラレーターで実行される可能性があるワークロードのパフォーマンス特性を推測できます。ワークロードのプロファイル情報から、パフォーマンスを見積もり、ボトルネックの特性を評価して、さらにオフロードデータ転送を推測します。
一般に、計算主体で、大規模なデータセットを持ち、限られたデータ転送を行うカーネルは、デバイスへのオフロードに適しています。
機能の説明については、『インテル® Advisor ユーザーズガイド』をご覧ください。

カーネルをオフロード
オフロードに適したカーネルを特定したら、DPC++ を使用してカーネルをデバイスにオフロードします。
詳細は以前の章をご覧ください。

最適化
oneAPI は、複数のアクセラレーターで実行できるコードを生成します。ただし、コードはすべてのアクセ
ラレーターでは最適ではない可能性があります。パフォーマンスの目標を達成するには 3 段階の最適化を行うことを推奨します。
1.
2.
3.

アクセラレーター全体に適用される一般的な最適化を行います。
優先するアクセラレーターに対して積極的に最適化を行います。
ステップ 1 と 2 を組み合わせてホストコードを最適化します。

最適化とは、ボトルネック（ほかのコードセクションに比べて実行時間が長いコード領域）を排除する作業です。これらのセクションは、デバイスまたはホストで実行できます。最適化では、インテル® VTune™
プロファイラーなどのプロファイル・ツールを使用して、コード内のボトルネックを特定します。
ここでは、最初のステップであるアクセラレーター全体に適用される一般的な最適化を検討します。デバ
イス固有の最適化、デバイス固有のベスト・プラクティス（ステップ 2）、およびホストとデバイス間の最適139

6化（ステップ 3 ）については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』（英語）などのデバイス固有の最適化ガイドで詳しく説明されています。このセクションでは、アクセラレーターにオフロードするカーネルがすでに決定されていること、および単独のアクセラレーターでワークが完了することを想定しています。このガイドは、ホストとアクセラレーター間、またはホストと複数の/異なるアクセラレーター間のワークの分割については考慮していません。
アクセラレーター全体に適用される一般的な最適化は次の 4 つに分類されます。
1.
2.
3.
4.

高レベルの最適化
ループ関連の最適化
メモリー関連の最適化
DPC++ 固有の最適化

次のセクションでは上記の最適化のみをカバーします。これらの最適化を実際にコードに反映する方法の詳細は、オンラインや一般に入手できるコード最適化関連の資料で見付けることができます。ここでは、
DPC++ 固有の最適化に関する詳細を示します。

高レベルの最適化•

並列ワークの量を増やします。処理要素を十分に活用するには、処理要素よりも多くのワークが必要です。

•

カーネルのコードサイズを最小化します。これにより、アクセラレーターの命令キャッシュにカーネルが保持されます。

•

カーネルのロードバランスを取ります。実行時間の長いカーネルはボトルネックとなり、ほかのカーネルのスループットに影響する可能性があるため、カーネル間の実行時間は大きく異ならないようにします。

•

高コストの関数は避けてください。実行時間が長い関数は、ボトルネックとなる可能性があるため呼び出さないでください。

ループ関連の最適化•

適切に構造化および構成された、単純な終了条件のループを使用します。単純な終了条件のループとは、出口が 1 つであり、整数上限値との比較で単一の終了条件を持つループです。

•

線形インデックスと定数上限値を持つループを優先します。例えば、配列への整数インデックスを使用し、コンパイル時に上限値が判明しているループなどです。

•

可能な限り深いスコープで変数を宣言します。これにより、メモリーまたはスタックの使用量を軽減できます。

•

ループ伝搬されるデータの依存関係を最小化または緩和します。ループ伝搬の依存関係により、並列化が制限されることがあります。可能な限り依存関係を排除します。排除できない場合は、依存関係の距離を最大化するか、依存関係をローカルメモリー内に留めます。

140

ソフトウェア開発プロセス•

pragma unroll でループをアンロールします。

メモリー関連の最適化•

可能な限り、メモリー使用よりも計算を優先します。メモリーのレイテンシーと帯域幅のほうが計算よりもボトルネックになる可能性があります。

•

可能であれば、グローバルメモリーよりもローカルおよびプライベート・メモリーを使用します。

•

ポインターのエイリアシングを避けます。

•

メモリーアクセスを結合します。メモリーアクセスをグループ化して個々のメモリー要求の数を減らし、
キャッシュラインの利用率を高めます。

•

可能であれば、頻繁に実行されるコード領域の変数と配列をプライベート・メモリーに保持します。

•

同時メモリーアクセスに対するループアンロールの影響に注意してください。

•

別のカーネルが読み取るグローバルメモリーへの書き込みを避けます。代わりにパイプを使用します。

•

カーネルに [[intel::kernel_args_restrict]] 属性を適用することを検討してください。この属性により、コンパイラーは DPC++ カーネルのアクセサー引数間の依存関係を無視できます。アクセサー引数の依存関係を無視すると、コンパイラーはさらに積極的な最適化を行い、カーネルのパ
フォーマンスが向上する可能性があります。

DPC++ 固有の最適化•

可能であれば、work-group サイズを指定します。属性 [[cl::reqd_work_group_size(X, Y,Z)]]（X、Y、Z は ND-range の整数次元）を使用して、work-group のサイズを設定できます。コンパ
イラーはこの情報を利用して積極的な最適化を行うことができます。

•

可能であれば、-Xsfp-relaxed オプションの使用を検討してください。このオプションは、算術浮動小数点演算の順序付けを緩和します。

•

可能であれば、-Xsfpc オプションの使用を検討してください。このオプションは、可能な場合は常に中間の浮動小数点丸め操作と変換を排除して、精度を維持するため追加ビットをキャリーします。

•-Xsno-accessor-aliasing オプションの使用を検討してください。このオプションは、SYCL*
カーネルのアクセサー引数間の依存関係を無視します。

再コンパイル、実行、プロファイル、そして繰り返し
コードを最適化したら、パフォーマンスを測定することが重要です。次を確認します。
•

メトリックは改善されましたか?

•

パフォーマンスの目標は達成できましたか?

141

6
•

利用可能な計算サイクルが残されていますか?

結果の正当性を確認します。数値結果を比較すると、コンパイラーの最適化やコード変更により異なる場
合があります。差異は許容範囲内ですか? そうでなければ、最適化ステップに戻ります。

oneAPI ライブラリーの互換性
oneAPI アプリケーションには、インテルのツールのリリースバージョンとの互換性のため、動的ライブラリーが実行時に含まれる場合があります。インテル® oneAPI ツールキットとコンポーネント製品は、互換性を維持するためセマンティック・バージョニングを使用します。
次のポリシーが、インテル® oneAPI ツールキットで提供される API および ABI に適用されます。
注：oneAPI アプリケーションは、64 ビットのターゲットデバイスでサポートされます。
•

新しいインテル® oneAPI デバイスドライバー、インテル® oneAPI 動的ライブラリー、およびインテル® oneAPI コンパイラーは、インテル® oneAPI ツールを使用してビルドされた展開済みのアプリ
ケーションを破壊することはありません。現在の API は、通知とメジャーバージョンの重複なしで削除
または変更されることはありません。

•

oneAPI アプリケーションの開発者は、ヘッダーファイルとライブラリーのリリースバージョンが同じであることを確認する必要があります。例えば、アプリケーションで、インテル® oneAPI マス・カーネ
ル・ライブラリー 2021.2 のヘッダーファイルをインテル® oneAPI マス・カーネル・ライブラリー
2021.1 で使用してはなりません。

•

インテル® コンパイラーで提供される新しい動的ライブラリーは、古いバージョンのコンパイラーで作成されたアプリケーションでも動作します（これは一般に下位互換と呼ばれます）。しかし、その逆は当てはまりません。インテル® oneAPI 動的ライブラリーの新しいバージョンには、以前のバージョンでは提供されていないルーチンが含まれる場合があります。

•

oneAPI 対応のインテル® コンパイラーで提供される古い動的ライブラリーは、新しいバージョンのoneAPI コンパイラーでは機能しません。

oneAPI アプリケーションの開発者は、oneAPI アプリケーションが互換性のあるインテル® oneAPI ライ
ブラリーとともに展開されていることを確認するため、完全なアプリケーションのテストを実施する必要があります。

142

用語集
アクセラレーター（Accelerator)
操作のサブセットを迅速に実行する計算リソースを含む専用コンポーネント。
例：CPU、GPU、または FPGA。
参照：デバイス

アクセサー（Accessor)
アクセスする場所（ホスト、デバイス）とモード（read、write）を通信します。

アプリケーション・スコープ（Application Scope)
ホスト上で実行されるコード。

バッファー（Buffers)
計算を行うためデバイスに送られる項目の数や型を通信するメモリー・オブジェクト。

コマンド・グループ・スコープ（Command Group Scope)
ホストとデバイス間のインターフェイスとして動作するコード。

コマンドキュー（Command Queue)
コマンドグループを同時に発行します。

計算ユニット（Compute Unit)
処理要素間で使用する共有要素を含み、デバイス上のほかの計算ユニットにあるメモリーよりも高速にアクセスするため、処理要素を「コア」にグループ化したもの。

デバイス（Device)
操作のサブセットを迅速に実行する計算リソースを含むアクセラレーターまたは専用コンポーネント。
CPU はデバイスとして利用できますが、その場合、 CPU はアクセラレーターとして使用されます。
例：CPU、GPU、または FPGA。

143

参照：アクセラレーター

デバイスコード（Device Code)
ホストではなくデバイスで実行されるコード。デバイスコードは、ラムダ式、ファンクター、またはカーネル
クラスを介して指定されます。

ファットバイナリー（Fat Binary)
複数デバイス向けのデバイスコードを含むアプリケーション・バイナリー。バイナリーには、汎用コード（SPIR-V* 形式）とターゲット固有の実行可能コードの両方が含まれます。

ファット・ライブラリー（Fat Library)
複数デバイス向けのオブジェクト・コードを含むアーカイブまたはライブラリー。ファット・ライブラリーには、汎用オブジェクト（SPIR-V* 形式）とターゲット固有のオブジェクト・コードの両方が含まれます。

ファット・オブジェクト（Fat Object)
複数デバイス向けのオブジェクト・コードを含むファイル。ファット・オブジェクトには、汎用オブジェクト（SPIR-V* 形式）とターゲット固有のオブジェクト・コードの両方が含まれます。

ホスト（Host)
プログラムの主要部分、具体的にはアプリケーション・スコープとコマンド・グループ・スコープを実行する CPU ベースのシステム（コンピューター）。

ホストコード（Host Code)
ホスト・コンパイラーによってコンパイルされ、デバイスではなくホストで実行されるコード。

イメージ（Images)
組込み関数を介してアクセスされるフォーマット済みのあいまいなメモリー・オブジェクト。通常、RGB な
どの形式で保存されピクセルで構成される画像に関係します。

カーネルスコープ（Kernel Scope)
デバイス上で実行されるコード。

144

用語集
ND-range
1 次元、2 次元、または 3 次元の N 次元レンジ、カーネル・インスタンスのグループ、またはワーク項目の略。

処理要素（Processing Element)
計算ユニットを構成する計算向けの個別のエンジン。

単一ソース（Single Source)
ホストとアクセラレーターで実行できる同じファイルのコード。

SPIR-V*
グラフィカル・シェーダー・ステージと計算カーネルを表現するバイナリー中間言語。

サブグループ（Sub-group)
サブグループはインテルによる拡張です。

ワークグループ（Work-group)
計算ユニットで実行するワーク項目の集合。

ワーク項目（Work-item)
oneAPI プログラミング・モデルにおける計算の基本単位。処理要素で実行されるカーネルに関連付けられます。

145