次のいずれかの方法で、データ並列 C++ (DPC++) ポリシーを使用して実行されるアルゴリズムにデータを渡すことができます。
oneapi:dpl::begin と oneapi::dpl::end 関数
統合共有メモリー (USM) ポインターと USM アロケーターを持つ std::vector
ホスト側の std::vector のイテレーター
oneapi::dpl::begin と oneapi::dpl::end 関数の使用
oneapi::dpl::begin と oneapi::dpl::end は、SYCL* バッファーを並列アルゴリズムに渡すことができるヘルパー関数です。これらの関数は、SYCL* バッファーを受け取り、以下の API を提供する不特定型のオブジェクトを返します。
CopyConstructible および CopyAssignable C++ 名前付き要件を満たし、operator== および operator!= と同等です。
次の有効な式が得られます: a + n、a - n、および a - b。ここで、a と b は指定された型のオブジェクト、n は整数値です。これらの演算の効果は、C++ 名前付き要件の LegacyRandomAccessIterator を満たす型と同じです。
begin と end 関数に渡すバッファーを返す get_buffer メソッドを提供します。
begin と end 関数は、SYCL* 2020 の推定タグおよび sycl::no_init を引数として指定して、カーネルをデバイスに送信するときにバッファーアクセサーに適用するアクセスモードを明示的に指定できます。次に例を示します。
auto first1 = begin(buf, sycl::read_only);
auto first2 = begin(buf, sycl::write_only, sycl::no_init);
auto first3 = begin(buf, sycl::no_init);
上記の例を使用して、並列アルゴリズムに渡す特定のバッファーのアクセスモードを制御できます。
これらの関数を使用するには、コードに #include <oneapi/dpl/iterator> を追加します。次に例を示します。
#include <oneapi/dpl/execution>
#include <oneapi/dpl/algorithm>
#include <oneapi/dpl/iterator>
#include <CL/sycl.hpp>
int main(){
sycl::buffer<int> buf { 1000 };
auto buf_begin = oneapi::dpl::begin(buf);
auto buf_end = oneapi::dpl::end(buf);
std::fill(oneapi::dpl::execution::dpcpp_default, buf_begin, buf_end, 42);
return 0;
}
統合共有メモリーの使用
以下の例は、並列アルゴリズムと USM を併用する 2 つの方法を示します。
USM ポインター
USM アロケーター
USM に割り当てられたバッファーがある場合は、バッファーの開始 (先頭) と終了 (最後の後) へのポインターを並列アルゴリズムに渡します。実行ポリシーとバッファーが同じキューに対して作成されていることを確認します。次に例を示します。
#include <oneapi/dpl/execution>
#include <oneapi/dpl/algorithm>
#include <CL/sycl.hpp>
int main(){
sycl::queue q;
const int n = 1000;
int* d_head = sycl::malloc_shared<int>(n, q);
std::fill(oneapi::dpl::execution::make_device_policy(q), d_head, d_head + n, 42);
sycl::free(d_head, q);
return 0;
}
あるいは、std::vector と USM アロケーターを併用できます。次に例を示します。
#include <oneapi/dpl/execution>
#include <oneapi/dpl/algorithm>
#include <CL/sycl.hpp>
int main(){
const int n = 1000;
auto policy = oneapi::dpl::execution::dpcpp_default;
sycl::usm_allocator<int, sycl::usm::alloc::shared> alloc(policy.queue());
std::vector<int, decltype(alloc)> vec(n, alloc);
std::fill(policy, vec.begin(), vec.end(), 42);
return 0;
}
デバイス USM (malloc_device で割り当てられたものなど) を使用する場合は、インテル® oneDPL アルゴリズムを呼び出す前に手動でこのメモリーへデータをコピーし、アルゴリズムの実行が終了したらコピーバックします。
ホスト側の std::vector の使用
インテル® oneAPI DPC++ ライブラリー (インテル® oneDPL) 並列アルゴリズムは、以下の例に示すように、通常の (ホスト側の) イテレーターを使用して呼び出すことができます。この場合、一時的な SYCL* バッファーが作成され、このバッファーにデータがコピーされます。デバイス上で一時バッファーの処理が完了すると、データはホストにコピーバックされます。ホストとデバイス間のデータコピーを軽減するため、SYCL* バッファーを使用することを推奨します。次に例を示します。
#include <oneapi/dpl/execution>
#include <oneapi/dpl/algorithm>
#include <vector>
int main(){
std::vector<int> vec( 1000 );
std::fill(oneapi::dpl::execution::dpcpp_default, vec.begin(), vec.end(), 42);
// vec の各要素は 42 に等しい
return 0;
}