DPC++ と SYCL* でグラフィックス・デバイスを選択して実行する

インテル® oneAPI

ディスクリートのインテル® Arc™ A380 グラフィックス・カードも入手可能となり、やっとプラットフォームで複数のグラフィックス・プロセッサーを利用できるようになりました。これまで、統合グラフィックス (iGPU) を使用した SYCL* や OpenMP* のプログラミング例を紹介してきましたが、この記事では複数のグラフィックス・プロセッサーを明示的に選択して実行するにはどのようにするか簡単に紹介します。

SYCL* を使用したプログラムでは、これまでの記事でデバイスを選択するいくつかの方法を紹介しましたが、ここでは最も容易なデフォルトデバイスを使用します。明示的にプログラムからデバイスを選択するにはデバイスセレクターを使用します。

SYCL* 環境では、sycl-ls コマンドで利用可能なデバイスの一覧を確認できます。デフォルトデバイスは環境変数 SYCL_DEVICE_FILER に、コマンドで示されるデバイスとデバイス番号を設定して容易に変更できます。

デバイスとデバイス番号に対応するターゲットデバイスは、異なるプラットフォームでも同一であるとは限りません。プログラム中でデバイスを選択する場合、デバイス名を識別する必要があるため、環境変数を使用する方法が最も簡単にデバイスを変更できると言ってよいでしょう。

次の簡単なコードを使用して、デフォルトデバイスを選択し計算をオフロードする例を紹介します。このコードは、queue q でデバイスキューを宣言し、デバイスセレクターを指定していないため、デフォルトデバイスがターゲットとして割り当てられます。

#include <CL/sycl.hpp>
using namespace sycl;
static const int N = 16;
int main(){  
queue q;                                          // デバイスキューを宣言
  std::cout << "デバイス: " << q.get_device().get_info<info::device::name>() << std::endl; // デバイス名を表示

     int *data = malloc_shared<int>(N, q);        // 統合共有メモリーを割り当て
     for(int i=0; i<N; i++) data[i] = i;          // メモリーを初期化

     q.parallel_for(range<1>(N), [=] (id<1> i){   // デバイスキューへ計算をオフロード
        data[i] *= 2;                             // オフロードされる計算カーネル
     }).wait();                                   // デバイス上で計算が完了するのを待機
  free(data, q);
  return 0;
}

上記のコードを dpcpp コンパイラーでコンパイルして実行したところ、次のような結果が表示されました。

デフォルトデバイスである、インテル® UHD グラフィックス 770 にコードがオフロードされています。

注:
この例では、インテル® Core™ i7 12700K プロセッサー (インテル® UHD グラフィックス 770 搭載) とインテル® Arc™ A380 グラフィックス・カードを搭載するシステムで、Windows* 11 とインテル® oneAPI ベース・ツールキット 2022.3 およびインテル® oneAPI HPC ツールキット 2022.3、Microsoft* Visual Studio* 2022 をインストールした環境を使用しています。

Windows* のタスクマネージャーでハードウェアの割り当てを確認すると、GPU は次のように確認できました。GPU 0 がデフォルトデバイスとして識別され、上記の結果が報告されています。

環境変数 SYCL_DEVICE_FILER を使用してターゲットデバイスを変更できます。上記の sycl-ls コマンドでは、このプラットフォームで利用可能なデバイスは次のようにレポートされました。

[opencl:acc:0] Intel(R) FPGA Emulation Platform for OpenCL(TM), Intel(R) FPGA Emulation Device 1.2 [2022.14.7.0.30_160000]
[opencl:cpu:1] Intel(R) OpenCL, 12th Gen Intel(R) Core(TM) i7-12700K 3.0 [2022.14.7.0.30_160000]
[opencl:gpu:2] Intel(R) OpenCL HD Graphics, Intel(R) UHD Graphics 770 3.0 [31.0.101.3430]
[opencl:gpu:3] Intel(R) OpenCL HD Graphics, Intel(R) Arc(TM) A380  Graphics 3.0 [31.0.101.3430]
[ext_oneapi_level_zero:gpu:0] Intel(R) Level-Zero, Intel(R) UHD Graphics 770 1.3 [1.3.23904]
[ext_oneapi_level_zero:gpu:1] Intel(R) Level-Zero, Intel(R) Arc(TM) A380  Graphics 1.3 [1.3.23904]
[host:host:0] SYCL host platform, SYCL host device 1.2 [1.2]

acc:0 や cpu:0 のようにそのカテゴリーのデバイスが 1 つしか存在しない場合は ACC や CPU のように設定できますが、複数の同一カテゴリーのデバイスが複数存在する場合、gpu:0、gpu:1、gpu:2 または gpu:3 のようにデバイス番号を指定します。例えば、SYCL_DEVICE_FILER=GPU:3 のように、OpenCL* インターフェイスを使用してインテル® ARC™ A380 グラフィックス・デバイスを指定すると、実行結果は次のようになります。

同様に、デバイスとデバイス番号を GPU:2 に設定すると次のようになります。これは、デフォルトデバイスと同様です。

プログラムを変更することなく同一バイナリーで複数のデバイスに対応できるため、デフォルトデバイスを使用すると、複数のターゲットデバイスでパフォーマンスを評価したり、異なるシステムで動作を検証する際に便利です。

ただし、環境変数 SYCL_DEVICE_FILTER を設定して sycl-ls コマンドを実行すると、設定されているデバイスしかレポートされないことに注意してください。次の例では SYCL_DEVICE_FILTER に GPU:3 が設定されているため、インテル® Arc™ A380 グラフィックスのみがレポートされています。

複数のデバイスキューを非同期に実行すると、複数のインテル® プロセッサーやグラフィックス・プロセッサーで同時に計算カーネルを実行できます。その場合、デバイスセレクターを使用して複数のデバイスで非同期実行するコードを記述する必要があります。

次回は、インテル® DPC++/C++ コンパイラーおよびインテル® Fortran コンパイラーでサポートされる OpenMP* オフロードで統合グラフィックスとディスクリート・グラフィックスを使用する方法を紹介します。

タイトルとURLをコピーしました