TadaoYamaokaの日記

山岡忠夫Homeで公開しているプログラムの開発ネタを中心に書いていきます。

dlshogiのOpenCL対応 その1

dlshogiをOpenCLに対応させたいと思っている。
現在のdlhsogiはTensorRTを使用しているため、再配布の制限があり、環境構築が大変になっている。
OpenCLは、必要なdllを同梱すれば環境構築が不要になるので利用者にメリットがある。

OpenCLのコードを一から作成するのは難易度が高すぎるので、KataGoで、OpenCLでTensorCoreを使う実装がされているので、ソースを流用して対応しようと思っている。

OpenCLのチューニング処理

今回は、KataGoのソースの内、OpenCLのチューニングを行う部分だけ抜き出して試してみた。
OpenCL 1.2は、OpenCL C言語のソースを文字列でライブラリに渡す仕組み(オンラインコンパイル)で、KataGoではOpenCLのソースで使用するパラメータを初回にチューニングして、ソースにパラメータを埋め込んで編集するようにしている。
行列演算(gemm)と、畳み込み演算で使うパラメータがチューニング対象になっている。

ソース修正

KataGoのチューニングの処理は、KataGoのモデルに特化したテストを行っているため、そのままではdlshogiのモデルでは使用できない箇所があった。
具体的には、盤のサイズが19x19でなくて、9x9になる。
また、KataGoは入力層が5x5の畳み込みになっているので、conv5x5のテストがあるが、dlshogiでは不要である。
また、グローバルプーリングに特化した処理もあったがdlshogiでは不要である。
畳み込みの入力チャネルサイズと出力チャネルサイズのパターンもdlshogiに合わせた変更が必要であった。

依存しているソースが多かったので諸々スリムにして、最小限のソースで試せるようにした。
opencltune/tune at master · TadaoYamaoka/opencltune · GitHub

実行結果

チューニングを実行すると以下のように表示される。

Found OpenCL Platform 0: NVIDIA CUDA (NVIDIA Corporation) (OpenCL 1.2 CUDA 11.2.152)
Found 1 device(s) on platform 0 with type CPU or GPU or Accelerator
Found OpenCL Device 0: GeForce RTX 3090 (NVIDIA Corporation) (score 11000102)
Creating context for OpenCL Platform: NVIDIA CUDA (NVIDIA Corporation) (OpenCL 1.2 CUDA 11.2.152)
Using OpenCL Device 0: GeForce RTX 3090 (NVIDIA Corporation) OpenCL 1.2 CUDA (Extensions: 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_fp64 cl_khr_byte_addressable_store cl_khr_icd cl_khr_gl_sharing cl_nv_compiler_options cl_nv_device_attribute_query cl_nv_pragma_unroll cl_nv_d3d10_sharing cl_khr_d3d10_sharing cl_nv_d3d11_sharing cl_nv_copy_opts cl_nv_create_buffer cl_khr_int64_base_atomics cl_khr_int64_extended_atomics cl_khr_device_uuid)
Beginning GPU tuning for GeForce RTX 3090 channels 224
Setting winograd3x3TileSize = 4
------------------------------------------------------
Tuning xGemmDirect for 1x1 convolutions and matrix mult
Testing 56 different configs
Tuning 0/56 (reference) Calls/sec 16094.4 L2Error 0 WGD=8 MDIMCD=1 NDIMCD=1 MDIMAD=1 NDIMBD=1 KWID=1 VWMD=1 VWND=1 PADA=1 PADB=1
Tuning 1/56 Calls/sec 16281.7 L2Error 0 WGD=8 MDIMCD=1 NDIMCD=1 MDIMAD=1 NDIMBD=1 KWID=1 VWMD=1 VWND=1 PADA=1 PADB=1
Tuning 2/56 Calls/sec 86246.6 L2Error 0 WGD=8 MDIMCD=8 NDIMCD=8 MDIMAD=8 NDIMBD=8 KWID=1 VWMD=1 VWND=1 PADA=1 PADB=1
Tuning 3/56 Calls/sec 112680 L2Error 0 WGD=16 MDIMCD=8 NDIMCD=8 MDIMAD=8 NDIMBD=8 KWID=1 VWMD=1 VWND=1 PADA=1 PADB=1
Tuning 20/56 ...
Tuning 40/56 ...
------------------------------------------------------
Tuning xGemm for convolutions
Testing 70 different configs
Tuning 0/70 (reference) Calls/sec 2668.78 L2Error 0 MWG=8 NWG=8 KWG=8 MDIMC=1 NDIMC=1 MDIMA=1 NDIMB=1 KWI=1 VWM=1 VWN=1 STRM=0 STRN=0 SA=0 SB=0
Tuning 1/70 Calls/sec 2675.99 L2Error 0 MWG=8 NWG=8 KWG=8 MDIMC=1 NDIMC=1 MDIMA=1 NDIMB=1 KWI=1 VWM=1 VWN=1 STRM=0 STRN=0 SA=0 SB=0
Tuning 2/70 Calls/sec 13413.4 L2Error 0 MWG=8 NWG=8 KWG=8 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=1 VWM=1 VWN=1 STRM=0 STRN=0 SA=0 SB=0
Tuning 3/70 Calls/sec 20150.1 L2Error 0 MWG=16 NWG=16 KWG=16 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=1 VWM=1 VWN=1 STRM=0 STRN=0 SA=0 SB=0
Tuning 4/70 Calls/sec 26924.6 L2Error 0 MWG=16 NWG=16 KWG=16 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=2 VWN=2 STRM=0 STRN=0 SA=0 SB=0
Tuning 9/70 Calls/sec 27470.9 L2Error 0 MWG=16 NWG=16 KWG=32 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=2 VWN=2 STRM=0 STRN=0 SA=0 SB=0
Tuning 17/70 Calls/sec 29074.5 L2Error 0 MWG=32 NWG=32 KWG=32 MDIMC=16 NDIMC=8 MDIMA=16 NDIMB=8 KWI=2 VWM=2 VWN=2 STRM=0 STRN=0 SA=1 SB=1
Tuning 22/70 Calls/sec 36589.1 L2Error 0 MWG=64 NWG=64 KWG=32 MDIMC=16 NDIMC=8 MDIMA=16 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
Tuning 24/70 Calls/sec 39082.6 L2Error 0 MWG=64 NWG=64 KWG=32 MDIMC=16 NDIMC=16 MDIMA=16 NDIMB=16 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
Tuning 31/70 Calls/sec 39529.5 L2Error 0 MWG=32 NWG=32 KWG=32 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
Tuning 44/70 Calls/sec 41162 L2Error 0 MWG=32 NWG=32 KWG=16 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
Tuning 60/70 ...
------------------------------------------------------
Tuning hGemmWmma for convolutions
Testing 146 different configs
Tuning 0/146 (reference) Calls/sec 71175 L2Error 0 MWG=16 NWG=16 KWG=16 MWAVE=16 NWAVE=16 MWARP=16 NWARP=16 VWM=2 VWN=2 SA=0 SB=0
Tuning 1/146 Calls/sec 77126.9 L2Error 0 MWG=16 NWG=16 KWG=16 MWAVE=16 NWAVE=16 MWARP=16 NWARP=16 VWM=2 VWN=2 SA=0 SB=0
Tuning 20/146 ...
Tuning 40/146 ...
Tuning 60/146 ...
Tuning 64/146 Calls/sec 87848.6 L2Error 0 MWG=32 NWG=32 KWG=16 MWAVE=32 NWAVE=8 MWARP=32 NWARP=8 VWM=2 VWN=2 SA=0 SB=0
Tuning 80/146 ...
Tuning 96/146 Calls/sec 88581 L2Error 0 MWG=32 NWG=32 KWG=32 MWAVE=16 NWAVE=16 MWARP=16 NWARP=16 VWM=2 VWN=2 SA=0 SB=0
Tuning 120/146 ...
Tuning 140/146 ...
Enabling FP16 tensor cores due to better performance
------------------------------------------------------
Using FP16 storage!
Using FP32 compute!
Using FP16 tensor cores!
------------------------------------------------------
Tuning winograd transform for convolutions
Testing 47 different configs
Tuning 0/47 (reference) Calls/sec 34136.7 L2Error 0  transLocalSize0=1 transLocalSize1=1
Tuning 1/47 Calls/sec 34885.4 L2Error 0  transLocalSize0=1 transLocalSize1=1
Tuning 2/47 Calls/sec 184904 L2Error 0  transLocalSize0=128 transLocalSize1=2
Tuning 8/47 Calls/sec 217745 L2Error 0  transLocalSize0=16 transLocalSize1=2
Tuning 9/47 Calls/sec 230045 L2Error 0  transLocalSize0=64 transLocalSize1=1
Tuning 20/47 ...
Tuning 40/47 ...
------------------------------------------------------
Tuning winograd untransform for convolutions
Testing 111 different configs
Tuning 0/111 (reference) Calls/sec 58050.2 L2Error 0  untransLocalSize0=1 untransLocalSize1=1 untransLocalSize2=1
Tuning 1/111 Calls/sec 58849.8 L2Error 0  untransLocalSize0=1 untransLocalSize1=1 untransLocalSize2=1
Tuning 2/111 Calls/sec 173990 L2Error 0  untransLocalSize0=8 untransLocalSize1=1 untransLocalSize2=8
Tuning 4/111 Calls/sec 210017 L2Error 0  untransLocalSize0=8 untransLocalSize1=2 untransLocalSize2=4
Tuning 20/111 ...
Tuning 32/111 Calls/sec 211785 L2Error 0  untransLocalSize0=8 untransLocalSize1=4 untransLocalSize2=4
Tuning 40/111 Calls/sec 236954 L2Error 0  untransLocalSize0=8 untransLocalSize1=4 untransLocalSize2=2
Tuning 60/111 ...
Tuning 80/111 ...
Tuning 100/111 ...
Done tuning
------------------------------------------------------

パラメータの組み合わせのテストを実行してスループットが計測されている。
TensorCoreも使用できている。

チューニングを実行した結果、以下のようにパラメータが保存された。

VERSION=8
#shouldUseFP16Storage
1
#shouldUseFP16Compute
0
#shouldUseFP16TensorCores
1
#xGemmDirect
WGD=16 MDIMCD=8 NDIMCD=8 MDIMAD=8 NDIMBD=8 KWID=1 VWMD=1 VWND=1 PADA=1 PADB=1
#xGemm
MWG=32 NWG=32 KWG=16 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
#xGemm16
MWG=32 NWG=32 KWG=16 MDIMC=8 NDIMC=8 MDIMA=8 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
#hGemmWmma
MWG=32 NWG=32 KWG=32 MWAVE=16 NWAVE=16 MWARP=16 NWARP=16 VWM=2 VWN=2 SA=0 SB=0
#conv3x3
INTILE_XSIZE=6 INTILE_YSIZE=6 OUTTILE_XSIZE=4 OUTTILE_YSIZE=4 transLocalSize0=64 transLocalSize1=1 untransLocalSize0=8 untransLocalSize1=4 untransLocalSize2=2

KataGoを初回起動して実行されたチューニングで保存された結果は、以下の通りになる。

VERSION=8
#shouldUseFP16Storage
1
#shouldUseFP16Compute
0
#shouldUseFP16TensorCores
1
#xGemmDirect
WGD=32 MDIMCD=8 NDIMCD=8 MDIMAD=16 NDIMBD=16 KWID=8 VWMD=2 VWND=2 PADA=1 PADB=1
#xGemm
MWG=64 NWG=64 KWG=32 MDIMC=16 NDIMC=8 MDIMA=16 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
#xGemm16
MWG=64 NWG=64 KWG=32 MDIMC=16 NDIMC=8 MDIMA=16 NDIMB=8 KWI=2 VWM=4 VWN=4 STRM=0 STRN=0 SA=1 SB=1
#hGemmWmma
MWG=64 NWG=64 KWG=64 MWAVE=16 NWAVE=16 MWARP=16 NWARP=16 VWM=2 VWN=2 SA=0 SB=0
#conv3x3
INTILE_XSIZE=6 INTILE_YSIZE=6 OUTTILE_XSIZE=4 OUTTILE_YSIZE=4 transLocalSize0=128 transLocalSize1=1 untransLocalSize0=8 untransLocalSize1=4 untransLocalSize2=1
#conv5x5
INTILE_XSIZE=6 INTILE_YSIZE=6 OUTTILE_XSIZE=2 OUTTILE_YSIZE=2 transLocalSize0=128 transLocalSize1=1 untransLocalSize0=8 untransLocalSize1=4 untransLocalSize2=1
#gPool
XYSTRIDE=16 CHANNELSTRIDE=2 BATCHSTRIDE=1

ベストなパラメータがdlshogi向けと比べて変わっているのが確認できる。

まとめ

OpenCL対応のとっかかりとして、KataGoのチューニング処理を抜き出して試してみた。
これで、行列演算と畳み込み演算という基本部品は動かせるようになった。
次はdlshogiモデルの推論処理を試す予定だが、KataGoとdlshogiのモデルの違いから、OpenCL C言語のソースを修正する必要がある。
OpenCLのコードの理解して修正する必要があり、まだ先は長そうである。