1. 概要
前回記事 では、Coral EdgeTPU Dev Board 上で、TensorFlow Lite の GPU Delegate (OpenGLES版)を試しました。
一方で、GPU Delegate には OpenCL版 もあり、かねてからこちらも試してみたいと思っていました。
EdgeTPU DevBoard の GPU は、カタログスペック によれば、 OpenGLES3.1 に加えて OpenCL にも対応しているので、うまくやれば DevBoard 上で GPU Delegate (OpenCL版) を動かせるはずです。(前回同様、EdgeTPU DevBoard なのに EdgeTPU を使いません。)
今回の記事では、その第一歩として、EdgeTPU DevBoard における OpenCL の動作環境構築までを書いてみます。
2. 必要ファイルの確認
この作業に着手する前は、「そもそも DevBoard 上で OpenCL アプリをビルドするために必要なヘッダファイルやライブラリは、どこかに用意されてるのか?」という心配もあったのですが、あっけなく見つかりました。DevBoard 上に最初から存在しているようです。
■OpenCL ヘッダファイル
mendel@green-rabbit:~$ ls -l /usr/include/CL
total 188
-rw-r--r-- 1 root root 74542 Jun 14 2016 cl.h
-rw-r--r-- 1 root root 18168 Sep 8 2016 cl_ext.h
-rw-r--r-- 1 root root 43558 Sep 8 2016 cl_platform.h
-rw-r--r-- 1 root root 1993 Jun 14 2016 opencl.h
(以下略)
■OpenCL ライブラリ
mendel@green-rabbit:~$ ls -l /usr/lib/vivante/
total 17904
-rw-r--r-- 1 root root 2161664 Mar 20 2019 libCLC.so
-rw-r--r-- 1 root root 4322368 Mar 20 2019 libLLVM_viv.so
-rw-r--r-- 1 root root 26928 Mar 20 2019 libOpenCL.so
-rw-r--r-- 1 root root 372872 Mar 20 2019 libSPIRV_viv.so
-rw-r--r-- 1 root root 320440 Mar 20 2019 libVivanteOpenCL.so
(以下略)
DevBoard 上で、上記ファイルを使ってネイティブビルドすれば、OpenCL アプリをビルドすることができそうです。
3. OpenCL デバイスクエリ
とっかかりのOpenCLアプリとして、Dev Board の GPU がどのような OpenCL デバイスとして見えるのかを確認するQueryアプリを作りました。
3.1 Queryアプリの実装
下記のように、OpenCL プラットフォーム および OpnCL デバイスに関する情報取得を行うAPIを一通り叩くようなコードを準備します。
特に目新しいコードではありませんが、実際に私が使ったコードは、ここ で公開しています。
#include <CL/cl.h>
#define PRINT_PLATFORM_INFO_STR(pf_id, param_name) \
do \
{ \
char strbuf[1024]; \
clGetPlatformInfo (pf_id, param_name, sizeof(strbuf), strbuf, NULL); \
fprintf (stderr, " %-24s: %s\n", #param_name, strbuf); \
} while (0)
opencl_device_query ()
{
cl_platform_id* pf_ids;
cl_uint i, j, num_platforms;
/* OpenCL プラットフォーム数を取得し、全てのプラットフォームID を取得 */
clGetPlatformIDs (0, NULL, &num_platforms);
pf_ids = (cl_platform_id*)malloc (num_platforms * sizeof (cl_platform_id));
clGetPlatformIDs (num_platforms, pf_ids, NULL);
/* i 番目のプラットフォームに関する Query */
for (i = 0; i < num_platforms; i++)
{
cl_platform_id pf_id = pf_ids[i];
cl_uint num_devices;
cl_device_id *devices;
PRINT_PLATFORM_INFO_STR(pf_id, CL_PLATFORM_NAME);
PRINT_PLATFORM_INFO_STR(pf_id, CL_PLATFORM_VENDOR);
PRINT_PLATFORM_INFO_STR(pf_id, CL_PLATFORM_VERSION);
PRINT_PLATFORM_INFO_STR(pf_id, CL_PLATFORM_PROFILE);
PRINT_PLATFORM_INFO_STR(pf_id, CL_PLATFORM_EXTENSIONS);
/* i 番目のプラットフォームに属する全てのデバイスIDを取得 */
clGetDeviceIDs (pf_id, CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
devices = (cl_device_id *)malloc (sizeof(cl_device_id) * num_devices);
clGetDeviceIDs (pf_id, CL_DEVICE_TYPE_ALL, num_devices, devices, &num_devices);
for (j = 0; j < num_devices; j++)
{
query_cldev (devices[j]);
}
}
}
3.2 Queryアプリのビルド
上記ソースコードは、DevBoard 上でネイティブビルドすれば、至ってシンプルにビルドすることができました。
mendel@green-rabbit:~$ gcc -L/usr/lib/vivante -lOpenCL main.c
mendel@green-rabbit:~$ ls -l a.out
-rwxr-xr-x 1 mendel mendel 18008 Nov 3 12:58 a.out*
3.3 Queryアプリ実行結果
上記アプリを DevBoard 上で実行すると、下記のようなQuery結果が表示されます。
OpenCL 1.2 Full Profile (DEVICE_TYPE=GPU) のデバイスとして、ちゃんと見えているようです。
--------------------------------------------------------
OpenCL Platform [0/1]
--------------------------------------------------------
CL_PLATFORM_NAME : Vivante OpenCL Platform
CL_PLATFORM_VENDOR : Vivante Corporation
CL_PLATFORM_VERSION : OpenCL 1.2 V6.2.4.p2.163672
CL_PLATFORM_PROFILE : FULL_PROFILE
CL_PLATFORM_EXTENSIONS : cl_khr_icd
----------------------------------
CL Device [0/1]
----------------------------------
CL_DEVICE_NAME : Vivante OpenCL Device GC7000L.6214.0000
CL_DEVICE_VENDOR : Vivante Corporation
CL_DRIVER_VERSION : OpenCL 1.2 V6.2.4.p2.163672
CL_DEVICE_OPENCL_C_VERSION : OpenCL C 1.2
CL_DEVICE_PROFILE : FULL_PROFILE
CL_DEVICE_AVAILABLE : true
CL_DEVICE_COMPILER_AVAILABLE : true
CL_DEVICE_TYPE : CL_DEVICE_TYPE_GPU
CL_DEVICE_EXTENSIONS : cl_khr_byte_addressable_store cl_khr_global_int32_base_atomics cl_khr_global_int32_extended_atomics cl_khr_local_int32_base_atomics cl_khr_local_int32_extended_atomics cl_khr_gl_sharing
CL_DEVICE_VENDOR_ID : 5654870
CL_DEVICE_MAX_COMPUTE_UNITS : 1
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS : 3
CL_DEVICE_MAX_WORK_ITEM_SIZES : 1024 / 1024 / 1024
CL_DEVICE_MAX_WORK_GROUP_SIZE : 1024
CL_DEVICE_MAX_CLOCK_FREQUENCY : 800 MHz
CL_DEVICE_ADDRESS_BITS : 32
CL_DEVICE_MAX_MEM_ALLOC_SIZE : 128 MByte
CL_DEVICE_GLOBAL_MEM_SIZE : 256 MByte
CL_DEVICE_ENDIAN_LITTLE : true
CL_DEVICE_HOST_UNIFIED_MEMORY : true
CL_DEVICE_ERROR_CORRECTION_SUPPORT : true
CL_DEVICE_LOCAL_MEM_TYPE : global
CL_DEVICE_LOCAL_MEM_SIZE : 32 KByte
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE : 64 KByte
CL_DEVICE_QUEUE_PROPERTIES : CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
CL_DEVICE_QUEUE_PROPERTIES : CL_QUEUE_PROFILING_ENABLE
CL_DEVICE_IMAGE_SUPPORT : true
CL_DEVICE_MAX_READ_IMAGE_ARGS : 128
CL_DEVICE_MAX_WRITE_IMAGE_ARGS : 8
CL_DEVICE_IMAGE2D_MAX_WIDTH : 8192
CL_DEVICE_IMAGE2D_MAX_HEIGHT : 8192
CL_DEVICE_IMAGE3D_MAX_WIDTH : 8192
CL_DEVICE_IMAGE3D_MAX_HEIGHT : 8192
CL_DEVICE_IMAGE3D_MAX_DEPTH : 8192
CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR : 4
CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT : 4
CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT : 4
CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG : 4
CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT : 4
CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE : 0
CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF : 0
CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR : 4
CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT : 4
CL_DEVICE_NATIVE_VECTOR_WIDTH_INT : 4
CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG : 4
CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT : 4
CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE : 0
CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF : 0
4. 最後に
EdgeTPU DevBoard 上で、OpenCL デバイスクエリに成功しました。
(まだ CLカーネルは1つも動かしてませんが、)EdgeTPU DevBoard 上で OpenCL は動きそうな感じがしてきたので、引き続き、TensorFlow Lite (OpenCL版) に挑戦したいと思います。