この実装は、ヘテロジニアス・システム向けの大規模な並列計算モデルの実行に使用されるデータ並列 C++ (DPC++) 実行ポリシーをサポートしています。ポリシーの詳細は、「oneAPI 仕様の DPC++ 実行ポリシー」 (英語) セクションを参照してください。
実装されているアルゴリズムでは、呼び出しの最初の引数として次のいずれかの実行ポリシー・オブジェクトを渡して、実行の動作を指定します。ポリシーには次の意味があります。
実行ポリシー値 |
説明 |
---|---|
seq |
シーケンシャル実行。 |
unseq |
順序関係のない SIMD 実行。提供されているすべての関数が SIMD セーフである必要があります。 |
par |
複数のスレッドによる並列実行。 |
par_unseq |
unseq と par の効果を組み合わせます。 |
dpcpp_default |
DPC++ を使用したデバイス上での大規模な並列実行。 |
dpcpp_fpga |
FPGA デバイス上での大規模な並列実行。 |
実装は、LLVM プロジェクト (英語) の Parallel STL をベースにしています。
インテル® oneDPL は、par および par_unseq ポリシーで実行するため、2 つの並列バックエンドをサポートしています。
インテル® TBB バックエンド (デフォルトで有効) は、並列実行にインテル® oneAPI スレッディング・ビルディング・ブロック (インテル® oneTBB) またはインテル® スレッディング・ビルディング・ブロック (インテル® TBB) を使用します。
OpenMP* バックエンドは、並列実行に OpenMP* プラグマを使用します。OpenMP* バックエンドを有効にする方法については、「マクロ」を参照してください。
次の手順に従って、アプリケーションに Parallel API を追加します。
コードに #include <oneapi/dpl/execution> を追加します。次に、使用するアルゴリズムに応じて、次のヘッダーファイルを 1 つ以上インクルードします。
#include <oneapi/dpl/algorithm>
#include <oneapi/dpl/numeric>
#include <oneapi/dpl/memory>
C++ 標準ライブラリーとの共存性を高めるには、標準 C++ ヘッダーファイルの前にインテル® oneDPL ヘッダーファイルをインクルードします。
oneapi::dpl::execution 名前空間で定義されているインテル® oneDPL 実行ポリシー・オブジェクトを並列アルゴリズムに渡します。
C++ 標準の実行ポリシーを使用します。
OpenMP* の並列化やベクトル化プラグマを有効にするオプションを指定してコードをコンパイルします。
インテル® TBB ベースの並列処理向けにインテル® oneAPI スレッディング・ビルディング・ブロック (インテル® oneTBB) またはインテル® スレッディング・ビルディング・ブロック (インテル® TBB) のダイナミック・ライブラリーとリンクします。
DPC++ 実行ポリシーを使用します。
SYCL* 2020 のサポートを有効にするオプションを指定してコードをコンパイルします。
次に例を示します。
#include <oneapi/dpl/execution>
#include <oneapi/dpl/algorithm>
#include <vector>
int main()
{
std::vector<int> data( 1000 );
std::fill(oneapi::dpl::execution::par_unseq, data.begin(), data.end(), 42);
return 0;
}
DPC++ 実行ポリシーは、並列アルゴリズムを実行する場所を定義します。SYCL* デバイスまたはキューをカプセル化し、オプションのカーネル名を設定することができます。DPC++ 実行ポリシーは、実行ポリシーをサポートするすべての標準 C++ アルゴリズムで使用できます。
ポリシー・オブジェクトを作成するには、次のいずれかのコンストラクター引数を使用します。
SYCL* キュー
SYCL* デバイス
SYCL* デバイスセレクター
異なるカーネル名の既存のポリシー・オブジェクト
カーネル名はポリシー・テンプレート引数で設定されます。コンパイラーが SYCL* カーネル関数の暗黙名をサポートしている場合、ポリシーのカーネル名の指定はオプションです。インテル® oneAPI DPC++/C++ コンパイラーはデフォルトでサポートしています。ほかのコンパイラーでは、-fsycl-unnamed-lambda などのコンパイラー・オプションを使用して有効にする必要があります。詳細は、コンパイラーのドキュメントを参照してください。
oneapi::dpl::execution::dpcpp_default オブジェクトは、device_policy クラスの事前定義オブジェクトです。デフォルトのカーネル名とデフォルトのキューで作成されています。カスタマイズされたポリシー・オブジェクトの構築に使用したり、アルゴリズムを呼び出す際に直接渡すことができます。
dpcpp_default が複数のアルゴリズムに直接渡される場合、コンパイラーで暗黙のカーネル名のサポートを有効にして (上記参照)、このオプションをオンにする必要があります。
make_device_policy 関数テンプレートは、device_policy の作成を簡素化します。
以下のコード例では、ポリシークラスと関数を参照する際に、using namespace oneapi::dpl::execution; と using namespace sycl; ディレクティブを追加することを仮定しています。
auto policy_a = device_policy<class PolicyA> {};
std::for_each(policy_a, ...);
auto policy_b = device_policy<class PolicyB> {device{gpu_selector{}}};
std::for_each(policy_b, ...);
auto policy_c = device_policy<class PolicyС> {cpu_selector{}};
std::for_each(policy_c, ...);
auto policy_d = make_device_policy<class PolicyD>(dpcpp_default);
std::for_each(policy_d, ...);
auto policy_e = make_device_policy(queue{property::queue::in_order()});
std::for_each(policy_e, ...);
fpga_policy クラスは、FPGA ハードウェア・デバイス上で並列アルゴリズムのパフォーマンスを向上するように調整された DPC++ ポリシーです。
FPGA ハードウェア・デバイスや FPGA エミュレーション・デバイスでアプリケーションを実行する場合は、次のステップを使用します。
FPGA デバイスで実行するには ONEDPL_FPGA_DEVICE マクロを、FPGA エミュレーション・デバイスで実行するには ONEDPL_FPGA_EMULATOR マクロを定義します。
コードに #include <oneapi/dpl/execution> を追加します。
アンロール係数 (以下の 注を参照) と一意のカーネル名のクラス型を示すテンプレート引数 (どちらもオプション)、および次のいずれかのコンストラクター引数を指定してポリシー・オブジェクトを作成します。
FPGA セレクター 用に構築された SYCL* キュー (その他のキューでは動作は未定義)
カーネル名、アンロール係数、または両方が異なる既存の FPGA ポリシー・オブジェクト
作成したポリシー・オブジェクトを並列アルゴリズムに渡します。
fpga_policy のデフォルトのコンストラクターは、ONEDPL_FPGA_EMULATOR が定義されている場合、fpga_selector または fpga_emulator_selector 用に作成された SYCL* キューをラップします。
oneapi::dpl::execution::dpcpp_fpga は、デフォルトのアンロール係数とデフォルトのカーネル名で作成された fpga_policy クラスの定義済みオブジェクトです。カスタマイズされたポリシー・オブジェクトの作成に使用したり、アルゴリズムを呼び出す際に直接渡すことができます。
ポリシーのアンロール係数を指定すると、アルゴリズムの実装でループアンロールが有効になります。デフォルト値は 1 です。より正確な値の選択方法については、『インテル® oneAPI DPC++ FPGA 最適化ガイド』 (英語) の「unroll プラグマ」 (英語) と「ループ解析」 (英語) を参照してください。
make_fpga_policy 関数テンプレートは、fpga_policy の作成を簡素化します。
以下のコード例では、ポリシーには using namespace oneapi::dpl::execution; を、キューとデバイスセレクターには using namespace sycl; を追加することを仮定しています。
constexpr auto unroll_factor = 8;
auto fpga_policy_a = fpga_policy<unroll_factor, class FPGAPolicyA>{};
auto fpga_policy_b = make_fpga_policy(queue{intel::fpga_selector{}});
auto fpga_policy_c = make_fpga_policy<unroll_factor, class FPGAPolicyC>();
DPC++ のエラー処理モデルは、2 種類のエラーをサポートしています。同期エラーは DPC++ ホスト・ランタイム・ライブラリーは例外をスローします。非同期エラーは DPC++ キューに関連付けられたユーザー提供のエラーハンドラーでのみ処理されます。
DPC++ ポリシーで実行されるアルゴリズムでは、同期または非同期にかかわらず、すべてのエラーを処理するのは呼び出し元の責任です。
アルゴリズムによって明示的に例外がスローされることはありません。
ランタイム・ライブラリーによってホスト CPU でスローされた例外 (DPC++ 同期例外を含む) は、呼び出し元に渡されます。
DPC++ 非同期エラーは処理されません。
DPC++ 非同期エラーを処理するには、エラー・ハンドラー・オブジェクトで DPC++ ポリシーに関連付けられたキューを作成する必要があります。定義済みポリシー・オブジェクト (dpcpp_default など) にはエラーハンドラーがないため、非同期エラーを処理する必要がある場合は使用しないでください。