Open3

cudnn graph api sample

bokutotubokutotu

cudnnのgraph apiでは、全ての設定をcudnnBackendSetAttribute(https://docs.nvidia.com/deeplearning/cudnn/v9.2.0/api/cudnn-graph-library.html#cudnn-backend-tensor-descriptor)で行うっぽい。
設定の基本となる型は、cudnnBackendDescriptor_t
このオブジェクトはcudnnBackendCreateDescriptorで作成する。
作成したディスクリプターにcudnnBackendSetAttributeで下記に書いた必要な設定を追加し、cudnnBackendFinalizeで設定を決定する。
結構ひどい設計だと思うけどこれでいいんかと強く思うが、これが今後推奨されるらしい。
性質の違う設定を同じAPIで設定するのはソフトウェアの設計としてはいいものとは私は思わない。(cudnn_frontendを使えというのはわかるが、私はcudnnをRustから使いたいので、生のcudnnを理解しないといけない(cudnn_frontendはヘッダーオンリーなので多分bindgenできない))

bokutotubokutotu

Tensor

https://docs.nvidia.com/deeplearning/cudnn/v9.2.0/api/cudnn-graph-library.html#cudnn-backend-tensor-descriptor
必要なアトリビュート

CUDNN_ATTR_TENSOR_UNIQUE_ID

  • テンソルを識別するためのユニークな数字
  • データ型はint64_t(CUDNN_TYPE_INT64) で一つの要素
  • このユニークな数字というは、cudnnのグローバルでユニークなのか、それとも、レイヤーごとにユニークなのかがわからない。
  • 必須

CUDNN_ATTR_TENSOR_DATA_TYPE

  • テンソルのデータ型
  • CUDNN_TYPE_INT64で1つの要素
  • 必須

CUDNN_ATTR_TENSOR_DIMENSIONS

  • テンソルのshape
  • CUDNN_TYPE_INT64で、長さとその配列の先頭ポインタを渡す

CUDNN_ATTR_TENSOR_STRIDES

  • テンソルのstride
  • CUDNN_TYPE_INT64で長さとその配列の先頭ポインタを渡す

CUDNN_ATTR_TENSOR_IS_VIRTUAL

  • virtualなテンソルかどうか
  • デフォルトはfalse
  • virtualなテンソルとは、レイヤーの中間的なもので他のところからはアクセスされないもの。

CUDNN_ATTR_TENSOR_BYTE_ALIGNMENT

  • byte alignment
  • なぜ、DATA_TYPEの部分で推論できないのか??

Tensorのディスクリプたを生成するコード

cudnnBackendDescriptor_t tensorDescriptorCreate(
  int64_t numDim, 
  int64_t *dim, 
  int64_t *stride, 
  int64_t byteAlignment, 
  cudnnDataType_t dataType, 
  int64_t name
) {
  cudnnBackendDescriptor_t tensorDesc;
  CHECK_CUDNN(cudnnBackendCreateDescriptor(CUDNN_BACKEND_TENSOR_DESCRIPTOR, &tensorDesc));
  CHECK_CUDNN(cudnnBackendSetAttribute(tensorDesc, 
                           CUDNN_ATTR_TENSOR_DATA_TYPE, CUDNN_TYPE_DATA_TYPE, 1, &dataType));
  CHECK_CUDNN(cudnnBackendSetAttribute(tensorDesc, 
                          CUDNN_ATTR_TENSOR_DIMENSIONS, CUDNN_TYPE_INT64, numDim, dim));
  CHECK_CUDNN(cudnnBackendSetAttribute(tensorDesc, 
                           CUDNN_ATTR_TENSOR_STRIDES, CUDNN_TYPE_INT64, numDim, stride));
  CHECK_CUDNN(cudnnBackendSetAttribute(tensorDesc, 
                           CUDNN_ATTR_TENSOR_BYTE_ALIGNMENT, CUDNN_TYPE_INT64, 1, &byteAlignment));
  CHECK_CUDNN(cudnnBackendSetAttribute(tensorDesc, 
                           CUDNN_ATTR_TENSOR_UNIQUE_ID, CUDNN_TYPE_INT64, 1, &name));
  CHECK_CUDNN(cudnnBackendFinalize(tensorDesc));

  return tensorDesc;
}
bokutotubokutotu

Normalization Layers

https://docs.nvidia.com/deeplearning/cudnn/v9.2.0/api/cudnn-graph-library.html#cudnn-backend-operation-norm-forward-descriptor

CUDNN_ATTR_OPERATION_NORM_FWD_MODE

CUDNN_ATTR_OPERATION_NORM_FWD_PHASE

訓練中or推論中
CUDNN_TYPE_NORM_FWD_PHASEのひとつの要素

CUDNN_ATTR_OPERATION_NORM_FWD_XDESC

入力のtensorディスクリプタ
CUDNN_TYPE_BACKEND_DESCRIPTORの一つの要素。

CUDNN_ATTR_OPERATION_NORM_FWD_MEAN_DESC

平均を突っ込むテンソルのディスクリプタ
https://github.com/NVIDIA/cudnn-frontend/blob/main/samples/cpp/norm/batchnorm.cppを見るに、
{1, channel, 1, 1}のshapeかつ{channel, 1, channel, channel}のストライドで入れないといけないらしい。

CUDNN_ATTR_OPERATION_NORM_FWD_INV_VARIANCE_DESC

フォワードとバックワード両方とも、途中計算で使うのでキャッシュしておくと訓練が早くなるぞー

CUDNN_ATTR_OPERATION_NORM_FWD_SCALE_DESC

スケール
必須

CUDNN_ATTR_OPERATION_NORM_FWD_BIAS_DESC

バイアス
必須

CUDNN_ATTR_OPERATION_NORM_FWD_EPSILON_DESC

割り算する時に0割しない要するやつ。必須

CUDNN_ATTR_OPERATION_NORM_FWD_INPUT_RUNNING_MEAN_DESC

runnning meanのやつ input

CUDNN_ATTR_OPERATION_NORM_FWD_INPUT_RUNNING_VAR_DESC

Running Var input

CUDNN_ATTR_OPERATION_NORM_FWD_OUTPUT_RUNNING_MEAN_DESC

runnning meanのoutput

CUDNN_ATTR_OPERATION_NORM_FWD_OUTPUT_RUNNING_VAR_DESC

output

CUDNN_ATTR_OPERATION_NORM_FWD_YDESC

output

CUDNN_ATTR_OPERATION_NORM_FWD_EXP_AVG_FACTOR_DESC

batch normでいうmomentum