データ並列 c++ (インテル® oneapi dpc++) の紹介
TRANSCRIPT
Mike Kinsner
インテル コーポレーションソフトウェア・エンジニア
Khronos* SYCL* および OpenCL* ワーキンググループのメンバー
データ並列 C++ (インテル® oneAPI DPC++) の紹介標準ベースのクロスアーキテクチャープログラミング言語
目的
データ並列 C++、コードの構造、およびコードをすぐに記述するための主要概念を紹介
トピック
1. データ並列 C++ とは?
2. プログラミング構造と実行モデル
3. コードのコンパイル
4. キューとデバイスの選択
5. データとタスクグラフの管理
6. インテルによる DPC++ の拡張
プログラミング課題
データセントリックのハードウェアの多様性
共通のプログラミング言語や API はありません
プラットフォーム間でのツールサポートの一貫性がありません
それぞれのプラットフォームには個別のソフトウェア投資が必要です
FPGAAIGPUCPU
いくつかの機能はアーキテクチャーごとに異なります
AI(将来)
FPGAGPUCPU
最適化されたアプリケーション
最適化されたミドルウェアとフレームワーク
インテル® oneAPI 製品
ダイレクト・プログラミング
データ並列 C++
API ベースのプログラミング
ライブラリー
解析、デバッグツール
インテル® oneAPI はクロスアーキテクチャー向けのパフォーマンスをもたらします
すぐに動作します、 そして解析とチューニングを行います
データ並列 C++
= 標準化された C++ と SYCL* および インテルによる拡張
C++ ベース
▪C++ の生産性の利点と慣れ親しんだ構文
標準化ベースのクロスアーキテクチャー
▪データ並列処理とヘテロジニアス・プログラミング向けに SYCL* 標準を取り入れています
データ並列 C++ ⇔ DPC++
データ並列 C++ とは?
Khronos は登録商法であり、SYCL は Khronos Group, Inc の商標です。
生産性の向上
• シンプルなものはシンプルに表現する必要があります
• 冗長性とプログラマーの負担を軽減します
パフォーマンスの向上
• プログラマーがプログラムの実行を制御できるようにします
• ハードウェア固有の機能を有効にします
DPC++: SYCL* 規格への迅速でオープンな実装
• 上流の LLVM を目標とするオープンソース実装
• DPC++ 拡張は、SYCL* コアや Khronos* 拡張に取り入れられることを目的としています
DPC++ は SYCL* 1.2.1 を拡張
完全な DPC++ プログラム#include <CL/sycl.hpp>#include <iostream>constexpr int num=16;using namespace cl::sycl;
int main() {auto R = range<1>{ num };buffer<int> A{ R };
queue{}.submit([&](handler& h) {auto out =A.get_access<access::mode::write>(h);
h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
auto result =A.get_access<access::mode::read>();
for (int i=0; i<num; ++i)std::cout << result[i] << "¥n";
return 0;}
単一ソース
• ホストコードとヘテロジニアス・アクセラレーター向けのカーネルを混在して同一ソースファイルに記述できます
C++ のように利用できます
• ライブラリー構造は、次のような機能を追加します
ホストコード
アクセラレーター・デバイス・コード
ホストコード
構造 目的
キュー ターゲットでのワーク
バッファー データ管理
parallel_for 並列処理
インテル® DPC++ コンパイラーを使用
• dpcpp -fsycl-unnamed-lambda my_source.cpp –o executable
コンパイラーを入手
DPC++ プログラムのコンパイル
oneAPI 向けのインテル® DevCloud
(software.intel.com/devcloud/oneAPI (英語)) でインテル® oneAPI を使用して、さまざまなインテルの
データセントリックなアーキテクチャーでコードとワークロードをテストできます
関連情報とダウンロードインテル® oneAPI ツールキットは、software.intel.com/oneapi (英語)
からダウンロードできます
ワークロードの評価
ヘテロジニアス・アプリケーションのビルド
インテル® oneAPI ツールキットを学習
データ並列 C++ を学習
プロジェクトのプロトタイプを作成
ダウンロード不要 | ハードウェア不要 | インストール不要 | セットアップと設定不要
わずかな時間で起動および実行できます!!
インテル® oneAPI ツールキットを使用して、さまざまなインテルの CPU、GPU、FPGA でワークロードを開発、テスト、および実行する開発向けのサンドボックス
インテル® oneAPI を使用する
インテル® DevCloud
software.intel.com/en-us/devcloud/oneapi (英語)
アクセラレーター・デバイスで実行するワークを定義
#include <CL/sycl.hpp>#include <iostream>constexpr int num=16;using namespace cl::sycl;
int main() {auto R = range<1>{ num };buffer<int> A{ R };
queue{}.submit([&](handler& h) {auto out = A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
auto result = A.get_access<access::mode::read>();for (int i=0; i<num; ++i)std::cout << result[i] << "¥n";
return 0;}
次の方法でカーネルを指定できます:
• C++ ラムダ式
• 関数を呼び出す軽量のラッパー
• ファンクター・オブジェクト
• 相互運用
カーネルはキューに送信されます:
• parallel_for
• single_task
• parallel_for_work_group
カーネルのラムダ式定義
カーネルベースのモデル#include <CL/sycl.hpp>#include <iostream>constexpr int num=16;using namespace cl::sycl;
int main() {auto R = range<1>{ num };buffer<int> A{ R };
queue{}.submit([&](handler& h) {auto out =A.get_access<access::mode::write>(h);
h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
auto result =A.get_access<access::mode::read>();
for (int i=0; i<num; ++i)std::cout << result[i] << "¥n";
return 0;}
カーネル
• アクセラレーターで実行されるコード(通常、カーネル呼び出しごとに (ND-range 全体で) 繰り返し呼び出されるインスタンス)
カーネルはコード中で明確に識別できます
• 少数のクラスでカーネルを定義できます (例: parallel_for)
開発者はカーネルを実行する位置を指定します
• 各種レベルの制御
カーネルの定義
データ並列処理は ND-range を使用して表現されます
• 合計ワーク = Work-group 数 x Work-group ごとの Work-item 数
• ボトムアップ、階層型の単一プログラム複数データ (SPMD) モデル
カーネルの実行モデル
ND-range の次元 2
ND-range の次元 1
ND-range の次元 0
work-item (4,4,4) の work-group
ND-range
sub-group の次元 0
Sub-group Work-itemWork-group
4 つの work-item の sub-group
work-group の次元 2
work-group の次元 1
work-group の次元 0
単一の work-item の視点からコードを記述
集合関数により、work-item 間の操作を表現可能 (バリアなど)
ワークはキューへ送信されます
• 各キューは、厳密に 1 つのデバイスに関連付けられます (例: GPU または FPGA)
• 次を行うことができます:
• キューに関連付けられているデバイスを特定 (必要であれば)
• ヘテロジニアス・システムでは、ワークをディスパッチする複数のキューを作成
デバイスカーネルを実行する場所を選択
対象のデバイス向けのキューを作成 queue();
事前構成されているデバイスクラスをターゲットとするキューを作成
queue(cpu_selector{});
queue(gpu_selector{});
queue(intel::fpga_selector{});
queue(accelerator_selector{});
queue(host_selector{});
特定のデバイスをターゲットとするキューを作成 (特殊用途):
class custom_selector : public
device_selector {
int operator()(…… // ロジックを記述 !…
queue(custom_selector{});
Queue_A
Queue_B
Queue_C
GPU
FPGA
常に利用可能
自動でデータと制御の依存関係を解決します
カーネル実行のグラフ
プログラムの完了
A
A
B
A
B
int main() {auto R = range<1>{ num };buffer<int> A{ R }, B{ R };queue Q;
Q.submit([&](handler& h) {auto out = A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
Q.submit([&](handler& h) {auto out = A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
Q.submit([&](handler& h) {auto out = B.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
Q.submit([&](handler& h) {auto in = A.get_access<access::mode::read>(h);auto inout =B.get_access<access::mode::read_write>(h);
h.parallel_for(R, [=](id<1> idx) {inout[idx] *= in[idx]; }); });
}
カーネル 1
カーネル 3
カーネル 2
カーネル 4
= データ依存関係
カーネル 1
カーネル 2
カーネル 3
カーネル 4
バッファー: SYCL* アプリケーションでデータをカプセル化
• デバイスとホスト間の両方で
アクセサー: バッファーのデータにアクセスするメカニズム
• カーネルの実行を順序付けるSYCL* グラフでデータの依存関係を作成
バッファーモデル
int main() {auto R = range<1>{ num };buffer<int> A{ R }, B{ R };queue Q;
Q.submit([&](handler& h) {auto out =
A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {
out[idx] = idx[0]; }); });
Q.submit([&](handler& h) {auto out =
A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {
out[idx] = idx[0]; }); });…
A
AB
A
Bカーネル1
カーネル3
カーネル2
カーネル4
バッファー
バッファーへのアクセサー
SYCL* アプリケーションは 2 つのパートで構成されます
1. ホストコード
2. カーネル実行のグラフ
同期操作を除きこれらは独立して実行されます
• ホストコードはグラフを作成するためワーク (計算を行う) を送信します
• カーネル実行とデータ移動のグラフは、SYCL* ランタイムで管理されるホストコードとは非同期に実行されます
非同期実行
#include <CL/sycl.hpp>#include <iostream>constexpr int num=16;using namespace cl::sycl;
int main() {auto R = range<1>{ num };buffer<int> A{ R };
queue{}.submit([&](handler& h) {auto out = A.get_access<access::mode::write>(h);h.parallel_for(R, [=](id<1> idx) {out[idx] = idx[0]; }); });
auto result = A.get_access<access::mode::read>();for (int i=0; i<num; ++i)std::cout << result[i] << "¥n";
return 0;}
ホストコードの実行
カーネルをキューに投入してグラフ化し処理を続行します
カーネル
A
A
グラフはホスト・プログラムとは非同期に実行されます
ホスト グラフ
非同期実行 (続き)
注意:
DPC++ = ISO C++ と SYCL* 標準 および 拡張機能
SYCL* 上の DPC++ 拡張機能
次の機能を見ていきます
1. 統合共有メモリー
2. Sub-group
3. 順序付けされたキュー
4. パイプ
5. オプションのラムダ命名
SYCL* 1.2.1 標準はバッファーメモリーを抽象化します
• 強力でエレガントに表現されたデータ依存関係
しかし …
• すべてのポインターと配列を C++ プログラムでバッファーに置き換えるのは大きな負担です
DPC++ の USM はポインターベースの代替手段を提供します
• アクセラレーターへの移植を容易にします
• プログラマーに必要な制御レベルを提供します
• バッファーを補完します
統合共有メモリー (USM)
USM の割り当てとポインターの使用法
タイプ 説明 アクセス可能 制御対象
デバイスデバイス割り当て
ホスト ホスト
デバイス ✓ デバイス
その他のデバイス
? その他のデバイス
ホストホスト割り当て
ホスト ✓ ホスト
任意のデバイス
✓ デバイス
共有潜在的な移行の割り当て
ホスト ✓ ホスト ✓*
デバイス ✓ デバイス ✓*
その他のデバイス
? その他のデバイス
?
auto A = (int*)malloc_shared(N*sizeof(int), …);auto B = (int*)malloc_shared(N*sizeof(int), …);…
q.submit([&](handler& h) {h.parallel_for(range<1>{N}, [=] (id<1> ID) {auto i = ID[0];A[i] *= B[i];
});});
アロケーション・タイプ
自動データアクセスと明示的なデータ移動がサポートされます
バッファーは強力でエレガント
• アプリケーションでうまく抽象化されている場合、またはバッファーが開発に影響しない場合に使用します
USM は使い慣れたポインターベースの C++ インターフェイスを提供
• 最小限の修正で C++ コードを DPC++ へ移植できます
• コードを移植する際に共有割り当てを使用して即座に機能させます
USM ではすぐに最高のパフォーマンスが得られるわけではありません
• すぐに機能させることができます
• プロファイラーを使用して、チューニングの必要があるコード領域を特定します
統合共有メモリー - いつ使用するか
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C++ 配列の宣言
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C++ 配列の宣言
C ++ 配列の初期化
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C++ 配列の宣言
C ++ 配列の初期化
バッファーの宣言
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C ++ 配列の作成
C ++ 配列の初期化
バッファーの作成
アクセサーの作成
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C ++ 配列の作成
C ++ 配列の初期化
バッファーの作成
アクセサーの作成
カーネルでアクセサーを使用
バッファーの例 - 共通パターン
auto A = (int *) malloc(N * sizeof(int));auto B = (int *) malloc(N * sizeof(int));auto C = (int *) malloc(N * sizeof(int));
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
{buffer<int, 1> Ab(A, range<1>{N});buffer<int, 1> Bb(B, range<1>{N});buffer<int, 1> Cb(C, range<1>{N});
q.submit([&] (handler& h) {auto R = range<1>{N};auto aA = Ab.get_access<access::mode::read>(h);auto aB = Bb.get_access<access::mode::read>(h);auto aC = Cb.get_access<access::mode::write>(h);h.parallel_for(R, [=] (id<1> i) {
aC[i] = aA[i] + aB[i];});
});} // A、B、C 更新
C ++ 配列の作成
C ++ 配列の初期化
バッファーの作成
アクセサーの作成
カーネルでアクセサーを使用
C++ 配列の更新
USM の例 - 共通パターン
USM 配列の宣言auto A = (int *) malloc_shared(N * sizeof(int), …);auto B = (int *) malloc_shared(N * sizeof(int), …);auto C = (int *) malloc_shared(N * sizeof(int), …);
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
q.submit([&] (handler& h) {auto R = range<1>{N};h.parallel_for(R, [=] (id<1> ID) {auto i = ID[0];C[i] = A[i] + B[i];
});});q.wait();// A、B、C を更新し利用できるようにする
USM の例 - 共通パターン
auto A = (int *) malloc_shared(N * sizeof(int), …);auto B = (int *) malloc_shared(N * sizeof(int), …);auto C = (int *) malloc_shared(N * sizeof(int), …);
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
q.submit([&] (handler& h) {auto R = range<1>{N};h.parallel_for(R, [=] (id<1> ID) {auto i = ID[0];C[i] = A[i] + B[i];
});});q.wait();// A、B、C を更新し利用できるようにする
USM 配列の宣言
USM 配列の初期化
USM の例 - 共通パターン
auto A = (int *) malloc_shared(N * sizeof(int), …);auto B = (int *) malloc_shared(N * sizeof(int), …);auto C = (int *) malloc_shared(N * sizeof(int), …);
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
q.submit([&] (handler& h) {auto R = range<1>{N};h.parallel_for(R, [=] (id<1> ID) {auto i = ID[0];C[i] = A[i] + B[i];
});});q.wait();// A、B、C を更新し利用できるようにする
USM 配列の宣言
USM 配列の初期化
USM 配列を直接読み書き
ポインターを使用 !
USM の例 - 共通パターン
auto A = (int *) malloc_shared(N * sizeof(int), …);auto B = (int *) malloc_shared(N * sizeof(int), …);auto C = (int *) malloc_shared(N * sizeof(int), …);
for (int i = 0; i < N; i++) {A[i] = i; B[i] = 2*i;
}
q.submit([&] (handler& h) {auto R = range<1>{N};h.parallel_for(R, [=] (id<1> ID) {auto i = ID[0];C[i] = A[i] + B[i];
});});q.wait();// A、B、C を更新し利用できるようにする
USM 配列の宣言
USM 配列の初期化
USM 配列を直接読み書き
USM 配列の更新
USM とタスク・スケジュール (オプション)
明示的なスケジュール
• カーネルを送信するとイベントが返ります
• イベントを待機してタスクを実行します
auto E = q.submit([&] (handler& h) {auto R = range<1>{N};h.parallel_for(R, [=] (id<1> ID) {auto i = ID[0];C[i] = A[i] + B[i];
});});E.wait();
auto R = range<1>{N};
auto E = q.submit([&] (handler& h) {h.parallel_for(R, [=] (id<1> ID) {…});
});
q.submit([&] (handler& h) {h.depends_on(E);h.parallel_for(R, [=] (id<1> ID) {…});
});
DPC++ グラフ・スケジュール
• イベントからタスクのエッジを構築
work-item のグループ化
• ベクトル/SIMD ハードウェアにマッピング可能
• 集合操作を明示 (シャッフル、バリア、レデュースなど)
Sub-group
work-group を Sub-group へ分解
グローバル・ワーク・サイズ
Work-group
Work-item
Sub-group
順序付けされたキュー
DPC++ のキューはアウトオブオーダー
• 複雑な DAG を表現できます
線形タスクチェーンは一般的です
• ここでは DAG は不要であり、冗長性につながります
シンプルなものはシンプルに表現する必要があります
• インオーダーのセマンティクスは線形タスクパターンを容易に表現できます
// 順序付けされたキューなしqueue q;auto R = range<1>{N};
auto E = q.submit([&] (handler& h) {h.parallel_for(R, [=] (id<1> ID) {…});
});
auto F = q.submit([&] (handler& h) {h.depends_on(E);h.parallel_for(R, [=] (id<1> ID) {…});
});
q.submit([&] (handler& h) {h.depends_on(F);h.parallel_for(R, [=] (id<1> ID) {…});
});
順序付けされたキュー (続き)
DPC++ のキューはアウトオブオーダー
• 複雑な DAG を表現できます
線形タスクチェーンは一般的です
• ここでは DAG は不要であり、冗長性につながります
シンプルなものはシンプルに表現する必要があります
• インオーダーのセマンティクスは線形タスクパターンを容易に表現できます
// 順序付けされたキューordered_queue q;auto R = range<1>{N};
q.submit([&] (handler& h) {h.parallel_for(R, [=] (id<1> ID) {…});
});
q.submit([&] (handler& h) {h.parallel_for(R, [=] (id<1> ID) {…});
});
q.submit([&] (handler& h) {h.parallel_for(R, [=] (id<1> ID) {…});
});
データ・フロー・パイプ
制御サイドバンドを持つデータ
• 転送と同期の細粒度の情報
• 空間アーキテクチャーでは重要 (FPGA)
カーネルB
カーネルA
カーネルA
カーネルA
カーネルA
ホストプログラム
I/O インターフェイス(ネットワークなど)
カーネル1
カーネル3
カーネル2
カーネル4
FIFO
FIFO
FIFO
オプションのカーネルラムダ命名
SYCL* 1.2.1 標準では、すべてのカーネルで一意の名前付けが必要です
• ファンクター・クラス・タイプ
• ラムダ式のテンプレート・タイプ名
DPC++ はラムダ式のこの要件を緩和します
• ホストコードとデバイスコードの両方でDPC++ コンパイラーを使用する必要があります
• コンパイラー・スイッチを指定します
• -fsycl-unnamed-lambda
q.submit([&] (handler& h) {auto R = range<1>{N};
h.parallel_for(R, [=](id<1> ID) {
auto i = ID[0];C[i] = A[i] + B[i];
});});
DPC++ は、CPU とアクセラレーターの両方で妥協のない生産性とパフォーマンスをもたらす、標準化ベースのクロスアーキテクチャー言語です
• SYCL* 1.2.1 標準に新機能を拡張しています
タスクグラフを使用したカーネルベースのモデル
新機能はコミュニティーのプロジェクトによって開発されています
• https://github.com/intel/llvm (英語)
• 問題のレポートや提案を歓迎します!!
まとめ
XPU によってアクセラレートされる未来に備えて、すぐにインテル® oneAPI から始めましょう
oneAPI 仕様 はoneAPI.com (英語) から入手できます
oneAPI 向けのインテル® DevCloud
(software.intel.com/devcloud/oneAPI (英語)) でインテル® oneAPI を使用して、さまざまなインテルの
データセントリックなアーキテクチャーでコードとワークロードをテストできます
関連情報とダウンロードインテル® ツールキットは、
software.intel.com/oneapi (英語)からダウンロードできます
ワークロードの評価
ヘテロジニアス・アプリケーションのビルド
インテル® oneAPI ツールキットを学習
データ並列 C++ を学習
プロジェクトのプロトタイプを作成
ダウンロード不要 | ハードウェア不要 | インストール不要 | セットアップと設定不要
わずかな時間で起動および実行できます!!
インテル® oneAPI ツールキットを使用して、さまざまなインテルの CPU、GPU、FPGA でワークロードを開発、テスト、および実行する開発向けのサンドボックス
インテル® oneAPI を使用する
インテル® DevCloud
software.intel.com/en-us/devcloud/oneapi (英語)
最適化に関する注意事項
インテル® コンパイラーでは、インテル® マイクロプロセッサーに限定されない最適化に関して、他社製マイクロプロセッサー用に同等の最適化を行えないことがあります。これには、インテル® ストリーミング SIMD 拡張命令 2、インテル® ストリーミング SIMD 拡張命令 3、インテル® ストリーミング SIMD 拡張命令 3 補足命令などの最適化が該当します。インテルは、他社製マイクロプロセッサーに関して、いかなる最適化の利用、機能、または効果も保証いたしません。本製品のマイクロプロセッサー依存の最適化は、インテル® マイクロプロセッサーでの使用を前提としています。インテル® マイクロアーキテクチャーに限定されない最適化のなかにも、インテル® マイクロプロセッサー用のものがあります。この注意事項で言及した命令セットの詳細については、該当する製品のユーザー・リファレンス・ガイドを参照してください。注意事項の改訂 #20110804
法務上の注意書きと最適化に関する注意事項
本資料には、開発中の製品、サービスおよびプロセスについての情報が含まれています。本資料に含まれる情報は予告なく変更されることがあります。
インテルのテクノロジーを使用するには、対応したハードウェア、ソフトウェア、またはサービスの有効化が必要となる場合があります。詳細については、OEM または販売店にお問い合わせいただくか、https://www.intel.co.jp/ を参照してください。
性能に関するテストに使用されるソフトウェアとワークロードは、性能がインテル® マイクロプロセッサー用に最適化されていることがあります。SYSmark* や MobileMark* などの性能テストは、特定のコンピューター・システム、コンポーネント、ソフトウェア、操作、機能に基づいて行ったものです。結果はこれらの要因によって異なります。製品の購入を検討される場合は、他の製品と組み合わせた場合の本製品の性能など、ほかの情報や性能テストも参考にして、パフォーマンスを総合的に評価することをお勧めします。性能やベンチマーク結果について、さらに詳しい情報をお知りになりたい場合は、https://www.intel.com/benchmarks (英語) を参照してください。
本資料は、(明示されているか否かにかかわらず、また禁反言によるとよらずにかかわらず) いかなる知的財産権のライセンスも許諾するものではありません。インテルは、明示されているか否かにかかわらず、いかなる保証もいたしません。ここにいう保証には、商品適格性、特定目的への適合性、および非侵害性の黙示の保証、ならびに履行の過程、取引の過程、または取引での使用から生じるあらゆる保証を含みますが、これらに限定されるわけではありません。
© 2021 Intel Corporation. 無断での引用、転載を禁じます。Intel、インテル、Intel ロゴは、アメリカ合衆国および / またはその他の国における Intel Corporation またはその子会社の商標です。Khronos* は登録商法であり、SYCL* は Khronos Group, Inc の商標です。
* その他の社名、製品名などは、一般に各社の表示、商標または登録商標です。
質疑応答