LoginSignup
4
7

More than 5 years have passed since last update.

Docker コンテナで NVIDIA GPU によるハードウェアエンコードを動かす

Posted at

目的

NVIDIA GPU による高速なハードウェアエンコードを Docker コンテナで動かしたい。

前提条件

  • Docker コンテナで NVIDIA GPU を使用するには、ホストマシンに NVIDIA GPU が搭載されている必要がある。
  • 今回はホストマシンとして NVIDIA Tesla M60 を搭載した Amazon EC2 G3 インスタンス を使用した。
  • ホスト OS は Amazon Linux 2 を選択、NVIDIA GPU のドライバは執筆当時の最新版を使用した。

ホストマシンの準備

まずは Docker コンテナを動作させるホストマシンとなる Amazon EC2 インスタンスを用意する。

  1. Amazon EC2 G3 インスタンスを起動
    • AMI (Amazon Machine Image) は Amazon Linux 2 AMI ami-0a2de1c3b415889d2 を選択
    • インスタンスタイプは G3 インスタンスの中では比較的安価な g3.4xlargeg3s.xlarge を推奨
    • EBS ルートボリュームは 8 GB だと空き容量が不足する可能性があるため注意
  2. 起動した EC2 インスタンスに SSH 接続
  3. 最初にタイムゾーンを設定

    sudo timedatectl set-timezone Asia/Tokyo
    
  4. Docker のインストール
    Amazon Linux 2 では Extras Library を使用することで Docker を簡単にインストールすることができる。

    sudo amazon-linux-extras install docker
    
  5. NVIDIA Graphics Driver のインストール
    最新のドライバは https://www.nvidia.com/Download/index.aspx で Tesla M60 を検索することで取得可能。
    なお、NVIDIA Graphics Driver の使用には NVIDIA Software License Agreement への同意が必要である。

    sudo yum install gcc kernel-devel-$(uname -r)
    wget http://us.download.nvidia.com/tesla/410.72/NVIDIA-Linux-x86_64-410.72.run
    sudo bash NVIDIA-Linux-x86_64-410.72.run --ui=none --no-questions --accept-license
    
  6. nvidia-docker2 のインストール
    nvidia-docker2 は Docker コンテナで NVIDIA GPU を使用するために必要なランタイムである。

    distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
    curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | sudo tee /etc/yum.repos.d/nvidia-docker.repo
    sudo yum install nvidia-docker2
    
  7. Docker コンテナの起動確認
    先にインストールしたランタイムを指定して nvidia/cuda コンテナを起動する。
    コンテナ内部で実行する nvidia-smi は NVIDIA GPU の情報を取得するためのコマンドである。

    sudo systemctl start docker
    sudo docker run --runtime=nvidia nvidia/cuda nvidia-smi
    

    以下のように NVIDIA GPU の情報が表示されれば成功。

    +-----------------------------------------------------------------------------+
    | NVIDIA-SMI 410.72       Driver Version: 410.72       CUDA Version: 10.0     |
    |-------------------------------+----------------------+----------------------+
    | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
    | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
    |===============================+======================+======================|
    |   0  Tesla M60           Off  | 00000000:00:1E.0 Off |                  N/A |
    | N/A   29C    P0    40W / 150W |      0MiB /  7618MiB |     97%      Default |
    +-------------------------------+----------------------+----------------------+
    
    +-----------------------------------------------------------------------------+
    | Processes:                                                       GPU Memory |
    |  GPU       PID   Type   Process name                             Usage      |
    |=============================================================================|
    |  No running processes found                                                 |
    +-----------------------------------------------------------------------------+
    

FFmpeg のビルド

次に Docker コンテナで動かす FFmpeg のビルドを行う。ビルドも Docker コンテナ内部で行う。

  1. 作業用コンテナの起動
    nvidia/cuda:10.0-devel-centos7 コンテナを起動しシェルに接続する。

    sudo docker run --runtime=nvidia -it nvidia/cuda:10.0-devel-centos7 /bin/bash
    
  2. 必要なパッケージのインストール

    yum install autoconf bzip2 git make
    
  3. nasm のインストール

    curl -fsSLO https://www.nasm.us/pub/nasm/releasebuilds/2.14/nasm-2.14.tar.bz2
    tar xjvf nasm-2.14.tar.bz2
    cd nasm-2.14
    ./autogen.sh
    ./configure
    make -j$(nproc)
    make install
    
  4. ffnvcodec のインストール
    FFmpeg 4.0 以降 NVIDIA Video Codec SDK のヘッダファイルが FFmpeg 本体に付属されなくなった。

    git clone https://git.videolan.org/git/ffmpeg/nv-codec-headers
    cd nv-codec-headers
    make install
    
  5. FFmpeg 本体のビルド

    export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
    curl -fsSLO https://ffmpeg.org/releases/ffmpeg-4.1.tar.bz2
    tar xjvf ffmpeg-4.1.tar.bz2
    cd ffmpeg-4.1
    ./configure --enable-nvenc
    make -j$(nproc)
    make install
    

ハードウェアエンコードの実行

ビルドした FFmpeg を使ってハードウェアエンコードを行う。エンコードはより軽量な新しいコンテナで行う。

  1. エンコード実行用コンテナの起動
    環境変数 NVIDIA_DRIVER_CAPABILITIES=video を設定することで、ホストマシンにインストールされた NVIDIA GPU ドライバを構成するライブラリのうち NVENC に関連するものをコンテナ内部から使用できるようになる。
    nvidia/cuda:10.0-runtime イメージは nvidia/cuda:10.0-devel に比べて含まれるライブラリの種類が少ない代わりにイメージサイズが小さい。ビルド済みの CUDA アプリケーションを実行する場合はこちらを使用する。

    sudo docker run --runtime=nvidia -it -e 'NVIDIA_DRIVER_CAPABILITIES=video' nvidia/cuda:10.0-runtime-centos7 /bin/bash
    
  2. 前節でビルドした FFmpeg 本体 /usr/local/bin/ffmpeg を新しいコンテナにもコピーする。
    いったんコンテナから exit してから docker cp コマンドによりコンテナ内部のファイルを操作できる。

    sudo docker cp <source-container-id>:/usr/local/bin/ffmpeg <target-container-id>:/usr/local/bin/ffmpeg
    
  3. FFmpeg コマンドの実行
    再び新しいコンテナに docker attach してから、適当な動画ファイル input.mp4 を用意する。
    これに対し NVENC によるハードウェアエンコードを行うには、以下の ffmpeg コマンドを実行する。

    /usr/local/bin/ffmpeg -i input.mp4 -vcodec h264_nvenc -acodec aac output.mp4
    

Docker コンテナイメージの作成

NVENC に対応した FFmpeg が最初から使用可能な新しい Docker コンテナイメージ example/nvenc を作成する。完成したコンテナイメージを Docker Hub に公開すれば、誰でも docker pull できるようになる。

  1. Dockerfile の作成
    Dockerfile はコンテナイメージのレシピを記述したものである。
    以下の内容を Dockerfile という名前で作成する。Dockerfile の記法についてはここでは割愛する。

    FROM nvidia/cuda:10.0-devel-centos7 as builder
    
    ENV NASM_VERSION 2.14
    ENV NVCODEC_VERSION 8.2.15.6
    ENV FFMPEG_VERSION 4.1
    
    RUN yum install -y autoconf bzip2 git make
    
    RUN curl -fsSLO https://www.nasm.us/pub/nasm/releasebuilds/$NASM_VERSION/nasm-$NASM_VERSION.tar.bz2 \
      && tar -xjf nasm-$NASM_VERSION.tar.bz2 \
      && cd nasm-$NASM_VERSION \
      && ./autogen.sh \
      && ./configure \
      && make -j$(nproc) \
      && make install
    
    RUN git clone -b n$NVCODEC_VERSION --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers \
      && cd nv-codec-headers \
      && make install
    
    ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig
    RUN curl -fsSLO https://ffmpeg.org/releases/ffmpeg-$FFMPEG_VERSION.tar.bz2 \
      && tar -xjf ffmpeg-$FFMPEG_VERSION.tar.bz2 \
      && cd ffmpeg-$FFMPEG_VERSION \
      && ./configure --enable-nvenc \
      && make -j$(nproc) \
      && make install
    
    FROM nvidia/cuda:10.0-runtime-centos7
    
    ENV NVIDIA_VISIBLE_DEVICES all
    ENV NVIDIA_DRIVER_CAPABILITIES compute,video,utility
    
    COPY --from=builder /usr/local/bin/ffmpeg /usr/local/bin/ffmpeg
    COPY --from=builder /usr/local/bin/ffprobe /usr/local/bin/ffprobe
    
  2. Docker コンテナイメージのビルド
    Dockerfile と同じディレクトリで以下のコマンドを実行するとコンテナイメージのビルドが開始される。

    sudo docker build -t example/nvenc .
    
  3. Docker コンテナの起動確認
    作成した example/nvenc コンテナを起動し、ffmpeg コマンドが使用可能であることを確認する。

    sudo docker run --runtime=nvidia -it example/nvenc /bin/bash
    /usr/local/bin/ffmpeg
    
  4. コンテナイメージを Docker Hub に公開
    あらかじめ Docker Hub のアカウントを作成し Create Repository からリポジトリを作成しておく必要がある。

    sudo docker login
    sudo docker push example/nvenc
    

なお、今回作成した Docker コンテナイメージは https://hub.docker.com/r/clerk67/nvenc/ にて公開している。

4
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
7