トホホな疑問(10) cuDNN, サンプル動かないのもある

Jetson Nano楽しく使っております。JETPACK SDKという名のもとにインストールされているライブラリなどを順次確かめてみてもおります。今回は、DNN用のcuDNNというライブラリのサンプルプログラムを動かしてみていたときの疑問です。まあ、インストールイメージに含まれていたソースと言えども、必ずしも全てがJetson Nanoでは動かない、というだけのことなんでありますが。動かす前に気が付かないでいると、動かした後で何で?となるのです。

※「トホホな疑問」投稿順Indexはこちら

まずはcuDNNです。ご存知ない方向けに一言で言えば、GPUでDeep Learningするためのライブラリです。GPUをグラフィクスでなく汎用計算に使用するための仕組みであるCUDAの上で動作するライブラリの一つ。Deep Learningというとフレームワークと呼ばれるような、ソフトウエアシステムがいろいろありますが、それらの多くは「高水準」「抽象度高」でPythonのようなスクリプト言語で操作するものが多いと思います。それに対してcuDNNはC/C++のレベルで呼び出すライブラリ。フレームワークなどを下から支えるレベル(あからさまな計算を担う)のライブラリと言えるでしょう。コンボリューションレイヤとか、ReLUとか、ディープラーニングで使われる基本演算要素的なものを実装しているもの。実際多くのフレームワークがcuDNNを「使役して」いるようです。

さて、Jetson NanoにNvidia社の推奨手順通りにUbuntuをインストールしたならば、以下のフォルダにcuDNNのサンプルソースが格納されている筈(当然、cuDNNライブラリも使える状態になっている筈)です。

/usr/src/cudnn_samples_v7

上のディレクトリ配下には以下の3つのサンプルプログラムのサブディレクトリが格納されています。今回の疑問は、最初のconv_sampleに関するものです。

  • conv_sample
  • mnistCUDNN
  • RNN

例によってAI版Hello worldであるmnistのcuDNNでの実装版(とは言え以前試してみたmnistの学習プログラムではなく、既に学習済の係数を使って識別するものです)や、RNN(Recurrent Neural Network)にも使えるよ、といった感じで並んでいます。実際サンプルをいろいろ弄ってみたりするときには、これらの上位の cudnn_samples_v7以下をツリーまるごと作業用のディレクトリにコピーしてしまうのが良いようです。それぞれのサンプルディレクトリ内にMakefileが入っているので、基本 make 一発でサンプルがビルドできますが、それらMakefileはcudnn_samples_v7直下にある

samples_common.mk

を内部で呼んでいるのでツリーでコピるのが簡単です。

今回調べてみた conv_sampleは、DNNの基本中の基本かつ、もっとも計算負荷が重くなる筈のコンボリューション・レイヤの「いろいろ」なパラメータについて仮に(適当な数字で)動かしてみる、というサンプルプログラムです。一番重くてパラメータも多いコンボリューション・レイヤを使えれば、後のプーリング・レイヤその他は赤子の手を捻るようなもの(非人道的たとえ)、ということでしょうかね。前述の通りビルドは簡単にできます。また実行については

run_conv_sample.sh

というスクリプトが同じディレクトリに置かれているので、これを実行すれば良いです。サンプルプログラムは、1枚のコンボリューション・レイヤをテストしてみるだけのものですが、コマンドラインから与えるべきパラメータ数がとても多いです。また、そのパラメータは、ちゃんとcuDNNが想定しているパラメータ記法を理解していないと設定不能(多分直ぐ忘れるので、調べたことを次回にでもメモっておくつもりです)。とりあえず走らせてcuDNNがちゃんと動作していることを確かめるという目的であれば、上のサンプルスクリプトをそのまま実行するのが一番簡単。

$ ./run_conv_sample.sh
Using format CUDNN_TENSOR_NCHW (for INT8x4 and INT8x32 tests use CUDNN_TENSOR_NCHW_VECT_C)
Testing single precision
====USER DIMENSIONS====
input dims are 1, 2048, 7, 7
filter dims are 512, 2048, 1, 1
output dims are 1, 512, 7, 7
====PADDING DIMENSIONS====
padded input dims are 1, 2048, 7, 7
padded filter dims are 512, 2048, 1, 1
padded output dims are 1, 512, 7, 7
Testing conv
^^^^ CUDA : elapsed = 0.00181603 sec,
Test PASSED
Testing half precision (math in single precision)
====USER DIMENSIONS====
input dims are 1, 2048, 7, 7
filter dims are 512, 2048, 1, 1
output dims are 1, 512, 7, 7
====PADDING DIMENSIONS====
padded input dims are 1, 2048, 7, 7
padded filter dims are 512, 2048, 1, 1
padded output dims are 1, 512, 7, 7
Testing conv
^^^^ CUDA : elapsed = 0.00157499 sec,
Test PASSED

~途中略~

Using format CUDNN_TENSOR_NCHW_VECT_C (for single and double precision tests use a different format)
Device version 53 does not support int8x4!
Device version 53 does not support int8x32!
~以下略~

上のように、最初はパラメータ毎に単精度浮動小数でのテストと結果、半精度浮動小数でのテストと結果という具合に2個ずつ結果を出してきます。しかし、後半、

Device version 53 does not support

などというツレナイお言葉がずらずらと出力されてきます。その数を数えること18回!

Device versionというお言葉が書かれていますが、推測するにこれは、Nvidia社が公式的には以下のように呼んでいるものでしょう。

Compute Capabilities

いろいろな世代のGPUが、それぞれどのような機能をサポートしているのかを示すための数字。Jetson Nanoについては、以前ボードをセットアップしたときに、真っ先にビルドしてみた

deviceQuery

プログラムを動作させれば、報告があがってきます。

$ ./deviceQuery
./deviceQuery Starting...

CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 1 CUDA Capable device(s)

Device 0: "NVIDIA Tegra X1"
CUDA Driver Version / Runtime Version 10.0 / 10.0
CUDA Capability Major/Minor version number: 5.3
~以下略~

ソフトウエア的には Jetson nanoはこう見えているという数字。上のように、

CUDA Capability Major/Minor version number: 5.3

でした。

まあ、上のようにQuery動かさなくても、Nvidia社のホームページへ行けば、どのボードなどがどんなCompute Capabilityであるのかは列挙されています。そこを見ても、Jetson Nanoが 5.3 であることは明らかです。

しかし、ちょっと探し回ってしまったのが、どのバージョンが何をサポートしていて、何をサポートしていないかという点。Nvidia社のドキュメントの中で一番まともにそれを書いてあるように思えたのが以下の表とそれに続く Table.14です。

Table 13. Feature Support per Compute Capability

2つの表に大量の情報が列挙されており、当然 Compute Capability 5.3も表に含まれてはいるのですが、肝心なところ、私の知りたいことは含まれていないように見えます。

does not support int8x4!

とか

does not support int8x32!

という件。

GPUがDNN用にINT8型式の演算をサポートしたことについては、話題になったのでネット・ニュースなどで各所で取り上げられていました。Nvidia社の公式ドキュメントでなく、ちょっと古いニュースみていて理解しました。

一応、その境目のところを掻い摘んで書き留めておくと

Compute Capability 5.x は Maxwell世代。Maxwell世代で世間的に名が知られているグラボのGeForce GTXは5.0か5.2。5.3というのは珍しく、Jetson X1(Jetson nano)のみのようです。なお、半精度浮動小数のサポートは、5.3以上。実際、Jetson nano上で半精度使えているように見える。

Compute Capability 6.xは Pascal世代。この世代のGeForce GTXは6.1。INT8のサポートはPascal以降。

なお、現行のGeForce RTXなどは Turing 世代で、多くは、Compute Capability 7.5のようです。

つまり、Jetson nanoではINT8使えない。サンプルプログラムがエラーで報告している通り。トホホ。

トホホな疑問(9) ラズパイのBogoMipsのなぜ?

トホホな疑問(11) Python、空listの繰り返し へ進む