自動化されたPytorchアームは、NVIDIA Cudaとパイソン> 3.6のためにDocker BuildDXとともに構築します



マイワークフロー
ユースケースのために、NVIDIA Jetsonをエッジ推論のために利用したかったです.ここでのボトルネックの一つは、3.6より大きいPythonバージョンが必要だということでした.見るとNvidia Jetson packages for PyTorch これはバージョン3.6でのみ作成されたことがわかりました.
検索すると、私は非常に多くの人々は、私はNVIDIAデバイス(例えばNVIDIA Jetsonナノ)上で実行することができますこのようにcudaをサポートすることができますピーチのアームホイールの建物を自動化するのに役立つ解決策を調べることになったこの(私は証明)に苦しんで見つけることができます.
上記の全体のプロセスは、私はdockfileを構築し、最終的にCIのプロセスを自動化する方法を考え出すことから始めて、私は完全に11日間を取った.

Note: I also decided to utilize this article as an entry for a running Hackathon by


なぜ我々は自動化したいのだろうか?よく、最初に私のNVIDIA Jetson Nanoの上でこれをコンパイルするとき、私はそれを16 GBのスワップスペース(デバイスが2 GBを持っている)を使っているとき、80 ~ %をコンパイルすることができませんでした.私の個人的なPCの上にそれを構築した後に、これは完全にコンパイルすることを得るために~ 6 hをとりました.それを自動化するのに十分大きくて長くすること.

The final source code can be found on GitHub



提出カテゴリ
のDIYの展開

貢献
このサイズのどんな種類のプロジェクトでも、作られた特定の貢献があります.私のプロジェクトでは、次のようにしています.
  • 非GPUデバイスにCudaをインストールします
  • GPUを非GPUデバイスで有効にする
  • PythonのためのPytorchをコンパイルする> 3.6
  • ビルドの腕でのビルドを介して

  • 事業概要
    ベストプラクティスとして、私は常に上記の課題に取り組んだプロジェクトの概要を紹介したいと思います.
  • ホイールをビルドする
  • どのように、私はCudaのために造られますか?(最も難しい部分)
  • どうやって作るの?
  • クリエイトアクション
  • どうやって作るの?私は特に腕のために走ることができますか?

  • Dockerfileの作成-アームとPythonのPytorchを構築する> 3.6
    これまでのところ最も難しいのは、アームとPythonのためのPyTorchをコンパイルする方法です.私たちは、非GPUデバイス上で実行するため、cudaが利用できないので.dockerfileを並列に実行できる3つの特定のセクションに分割しました.
  • Cudaを設定する
  • PyTorchをセットアップする
  • Python 3.9の設定
  • コンパイルする
  • 私はここにNVIDIAのJetsonの最適化が含まれているQEngineering !
  • Dockfile結果
  • 以下の各ステップの説明を見つけることができます.最終回はDockerfile Docker層のサイズを小さくするための最適化( 1コマンドでのグループ化により)

    Cudaの設定
    Cudaのために、我々はCUDAライブラリを持っていません、また、我々は彼らにアクセスすることができません!しかし、我々はcudaをロードすることができますトリックがあります.NVIDIA Jetsonの公開鍵をコピーし、リポジトリに権限を与えます.それから、パッケージマネージャを使ってインストールします.
    V_CUDA_DASH=10-2
    
    # Add the public key
    echo "[Builder] Adding the Jetson Public Key"
    curl https://repo.download.nvidia.com/jetson/jetson-ota-public.asc > /etc/apt/trusted.gpg.d/jetson-ota-public.asc
    echo "deb https://repo.download.nvidia.com/jetson/common ${L4T} main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list
    echo "deb https://repo.download.nvidia.com/jetson/t186 ${L4T} main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list
    
    # Install the CUDA Libraries
    echo "[Builder] Installing CUDA System"
    apt-get update
    apt-get install -y --no-install-recommends \
        cuda-libraries-$V_CUDA_DASH \
        cuda-libraries-dev-$V_CUDA_DASH \
        cuda-nvtx-$V_CUDA_DASH \
        cuda-minimal-build-$V_CUDA_DASH \
        cuda-license-$V_CUDA_DASH \
        cuda-command-line-tools-$V_CUDA_DASH \
        libnvvpi1 vpi1-dev
    
    # Link CUDA to /usr/local/cuda
    ln -s /usr/local/cuda-$CUDA /usr/local/cuda
    
    我々が最終的にコンパイルを始めるとき、我々はCMDA出力🥳
    #   USE_CUDA              : ON
    #     Split CUDA          : OFF
    #     CUDA static link    : OFF
    #     USE_CUDNN           : OFF
    #     USE_EXPERIMENTAL_CUDNN_V8_API: OFF
    #     CUDA version        : 10.2
    #     CUDA root directory : /usr/local/cuda
    #     CUDA library        : /usr/local/cuda/lib64/stubs/libcuda.so
    #     cudart library      : /usr/local/cuda/lib64/libcudart.so
    #     cublas library      : /usr/local/cuda/lib64/libcublas.so
    #     cufft library       : /usr/local/cuda/lib64/libcufft.so
    #     curand library      : /usr/local/cuda/lib64/libcurand.so
    #     nvrtc               : /usr/local/cuda/lib64/libnvrtc.so
    #     CUDA include path   : /usr/local/cuda/include
    #     NVCC executable     : /usr/local/cuda/bin/nvcc
    #     NVCC flags          : <CUT>
    #     CUDA host compiler  : /usr/bin/clang
    #     NVCC --device-c     : OFF
    #     USE_TENSORRT        : OFF
    

    ピーチを設定する
    別のDockerステップでは、我々はPortRchを設定し、それをワーキングリポジトリにクローンします/build/pytorch )
    V_PYTORCH=v1.10.0
    
    # Downloads PyTorch to /build/pytorch
    git clone --recursive --branch ${V_PYTORCH} http://github.com/pytorch/pytorch /build/pytorch
    

    Python 3.9の設定
    私たちはPythonのバージョンをdeadsnakes ppaとデフォルトのリンクとしてリンクします.

    Best practice we should have a venv but since I am running it in a Docker container this should suffice.


    # Setting up Python 3.9
    RUN add-apt-repository ppa:deadsnakes/ppa \
        && apt-get update \
        && apt-get install -y python${V_PYTHON} python${V_PYTHON}-dev python${V_PYTHON}-venv python${V_PYTHON_MAJOR}-tk \
        && rm /usr/bin/python \
        && rm /usr/bin/python3 \
        && ln -s $(which python${V_PYTHON}) /usr/bin/python \
        && ln -s $(which python${V_PYTHON}) /usr/bin/python${V_PYTHON_MAJOR} \
        && curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | python
    

    ピクトレットのコンパイル
    dockerfileの最後のステップはPytorchをコンパイルすることです.このために、curdaを有効にし、他の部分(例えばmkldnn、nnpack、xnnpack、…をオフにする)を無効にすることで、ビルドプロセスを最適化するために、正しい環境変数を設定します.
    また、それを使用するように設定しますclang NVIDIA JetsonとしてNEON registers とclangはそれらをサポートします( gccはそうしません).
    我々のソースのために、我々は我々がつくった他の層を利用して、ちょうどそこからそれをコピーします.
    COPY --from=downloader-pytorch /build/pytorch /build/pytorch
    WORKDIR /build/pytorch
    
    # PyTorch - Build - Prerequisites
    # Set clang as compiler
    # clang supports the ARM NEON registers
    # GNU GCC will give "no expression error"
    ARG CC=clang
    ARG CXX=clang++
    
    # Build
    rm build/CMakeCache.txt || : \
    sed -i -e "/^if(DEFINED GLIBCXX_USE_CXX11_ABI)/i set(GLIBCXX_USE_CXX11_ABI 1)" CMakeLists.txt \
    pip install -r requirements.txt
    python setup.py bdist_wheel
    

    結果をアーティファクトとしてコピーする
    我々が利用できる感覚で、Docker BuildXは驚くべきです--output type-local,dest=. ローカルファイルシステムにファイルを出力し、Dockerがビルドされ、ビルド結果をアーティファクトとしてエクスポートできるようにします.
    これを達成するために、我々はscratch 画像と他のDocker層からの結果にコピーします.我々/ pathはPyTorchのビルドホイールをすべて含む.torch-1.10.0a0+git36449ea-cp39-cp39-linux_aarch64.whl )
    FROM scratch as artifact
    COPY --from=builder /pytorch/dist/* /
    

    Dockfile結果
    最後に、dockfileは以下のようになります.
    # ##################################################################################
    # Setup Nvidia CUDA for Jetson
    # ##################################################################################
    FROM ubuntu:18.04 as cuda-devel
    
    # Configuration Arguments
    ARG V_CUDA_MAJOR=10
    ARG V_CUDA_MINOR=2
    ARG V_L4T_MAJOR=32
    ARG V_L4T_MINOR=6
    
    ENV V_CUDA=${V_CUDA_MAJOR}.${V_CUDA_MINOR}
    ENV V_CUDA_DASH=${V_CUDA_MAJOR}-${V_CUDA_MINOR}
    ENV V_L4T=r${V_L4T_MAJOR}.${V_L4T_MINOR}
    
    # Expose environment variables everywhere
    ENV CUDA=${V_CUDA_MAJOR}.${V_CUDA_MINOR}
    
    # Accept default answers for everything
    ENV DEBIAN_FRONTEND=noninteractive
    
    # Fix CUDA info
    ARG DPKG_STATUS
    
    # Add NVIDIA repo/public key and install VPI libraries
    RUN echo "$DPKG_STATUS" >> /var/lib/dpkg/status \
        && echo "[Builder] Installing Prerequisites" \
        && apt-get update \
        && apt-get install -y --no-install-recommends ca-certificates software-properties-common curl gnupg2 apt-utils \
        && echo "[Builder] Installing CUDA Repository" \
        && curl https://repo.download.nvidia.com/jetson/jetson-ota-public.asc > /etc/apt/trusted.gpg.d/jetson-ota-public.asc \
        && echo "deb https://repo.download.nvidia.com/jetson/common ${V_L4T} main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list \
        && echo "deb https://repo.download.nvidia.com/jetson/t186 ${V_L4T} main" >> /etc/apt/sources.list.d/nvidia-l4t-apt-source.list \
        && echo "[Builder] Installing CUDA System" \
        && apt-get update \
        && apt-get install -y --no-install-recommends \
        cuda-libraries-${V_CUDA_DASH} \
        cuda-libraries-dev-${V_CUDA_DASH} \
        cuda-nvtx-${V_CUDA_DASH} \
        cuda-minimal-build-${V_CUDA_DASH} \
        cuda-license-${V_CUDA_DASH} \
        cuda-command-line-tools-${V_CUDA_DASH} \
        libnvvpi1 vpi1-dev \
        && ln -s /usr/local/cuda-${V_CUDA} /usr/local/cuda \
        && rm -rf /var/lib/apt/lists/*
    
    # Update environment
    ENV LIBRARY_PATH=/usr/local/cuda/lib64/stubs
    
    RUN ln -fs /usr/share/zoneinfo/Europe/Brussels /etc/localtime
    
    # ##################################################################################
    # Create PyTorch Docker Layer
    # We do this seperately since else we need to keep rebuilding
    # ##################################################################################
    FROM --platform=$BUILDPLATFORM ubuntu:18.04 as downloader-pytorch
    
    # Configuration Arguments
    # https://github.com/pytorch/pytorch
    ARG V_PYTORCH=v1.10.0
    # https://github.com/pytorch/vision
    ARG V_PYTORCHVISION=v0.11.1
    # https://github.com/pytorch/audio
    ARG V_PYTORCHAUDIO=v0.10.0
    
    # Install Git Tools
    RUN apt-get update \
        && apt-get install -y --no-install-recommends software-properties-common apt-utils git \
        && rm -rf /var/lib/apt/lists/* \
        && apt-get clean
    
    # Accept default answers for everything
    ENV DEBIAN_FRONTEND=noninteractive
    
    # Clone Source
    RUN git clone --recursive --branch ${V_PYTORCH} http://github.com/pytorch/pytorch
    
    # ##################################################################################
    # Build PyTorch for Jetson (with CUDA)
    # ##################################################################################
    FROM cuda-devel as builder
    
    # Configuration Arguments
    ARG V_PYTHON_MAJOR=3
    ARG V_PYTHON_MINOR=9
    
    ENV V_PYTHON=${V_PYTHON_MAJOR}.${V_PYTHON_MINOR}
    
    # Accept default answers for everything
    ENV DEBIAN_FRONTEND=noninteractive
    
    # Download Common Software
    RUN apt-get update \
        && apt-get install -y clang build-essential bash ca-certificates git wget cmake curl software-properties-common ffmpeg libsm6 libxext6 libffi-dev libssl-dev xz-utils zlib1g-dev liblzma-dev
    
    # Setting up Python 3.9
    WORKDIR /install
    
    RUN add-apt-repository ppa:deadsnakes/ppa \
        && apt-get update \
        && apt-get install -y python${V_PYTHON} python${V_PYTHON}-dev python${V_PYTHON}-venv python${V_PYTHON_MAJOR}-tk \
        && rm /usr/bin/python \
        && rm /usr/bin/python${V_PYTHON_MAJOR} \
        && ln -s $(which python${V_PYTHON}) /usr/bin/python \
        && ln -s $(which python${V_PYTHON}) /usr/bin/python${V_PYTHON_MAJOR} \
        && curl --silent --show-error https://bootstrap.pypa.io/get-pip.py | python
    
    # PyTorch - Build - Source Code Setup 
    # copy everything from the downloader-pytorch layer /torch to /torch on this one
    COPY --from=downloader-pytorch /pytorch /pytorch
    WORKDIR /pytorch
    
    # PyTorch - Build - Prerequisites
    # Set clang as compiler
    # clang supports the ARM NEON registers
    # GNU GCC will give "no expression error"
    ARG CC=clang
    ARG CXX=clang++
    
    # Set path to ccache
    ARG PATH=/usr/lib/ccache:$PATH
    
    # Other arguments
    ARG USE_CUDA=ON
    ARG USE_CUDNN=ON
    ARG BUILD_CAFFE2_OPS=0
    ARG USE_FBGEMM=0
    ARG USE_FAKELOWP=0
    ARG BUILD_TEST=0
    ARG USE_MKLDNN=0
    ARG USE_NNPACK=0
    ARG USE_XNNPACK=0
    ARG USE_QNNPACK=0
    ARG USE_PYTORCH_QNNPACK=0
    ARG TORCH_CUDA_ARCH_LIST="5.3;6.2;7.2"
    ARG USE_NCCL=0
    ARG USE_SYSTEM_NCCL=0
    ARG USE_OPENCV=0
    ARG USE_DISTRIBUTED=0
    
    # Build
    RUN cd /pytorch \
        && rm build/CMakeCache.txt || : \
        && sed -i -e "/^if(DEFINED GLIBCXX_USE_CXX11_ABI)/i set(GLIBCXX_USE_CXX11_ABI 1)" CMakeLists.txt \
        && pip install -r requirements.txt \
        && python setup.py bdist_wheel \
        && cd ..
    
    # ##################################################################################
    # Prepare Artifact
    # ##################################################################################
    FROM scratch as artifact
    COPY --from=builder /pytorch/dist/* /
    

    アクションクリエーション
    Pytorchは最終的にコンパイルされて以来!これは自動化を開始し、Githubのアーティファクトに公開するときです(この方法で我々は常にそれをトリガし、構築プロセスのキック).私は、リリースが発表されるとすぐに、自動的に建物を始めたいです!我々の行動のために、我々は以下のアウトラインを持っています:

    ワークフロー概要
  • リリースが作成されるとアクションがトリガーされます
  • リポジトリをクローンする
  • buildwithセットアップDocker
  • 実行するコンテナ
  • Githubの上でアーティファクトに作り付けの車輪をコピーしてください

  • 使用行動
    アクションについては、次のアクションを再利用できます.

  • docker/setup-buildx-action
  • 私は、パイプラインでAMD 64マシンでARM用にクロスコンパイルします

  • docker/setup-qemu-action
  • qemuをARM用にコンパイルし、qemuの静的バイナリをインストールすることができます

  • actions/checkout
  • レポをチェックする

  • actions/cache
  • Docker層のキャッシュを許可する

  • actions/upload-artifact
  • ディレクトリの出力をGithubアーティファクトにアップロードする

  • 結果
    最後に、以下のgithubアクションを実行します.
    name: ci
    
    # https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows
    on:
      push:
        branches: [ main ]
      release:
        types: [ created ]
    
    jobs:
      build_wheels:
        runs-on: ubuntu-latest
        steps:
        - name: Checkout Code
          uses: actions/checkout@v2
    
        - name: Set up QEMU
          uses: docker/setup-qemu-action@v1
    
        - name: Set up Docker Buildx
          id: buildx
          uses: docker/setup-buildx-action@v1
    
        - name: Cache Docker layers
          uses: actions/cache@v2
          with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
    
        - name: Build Docker Image
          run: |
          docker buildx build \
              --platform=linux/arm64 \
              --progress=plain \
              --output type=local,dest=./wheels \
              --file Dockerfile.jetson .
    
        - name: Upload Artifacts
          uses: actions/upload-artifact@v2
          with:
          name: wheels
          path: |
            wheels/*.whl
    
        # This ugly bit is necessary if you don't want your cache to grow forever
        # till it hits GitHub's limit of 5GB.
        # Temp fix
        # https://github.com/docker/build-push-action/issues/252
        # https://github.com/moby/buildkit/issues/1896
        - name: Move cache
          run: |
          rm -rf /tmp/.buildx-cache
          mv /tmp/.buildx-cache-new /tmp/.buildx-cache
    

    YAMLファイルまたはコードへのリンク
    ソースコードはGitHub 結果として生じるホイールを含むGitHub Action Workflow .

    将来の仕事

    余分な最適化を行う
    いくつかのサポートはまだソースコードを適応することによってNVIDIA Jetson Nanoのために加えられることができました、しかし、これは現在このプロジェクトの範囲外です.これらの最適化はQEngineering their post

    Githubアクションの改善
    現在、ビルド引数が含まれていますが、まだ使用されません.理論上、以下に加えることができますdocker buildx 他のPythonバージョンのビルドコマンド
    Python 3.8
    docker buildx build \
        --platform=linux/arm64 \
        --progress=plain \
        --build-arg PYTHON_MAJOR=3 \
        --build-arg PYTHON_MINOR=8 \
        --output type=local,dest=./wheels \
        --file Dockerfile.jetson .
    

    結論
    このプロジェクトは確かに簡単ではありませんでした.ビルドの間に長い時間をかけて、どこで構築し、自動化するかを考え出しています.これを共有することによって、私はコミュニティがより簡単に最新版でGPUを利用するのを援助したいです.
    次の記事では、Nvidia Jetson NanoとPython > 3.6でCudaを有効にした実際のAIモデルを実行する方法を紹介します.😉

    参考文献
    これらのすべては、他の貢献によって可能でした:

  • https://github.com/soerensen3/buildx-pytorch-jetson DockerFileコードのいくつかを助けてくれました(しかし、CUDAサポートを持っていませんでした).