DLProfでDeep LearningのGPUでの動作内容を把握してみた

GPU上でのDeep Learningの動作を簡単にプロファイリングできるツールが出たぞ

これでチューニングも簡単ですね

DLProfについて

Deep LearningのGPU上での動作を確認できるツールが出たようなのでどのような情報が確認できるか確かめてみました。

参考にしたのは下記の2つの記事です。本ブログではよくPyTorchを使用しているためPyTorchで動作確認しました。

https://docs.nvidia.com/deeplearning/frameworks/tensorboard-plugin-user-guide/index.html

https://docs.nvidia.com/deeplearning/frameworks/dlprof-user-guide/

構築環境

このブログではGoogle Colabをよく使用するのですが今回はDockerを使用していたので断念してローカル環境で動作確認しました。環境情報は下記です。

ハードウェア

  • CPU: Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz
  • Memory: 64GB
  • GPU: Geforce 2080 Ti

ソフトウェア

  • OS: Ubuntu 18.04
  • cuda: バージョン11.0
  • Graphics Driver: バージョン450.51.06
  • docker: 19.03.12

下記のコマンドでPytorchのコンテナを取得します。

docker pull nvcr.io/nvidia/pytorch:20.07-py3

下記のコマンドでDockerコンテナにアクセスします。

docker run --rm --gpus=0 --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 -it -p6008:6008 -v `pwd`:/pytorch nvcr.io/nvidia/pytorch:20.06-py3

ホストとパス連携したディレクトリに移動します。

cd /pytorch/

行列演算を高速化するTensorコアの動作も確認したいため、apexを導入します。

https://github.com/NVIDIA/apex

Tensorコアについては下記の記事をご覧ください。

https://www.nvidia.com/ja-jp/data-center/tensor-cores/

git clone https://github.com/NVIDIA/apex
cd apex
pip install -v --no-cache-dir --global-option="--cpp_ext" --global-option="--cuda_ext" ./

確認用コード

シンプルなpytorchのコードで動作確認します。

必要なライブラリをimportします。

import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.cuda.profiler as profiler
import torch.optim as optim
try:
    from apex import amp
except ImportError:
    raise ImportError("Please install apex from https://www.github.com/nvidia/apex to run this example.")
from tqdm import tqdm
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--amp", help="setting amp option",
                    action="store_true")
args = parser.parse_args()

PyTorchのプロファイリングツールを使用してGPU上の情報を取得できるようにします。

https://github.com/NVIDIA/PyProf

import pyprof
pyprof.init()

lenetモデルクラスを定義します。

class LeNet5(nn.Module):

    def __init__(self):
        super(LeNet5, self).__init__()
        # 1 input image channel, 6 output channels, 5x5 square convolution
        # kernel
        self.conv1 = nn.Conv2d(1, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        # an affine operation: y = Wx + b
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        # Max pooling over a (2, 2) window
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
        # If the size is a square you can only specify a single number
        x = F.max_pool2d(F.relu(self.conv2(x)), 2)
        x = x.view(-1, self.num_flat_features(x))
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

autograd処理の際にプロファイルできるようにコンテキストマネージャーを作成しています。

https://pytorch.org/docs/stable/autograd.html#torch.autograd.profiler.emit_nvtx

Tensorコアが動作しているかどうかも確認したかったのでapexを使用しています。

https://github.com/NVIDIA/apex

with torch.autograd.profiler.emit_nvtx():

    net = LeNet5().cuda()

    input = torch.randn(1, 1, 32, 32).cuda()
    out = net(input)

    target = torch.randn(10)  # a dummy target, for example
    target = target.view(1, -1).cuda()  # make it the same shape as output
    criterion = nn.MSELoss()

    # create your optimizer
    optimizer = optim.SGD(net.parameters(), lr=0.01)
    if args.amp:
        opt_level = 'O1'
        net, optimizer = amp.initialize(net, optimizer, opt_level=opt_level)

    for i in tqdm(range(10)):
        # in your training loop:
        optimizer.zero_grad()  # zero the gradient buffers

        profiler.start()
        output = net(input)
        loss = criterion(output, target)
        if args.amp:
            with amp.scale_loss(loss, optimizer) as scaled_loss:
                scaled_loss.backward()
        else:
            loss.backward()
        optimizer.step()  # Does the update
    profiler.stop()

apexを有効にするオプションの設定からTensorboardの起動までを一貫して動作するスクリプトを作成しました。

#!/usr/bin/env bash
set -eu

progname="dlprof"

# actions.
usage() {
    echo "Usage: DLprof AMP or No AMP [OPTIONS] COMMAND"
    echo
    echo "Options:"
    echo "  -h, --help         show help."
    echo "  -a, --amp set True option works amp or False set doesn't work amp"
    echo
}


# parse arguments and options.
declare -a params=()
for OPT in "$@"
do
    case "$OPT" in
        '-h'|'--help' )
            usage
            exit 0
            ;;
        '-a'|'--amp' )
            if [[ -z "${2:-}" ]] || [[ "${2:-}" =~ ^-+ ]]; then
                echo "$progname: option '$1' requires an argument. True or False" 1>&2
                exit 1
            fi
            amp_option="$2"
            ;;
        -*)
            echo "$progname: illegal option -- '$(echo $1 | sed 's/^-*//')'" 1>&2
            exit 1
            ;;
    esac
done

export TF_FORCE_GPU_ALLOW_GROWTH=true

if [ "$amp_option" = "True" ]; then
    rm -rf dlprof_amp_out
    rm -rf event_files_amp
    echo dlprof --key_node=block1_conv1/Conv2D --output_path=./dlprof_amp_out --force true \
            --out_tb_dir=./event_files_amp python lenet.py --amp
    dlprof --key_node=block1_conv1/Conv2D --output_path=./dlprof_amp_out --force true \
            --tb_dir=./event_files_amp python lenet.py --amp
    tensorboard --port 6008 --logdir ./dlprof_amp_out/event_files_amp/ &
else
    rm -rf dlprof_out
    rm -rf event_files
    echo dlprof --key_node=block1_conv1/Conv2D --output_path=./dlprof_out --force false \
            --out_tb_dir=./event_files python lenet.py
    dlprof --key_node=block1_conv1/Conv2D --output_path=./dlprof_out --force true \
            --tb_dir=./event_files python lenet.py 
    tensorboard --port 6008 --logdir ./dlprof_out/event_files/ &
fi

GPUの動作内容の把握

まずapexをオフにして下記のコマンドで動作確認します

bash dlprof_run_pytorch_lenet.sh --amp False

動作すればブラウザで下記にアクセスします。

http://localhost:6008/

上の4つのチャートですが

  • GPU Idle: GPUの実行とidle時間を把握できます。
  • Op Summary: OperationベースでTensorコアを使用しているかどうかを把握できます。
  • Kernel Summary: KernelベースでTensorコアを使用しているかどうかを把握できます。
  • Tensor Core Kernel Efficiency: Tensor Coreの使用比率を把握できます。

チャート以外の情報ですが下記があります。

  • Performance Summary: トータルの実行時間などが把握できます。
  • Top 10 GPU Ops: Operationごとに時間がかかった順に並んで表示されます。これによってどのオペレーションが最も時間がかかったかを把握できます。
  • System Config: GPU数、GPU名、ドライバのバージョンが把握できます。

下記により詳細な情報があります。

https://docs.nvidia.com/deeplearning/frameworks/tensorboard-plugin-user-guide/index.html#content_pane_views

ではapexを使用してTensor coreを使用していることを把握できるかどうか見てみます。

Tensorboardの動作を止めます。

pkill tensorboard

次にコードを動作します。

bash dlprof_run_pytorch_lenet.sh --amp True

Op Summaryを確認すると緑の部分が出ており、Tensor Coreを使用していることが分かります。

Tensor Core Kernel EfficiencyにもTensor Core使用率が上がっていることが分かります。

Top 10 GPU Opsにも”/LeNet5::forward/Conv2d::forward/Conv2d::_conv_forward/wrapper/conv2d”で”TC Eligible“と”Using TC“が変更されていることが分かります。

Tensor Coreを使用しているかどうか把握できるようになっている
さらにどのオペレーション時間が長いか把握できるようになっているのでボトルネックを見つけやすくなっているぞ

Close Bitnami banner
Bitnami