1. 概要
前回および前々回 では、Coral EdgeTPU DevBoard 上で、TensorFlow Lite GPU Delegate の OpenGLES版 および OpenCL版 を試しました。
OpenGLES, OpenCL とくれば、その次に気になるのは、Vulkan です。
TensorFlow Lite のロードマップ にも、GPU Delegate のバックエンドとして、今後 Vulkan がサポートされることが列挙されています。
幸い、EdgeTPU DevBoard の GPU は Vulkan にも対応している ので、うまくいけば、GPU Delegate Vulkan版 も動かせるかもしれません。
(下記画像は DevBoard データシート画面のキャプチャ)
そんなことを夢見ながら EdgeTPU DevBoard 上での Vulkan 環境について調べてみると、Vulkan 1.0 なら動かせそうだ ということが分かりました。
本記事では、DevBoard での Vulkan 環境について確認できたことをまとめます。
(注)前回同様、EdgeTPU DevBoard 上で作業しますが、EdgeTPU アクセラレータは使いません。使うのはGPUです。
2. Vulkan 関連ファイルの確認
2.1 プリインストールファイル
DevBoard 上で Vulkan を動かすために必要なライブラリは、DevBoard上に最初から存在しているようです。
このライブラリとリンクすれば、Vulkan アプリを動かせそうです。
mendel@indigo-calf:~$ ls -l /usr/lib/vivante/
total 19000
lrwxrwxrwx 1 root root 14 Nov 8 21:45 libvulkan.so -> libvulkan.so.1
-rw-r--r-- 1 root root 571944 Nov 8 21:45 libvulkan.so.1
-rw-r--r-- 1 root root 380912 Nov 8 21:45 libSPIRV_viv.so
-rw-r--r-- 1 root root 5990448 Nov 8 21:45 libVSC.so
(以下略)
2.2 apt パッケージ
さらに、DevBoard 上で Vulkan 関係のパッケージを apt 検索すると、いろいろ出てきます。
なんかもう、apt install するだけで vulkan アプリ動かせそうな気になってきます。
mendel@indigo-calf:~$ apt search vulkan
Sorting... Done
Full Text Search... Done
dxvk/mendel-day 0.96+ds1-1 all
Vulkan-based translation layer for Direct3D 10/11
libvkd3d-dev/mendel-day 1.1-3 arm64
Direct3D 12 to Vulkan translation - development files
libvkd3d-utils1/mendel-day 1.1-3 arm64
Direct3D 12 to Vulkan translation - utilities library
libvkd3d1/mendel-day 1.1-3 arm64
Direct3D 12 to Vulkan translation - library
libvulkan-dev/mendel-day,now 1.1.97-2 arm64 [installed]
Vulkan loader library -- development files
libvulkan1/mendel-day,now 1.1.97-2 arm64 [installed,automatic]
Vulkan loader library
mesa-vulkan-drivers/mendel-day 18.3.6-2 arm64
Mesa Vulkan graphics drivers
vkd3d-demos/mendel-day 1.1-3 arm64
Direct3D 12 to Vulkan translation - demos
vulkan-tools/mendel-day,now 1.1.97+dfsg1-2 arm64 [installed]
Miscellaneous Vulkan utilities
vulkan-utils/mendel-day 1.1.97+dfsg1-2 all
transitional package
vulkan-validationlayers/mendel-day 1.1.97-2 arm64
Vulkan validation layers
vulkan-validationlayers-dev/mendel-day 1.1.97-2 arm64
Vulkan validation layers -- development files
3. vulkaninfo による Vulkan デバイスクエリ
予想通り、apt を使って vulkaninfo ツールをインストールするだけで、いとも簡単に「DevBoard の GPU がどのようなVulkanデバイスとして見えるのか」を確認することができました。
mendel@indigo-calf:~$ sudo apt install vulkan-tools
mendel@indigo-calf:~$ vulkaninfo --html
なお vulkaninfo は、引数に --html
をつければ、ちょっとオシャレで見やすいhtml形式で出力してくれるので便利です。

vulkaninfo 結果から、Vulkan 1.0 (device type = INTEGRATED_GPU) のデバイスとして、ちゃんと見えることが確認できました。
4. デバイス Query アプリの自前ビルド
ここまで1行もソースを書かずビルドもせず Vulkan 環境の確認をしてきましたが、ここからは、自分で Vulkan アプリをビルド、動作確認してみます。
動かすアプリは、上記 vulkaninfo のソース を参考に、デバイスQueryに必要な最小限を切り出した自前アプリとします。
4.1 Vulkan ヘッダファイルのインストール
DevBoard 上には、Vulkan アプリのビルドに必要な vulkan.h
がプリインストールされていないようなので、apt install libvulkan-dev
でインストールします。
なお、この作業により、 /usr/lib/aarch64-linux-gpu/libvulkan.so
もおまけでインストールされますが、このライブラリは DevBoard 上で動作しません。ファイル名が libvulkan.so.1.1.97
なので、「ひょっとして Vulkan 1.1 が使えるのかも」、と淡い期待をもって実験してみましたが、残念ながら、Vulkan 初期化時に呼び出す vkCreateInstance() 関数が VK_ERROR_INCOMPATIBLE_DRIVER エラーを返すため、使えませんでした。
アプリビルド時・実行時は、DevBoard にプレインストールされている /usr/lib/vivante/libvulkan.so
を使いましょう。
# Vulkan ヘッダファイルのインストール
mendel@indigo-calf:~$ sudo apt install libvulkan-dev
# インストールされたヘッダファイル確認
mendel@indigo-calf:~$ ll /usr/include/vulkan/
total 2800
-rw-r--r-- 1 root root 1580 Jan 13 2019 vulkan.h
(以下略)
# おまけでインストールされる vulkan ライブラリ。このライブラリは vulkanインタンス初期化でエラー
mendel@indigo-calf:~$ ll /usr/lib/aarch64-linux-gnu/
lrwxrwxrwx 1 root root 14 Jan 23 2019 libvulkan.so -> libvulkan.so.1
lrwxrwxrwx 1 root root 19 Jan 23 2019 libvulkan.so.1 -> libvulkan.so.1.1.97
-rw-r--r-- 1 root root 350808 Jan 23 2019 libvulkan.so.1.1.97
(以下略)
4.2 Query アプリの実装
上記 vulkaninfo のソース を参考に、デバイスQueryに必要な最小限を切り出します。
下記はその一部分抜粋です。とくに目新しいコードではありませんが、ご参考までに、私が実験したソースコード全体は、ここ で公開しています。
# include <vulkan/vulkan.h>
VkPhysicalDevice
query_vulkan_device(VkInstance vk_instance)
{
VkResult err;
uint32_t gpu_count, i, j;
VkPhysicalDevice phydev, *phydev_array;
err = vkEnumeratePhysicalDevices(vk_instance, &gpu_count, NULL);
assert(err == VK_SUCCESS);
fprintf(stderr, "\n");
fprintf(stderr, "-----------------------------------------------------\n");
fprintf(stderr, " Physical Devices count : %d\n", gpu_count);
fprintf(stderr, "-----------------------------------------------------\n");
if (gpu_count == 0)
{
fprintf(stderr, "vkEnumeratePhysicalDevices() returned no devices.\n");
return NULL;
}
phydev_array = malloc(sizeof(VkPhysicalDevice) * gpu_count);
err = vkEnumeratePhysicalDevices(vk_instance, &gpu_count, phydev_array);
assert(err == VK_SUCCESS);
for (i = 0; i < gpu_count; i ++)
{
fprintf(stderr, " \n");
fprintf(stderr, " ##### Device[%d/%d] #####\n", i, gpu_count);
/* ------------------------------------ *
* PhysicalDeviceProperties
* ------------------------------------ */
phydev = phydev_array[i];
VkPhysicalDeviceProperties dev_props;
vkGetPhysicalDeviceProperties(phydev, &dev_props);
fprintf(stderr, " \n");
fprintf(stderr, " ------ PhysicalDeviceProperties\n");
fprintf(stderr, " deviceName : %s\n", dev_props.deviceName);
fprintf(stderr, " deviceType : %s\n", get_vkdevtype(dev_props.deviceType));
fprintf(stderr, " apiVersion : %d.%d.%d\n",
VK_VERSION_MAJOR(dev_props.apiVersion),
VK_VERSION_MINOR(dev_props.apiVersion),
VK_VERSION_PATCH(dev_props.apiVersion));
fprintf(stderr, " driverVersion: 0x%x\n", dev_props.driverVersion);
fprintf(stderr, " vendorID : 0x%x\n", dev_props.vendorID);
fprintf(stderr, " deviceID : 0x%x\n", dev_props.deviceID);
(以下略)
4.3 Queryアプリのビルド
上記ソースコードは、DevBoard 上でネイティブビルドすれば、至ってシンプルにビルドすることができます。
念のため、ライブラリパスを明記して、プリイントール版の libvulkan.so
を使うようにしています。
# Queryアプリのビルド
mendel@indigo-calf:~/work/VulkanSample/query_vk_devices$ gcc -L/usr/lib/vivante main.c -lvulkan
# ビルド生成物
mendel@indigo-calf:~/work/VulkanSample/query_vk_devices$ ls -l a.out
-rwxr-xr-x 1 mendel mendel 27528 Nov 23 05:30 a.out*
# 念のため依存ライブラリを確認
mendel@indigo-calf:~/work/VulkanSample/query_vk_devices$ ldd ./a.out
linux-vdso.so.1 (0x0000ffffa66bc000)
libvulkan.so.1 => /usr/lib/vivante/libvulkan.so.1 (0x0000ffffa65dc000)
libstdc++.so.6 => /usr/lib/aarch64-linux-gnu/libstdc++.so.6 (0x0000ffffa6451000)
libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffffa6394000)
libgcc_s.so.1 => /lib/aarch64-linux-gnu/libgcc_s.so.1 (0x0000ffffa6370000)
libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffffa61fe000)
libGAL.so => /usr/lib/vivante/libGAL.so (0x0000ffffa610a000)
libSPIRV_viv.so => /usr/lib/vivante/libSPIRV_viv.so (0x0000ffffa609e000)
libVSC.so => /usr/lib/vivante/libVSC.so (0x0000ffffa5b24000)
libGLSLC.so => /usr/lib/vivante/libGLSLC.so (0x0000ffffa5a26000)
libwayland-client.so.0 => /usr/lib/aarch64-linux-gnu/libwayland-client.so.0 (0x0000ffffa5a07000)
/lib/ld-linux-aarch64.so.1 (0x0000ffffa668e000)
libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000ffffa59f3000)
librt.so.1 => /lib/aarch64-linux-gnu/librt.so.1 (0x0000ffffa59db000)
libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000ffffa59ac000)
libffi.so.6 => /usr/lib/aarch64-linux-gnu/libffi.so.6 (0x0000ffffa5994000)
4.4 queryアプリ実行結果
上記アプリを DevBoard 上で実行すると、下記のようなQuery結果が表示されます。
自前ビルドしたアプリでも、apt でインストールした vulkaninfo と同様、Vulkan 1.0 (device type = INTEGRATED_GPU) のデバイスとして、ちゃんと見えることが確認できました。
Vulkan Instance Version = 1.0.0
-----------------------------------------------------
Instance Extension (GLOBAL) count : 5
-----------------------------------------------------
VK_EXT_debug_report ver: 8
VK_KHR_get_physical_device_properties2 ver: 1
VK_KHR_surface ver:25
VK_KHR_display ver:21
VK_KHR_wayland_surface ver: 6
-----------------------------------------------------
Instance Layer count : 0
-----------------------------------------------------
-----------------------------------------------------
Physical Devices count : 1
-----------------------------------------------------
##### Device[0/1] #####
------ PhysicalDeviceProperties
deviceName : VeriSilicon
deviceType : INTEGRATED_GPU
apiVersion : 1.0.59
driverVersion: 0x1802004
vendorID : 0x10002
deviceID : 0x70006214
limits.maxImageDimension1D: 8192
limits.maxImageDimension2D: 8192
limits.maxImageDimension3D: 512
limits.maxImageDimensionCube: 8192
(snipped)
sparseProp.residencyStandard2DBlockShape : 0
sparseProp.residencyStandard2DMultisampleBlockShape: 0
sparseProp.residencyStandard3DBlockShape : 0
sparseProp.residencyAlignedMipSize : 0
sparseProp.residencyNonResidentStrict : 0
------ ExtensionProperties count = 2
VK_KHR_maintenance1 (ver:1)
VK_KHR_swapchain (ver:68)
------ QueueFamilyProperties count = 1
QueueFamily[0/1]
queueFlags : GRAPHICS, COMPUTE, TRANSFER,
queueCount : 1
timestampValidBits : 0
minImgTransGranularity: (1, 1, 1)
------ PhysicalDeviceFeatures
robustBufferAccess : 1
fullDrawIndexUint32 : 0
imageCubeArray : 1
independentBlend : 1
geometryShader : 0
tessellationShader : 0
sampleRateShading : 0
shaderFloat64 : 0
shaderInt64 : 0
shaderInt16 : 0
(snipped)
------ PhysicalDeviceMemoryProperties
memoryTypeCount = 1
memoryType[0/1]
heapIndex : 0
propertyFlags: 0x00000007
DEVICE_LOCAL_BIT
HOST_VISIBLE_BIT
HOST_COHERENT_BIT
memoryHeapCount = 1
memoryHeap[0/1]
size : 768 [MB]
flags : 0x00000001
DEVICE_LOCAL_BIT
------ PhysicalDeviceFormatProperties
[VK_FORMAT_R8G8B8A8_UINT]
linearTilingFeatures : 0x0000cc87
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
VK_FORMAT_FEATURE_BLIT_SRC_BIT
VK_FORMAT_FEATURE_BLIT_DST_BIT
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
VK_FORMAT_FEATURE_TRANSFER_DST_BIT
optimalTilingFeatures: 0x0000cc87
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
VK_FORMAT_FEATURE_BLIT_SRC_BIT
VK_FORMAT_FEATURE_BLIT_DST_BIT
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
VK_FORMAT_FEATURE_TRANSFER_DST_BIT
bufferFeatures : 0x00000078
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
[VK_FORMAT_R8G8B8A8_UNORM]
linearTilingFeatures : 0x00000000
optimalTilingFeatures: 0x0000dd87
VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
VK_FORMAT_FEATURE_BLIT_SRC_BIT
VK_FORMAT_FEATURE_BLIT_DST_BIT
VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
VK_FORMAT_FEATURE_TRANSFER_DST_BIT
bufferFeatures : 0x00000078
VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT
VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
(snipped)
5.最後に
EdgeTPU DevBoard上で、Vulkan デバイスクエリができました。
サポートしている Vulkan バージョンが 1.0 と少し古いのが気になりますが、
もし、TensorFlow Lite GPU Delegate が要求する Vulkan バージョンが 1.0 なら、DevBoard 上での動作に挑戦したいと思います。
そして、GPU Delegate のバックエンド3兄弟 (OpenGLES/OpenCL/Vulkan) でガチンコ勝負できればいいなと思っています。