この記事は、The Parallel Universe Magazine 52 号に掲載されている「Device Discovery with SYCL*」の日本語参考訳です。原文は更新される可能性があります。原文と翻訳文の内容が異なる場合は原文を優先してください。
デバイス検出は、SYCL* やクロスアーキテクチャーのヘテロジニアス並列プログラミング・アプローチの重要な一面です。以前の oneAPI の記事では、SYCL* と oneMKL および oneDPL ライブラリーを使用して計算をアクセラレーター・デバイスにオフロードすること (つまり、コードを実行する場所の制御) に焦点を当てました。ヘテロジニアス・システム向けの移植可能なコードを記述するには利用可能なハードウェアに関する情報をシステムに照会する機能が必要になるため、この記事ではデバイス検出に焦点を当てています。例えば、GPU を使用するように SYCL* デバイスセレクターを指定しても、システムに GPU がない場合、次の文は失敗します。
... sycl::queue Q(sycl::gpu_selector_v); ... terminate called after throwing an instance of ‘sycl::_V1::runtime_error’ what(): No device of requested type available. Please check https://software.intel.com/content/www/us/en/develop/articles/intel-oneapi-dpcpp-system-requirements.html -1 (PI_ERROR_DEVICE_NOT_FOUND) Aborted
このコードは、GPU がないシステムには移植できません。GPU セレクターの代わりにデフォルトセレクターを使用して SYCL* キューをインスタンス化すれば動作することは保証されますが、キューがどこワークを送信するか制御できなくなります。SYCL* ランタイムがデバイスを選択します。
... sycl::queue Q(sycl::default_selector_v); std::cout << "Running on: " << Q.get_device().get_info<sycl::info::device::name>() << std::endl; ... Running on: Intel(R) Xeon(R) Gold 6128 CPU @ 3.40GHz
確実なヘテロジニアス並列プログラムを作成するため、SYCL* デバイス検出を詳しく見て、次の質問に答えてみましょう。
- どのアクセラレーター・デバイスを使用できますか?
- SYCL* キューはどのデバイスを使用していますか?
- oneDPL 実行ポリシーはどのデバイスを使用していますか?
堅牢なデバイス検出
さまざまなインテル® ハードウェアのオプションがあり、最新のインテル® oneAPI ソフトウェアがすでにインストールされているインテル® DevCloud for oneAPI (英語) で、いくつかの例を実行してみましょう。ハードウェアは定期的に更新されますが、この記事の執筆時点 (2022年12月2日) では次の計算ノードが利用可能でした。
$ pbsnodes | grep properties | sort | uniq -c | sort -nr 79 properties = xeon,skl,gold6128,ram192gb,net1gbe,jupyter,batch 78 properties = xeon,cfl,e-2176g,ram64gb,net1gbe,gpu,gen9 26 properties = xeon,skl,gold6128,ram192gb,net1gbe,jupyter,batch,fpga_compile 25 properties = core,tgl,i9-11900kb,ram32gb,netgbe,gpu,gen11 12 properties = xeon,skl,ram384gb,net1gbe,renderkit 12 properties = xeon,skl,gold6128,ram192gb,net1gbe,fpga_runtime,fpga,arria10 6 properties = xeon,icx,gold6348,ramgb,netgbe,jupyter,batch 4 properties = xeon,icx,plat8380,ram2tb,net1gbe,batch 4 properties = xeon,clx,ram192gb,net1gbe,batch,extended,fpga,stratix10,fpga_runt
ご覧のように、さまざまな CPU、GPU、および FPGA オプションがあります (機密保持契約ユーザーは、インテル® DevCloud for oneAPI の NDA パーティション内のリリース前のハードウェアにアクセスできます)。ノードをリクエストして、利用可能なデバイスを確認します。
$ qsub -I -l nodes=1:gen11:ppn=2
このコマンドは、第 11 世代インテル® プロセッサー・グラフィックスを含む単一ノードへの対話型アクセスをリクエストします。SYCL* では、すでに説明した 2 つのセレクターに加えて、ビルトインセレクターとして default_selector_v、gpu_selector_v、cpu_selector_v、および accelerator_selector_v を提供しています。インテルは、FPGA 開発向けに、fpga_selector および fpga_emulator_selector の 2 つの拡張機能も提供しています。これらの拡張機能は sycl/ext/intel/fpga_device_selector.hpp ヘッダーに含まれています。FPGA 上での SYCL* の使用に関する詳細は、『インテル® oneAPI プログラミング・ガイド』の「FPGA フロー」を参照してください。
ビルトインセレクターは主に利便性を目的としていますが、例外処理と組み合わせると堅牢になります。
sycl::device d; try { d = sycl::device(sycl::gpu_selector_v); } catch (sycl::exception const &e) { d = sycl::device(sycl::cpu_selector_v); }
しかし、まだ SYCL* ランタイムがデバイスを選択しています。特に複数のデバイスが利用可能な場合は、さらなる制御が必要になります。
次のプログラムは、計算ノードで利用可能なプラットフォームとデバイスをリストします (この情報は、sycl-ls コマンドライン・ユーティリティーを使用して取得することもできます)。
#include <sycl/sycl.hpp> int main() { for (auto platform : sycl::platform::get_platforms()) { std::cout << "Platform: " << platform.get_info<sycl::info::platform::name>() << std::endl; for (auto device : platform.get_devices()) { std::cout << "\tDevice: " << device.get_info<sycl::info::device::name>() << std::endl; } } } $ icpx -fsycl show_platforms.cpp -o show_platforms $ ./show_platforms Platform: Intel(R) FPGA Emulation Platform for OpenCL(TM) Device: Intel(R) FPGA Emulation Device Platform: Intel(R) OpenCL Device: 11th Gen Intel(R) Core(TM) i9-11900KB @ 3.30GHz Platform: Intel(R) OpenCL HD Graphics Device: Intel(R) UHD Graphics [0x9a60] Platform: Intel(R) Level-Zero Device: Intel(R) UHD Graphics [0x9a60]
SYCL* プラットフォームは、ホストがアクセラレーター・デバイスに接続されている OpenCL* プラットフォーム・モデルに基づいています。これは、上記の出力例で明白です。このシステムには OpenCL* プラットフォームと oneAPI レベルゼロ・プラットフォームがあります。各プラットフォームには、SYCL* プログラムがワークを送信できるデバイスがあります。OpenCL* または oneAPI レベルゼロ・バックエンドを使用するかどうかに応じて、2 つの GPU プラットフォームがあります。CPU および FPGA エミュレーション・プラットフォームもあります。この情報を利用して、これらのデバイスのいずれかにワークを送信するキューを作成できます。