バッファーと USM の使用

アルゴリズムにデータを渡す

次のいずれかの方法で、データ並列 C++ (DPC++) ポリシーを使用して実行されるアルゴリズムにデータを渡すことができます。

oneapi::dpl::begin と oneapi::dpl::end 関数の使用

oneapi::dpl::beginoneapi::dpl::end は、SYCL* バッファーを並列アルゴリズムに渡すことができるヘルパー関数です。これらの関数は、SYCL* バッファーを受け取り、以下の API を提供する不特定型のオブジェクトを返します。

beginend 関数は、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 に割り当てられたバッファーがある場合は、バッファーの開始 (先頭) と終了 (最後の後) へのポインターを並列アルゴリズムに渡します。実行ポリシーとバッファーが同じキューに対して作成されていることを確認します。次に例を示します。

#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;
}