LoginSignup
8
11

More than 1 year has passed since last update.

Jetson用のCUDAを有効にしたOpenCLおよびOpenCVをビルドする方法

Last updated at Posted at 2021-12-20

##はじめに

これはどちらかというと、かなりチラシの裏的な備忘録です。
題名の通り、Jetso AGX XavierやNXなどでCUDAを有効にしたOpenCLやOpenCVをビルドすることが非常に大変だったので、覚書です。

##そもそも

JetsonシリーズはOpenCLに公式には対応していません。そこでpoCLという互換?のものを使用します。
また、OpenCVに関しては、標準でJetPackに含まれているものはOpenCLはおろかCUDAにすら対応したものではないので、自前で用意する必要があります。

この記事は基本的に以下の記事をXavierなどに対応させたものになります。

##準備
OpenGL絡みでパッチを当てておく必要があるのと、必要なqt4-defaultを入れておきます。

sudo apt-get install qt4-default
wget https://gist.githubusercontent.com/Muhammad-Yunus/2981f35eda97228525203b5d1be2570f/raw/064cdae27b3faf4a221315f1a876a43d7faff4ed/OpenGLHeader.patch
sudo patch -N /usr/local/cuda-10.2/targets/aarch64-linux/include/cuda_gl_interop.h OpenGLHeader.patch

また以下のファイルを編集して、コメントアウトをすることで、JetPack内に含まれているOpenCVが入らないようにします。

vi /etc/apt/sources.list.d/nvidia-l4t-apt-source.list

そのあと、

sudo apt update
sudo apt purge libopencv* opencv*

でOpenCVを消しておきます。

念の為CMakeも最新にしておきます。

wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null
echo "deb https://apt.kitware.com/ubuntu/ bionic main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
sudo apt-get install kitware-archive-keyring
sudo rm /etc/apt/trusted.gpg.d/kitware.gpg
sudo apt install cmake

##poCLのXavier/NX向けのビルド

poCLはClang/LLVMを使用してコンパイルを行います。コンパイルを行う際にCPUを指定する必要がありますが、上記のサイトのJetso Nanoのやり方では、CPUが異なるため、よろしくありません。(Jetson Nanoはcortex-a57でXavier/NXはcarmel)

そこで、Xavier/NXのCarmelに対応したClamg/LLVMの12を使用した方法でビルドする必要があります。

wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
echo "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main" | sudo tee -a /etc/apt/sources.list
sudo apt-get update
LLVM_VERSION=12
sudo apt install -y build-essential ocl-icd-libopencl1 cmake git pkg-config libclang-${LLVM_VERSION}-dev clang-${LLVM_VERSION} llvm-${LLVM_VERSION} make ninja-build ocl-icd-libopencl1 ocl-icd-dev ocl-icd-opencl-dev libhwloc-dev zlib1g zlib1g-dev clinfo dialog apt-utils libxml2-dev libclang-cpp${LLVM_VERSION}-dev libclang-cpp${LLVM_VERSION} llvm-${LLVM_VERSION}-dev libncurses5

Clang/LLVMを12が使われるように指定します。以下のスクリプトを取ってきて使うと楽なので、それを使います。

wget https://gist.githubusercontent.com/junkdog/70231d6953592cd6f27def59fe19e50d/raw/92f0e73d2558402b7316021c1ab408b30e534de6/update-alternatives-clang.sh
chmod +x update-alternatives-clang.sh
sudo ./update-alternatives-clang.sh 12 50

以下のコマンドで12が選択されているか確認できます。

update-alternatives --config clang
update-alternatives --config llvm-config

続いてpoCLをCloneしてきてビルドをしてきます。(ここでは1.7を使っています。)

cd ~
git clone --single-branch --branch release_1_7 https://github.com/pocl/pocl.git
cd pocl
mkdir build
cd build

そしてビルドしてきます。

Jetson Nanoの場合

cmake -DCMAKE_INSTALL_PREFIX=/usr/local/pocl/ -DENABLE_CUDA=ON  -DCMAKE_BUILD_TYPE=Release -DLLC_HOST_CPU=cortex-a57  ..
make 
sudo make install

Jetson AGX Xavier/NXの場合

cmake -DCMAKE_INSTALL_PREFIX=/usr/local/pocl/ -DENABLE_CUDA=ON  -DCMAKE_BUILD_TYPE=Release -DLLC_HOST_CPU=carmel  ..
make 
sudo make install

終わったら以下のファイルを作成し編集します。

mkdir -p /etc/OpenCL/vendors/
cd /etc/OpenCL/vendors/
sudo vi pocl.icd

以下の一行のみ記述

/usr/local/pocl/lib/libpocl.so

きちんとpoCLがインストールできると以下のコマンドでOpenCLが使えるかどうかがわかります。

clinfo

##OpenCVのCUDA有効にしたビルド

これは色々と手順が複雑であることもあるので、以下のスクリプトを作成して実行します。ここではJetPackに標準で入っている4.1.1をCUDA/CUDNN/OpenCLを有効にしてビルドします。
またsfmでエラーが出るときは以下を追加します。(エラーが出ないときは消せばOK)
-D BUILD_opencv_sfm=OFF"

#!/usr/bin/env bash
# 2019 Michael de Gans

set -e

# change default constants here:
readonly PREFIX=/usr/local  # install prefix, (can be ~/.local for a user install)
readonly DEFAULT_VERSION=4.1.1  # controls the default version (gets reset by the first argument)
readonly CPUS=$(nproc)  # controls the number of jobs

# better board detection. if it has 6 or more cpus, it probably has a ton of ram too
if [[ $CPUS -gt 5 ]]; then
    # something with a ton of ram
    JOBS=$CPUS
else
    JOBS=1  # you can set this to 4 if you have a swap file
    # otherwise a Nano will choke towards the end of the build
fi

cleanup () {
# https://stackoverflow.com/questions/226703/how-do-i-prompt-for-yes-no-cancel-input-in-a-linux-shell
-script
    while true ; do
        echo "Do you wish to remove temporary build files in /tmp/build_opencv ? "
        if ! [[ "$1" -eq "--test-warning" ]] ; then
            echo "(Doing so may make running tests on the build later impossible)"
        fi
        read -p "Y/N " yn
        case ${yn} in
            [Yy]* ) rm -rf /tmp/build_opencv ; break;;
            [Nn]* ) exit ;;
            * ) echo "Please answer yes or no." ;;
        esac
    done
}

setup () {
    #if [[ -d "build_opencv" ]] ; then
    #    echo "It appears an existing build exists in /tmp/build_opencv"
        #cleanup
    #fi
    mkdir build_opencv
    cd build_opencv
}

git_source () {
    echo "Getting version '$1' of OpenCV"
    git clone --depth 1 --branch "$1" https://github.com/opencv/opencv.git
    git clone --depth 1 --branch "$1" https://github.com/opencv/opencv_contrib.git
}

install_dependencies () {
    # open-cv has a lot of dependencies, but most can be found in the default
    # package repository or should already be installed (eg. CUDA).
    echo "Installing build dependencies."
    sudo apt-get update
    sudo apt-get dist-upgrade -y --autoremove
    sudo apt-get install -y \
        build-essential \
        cmake \
        git \
        gfortran \
        libatlas-base-dev \
        libavcodec-dev \
        libavformat-dev \
        libavresample-dev \
        libcanberra-gtk3-module \
        libdc1394-22-dev \
        libeigen3-dev \
        libglew-dev \
        libgstreamer-plugins-base1.0-dev \
        libgstreamer-plugins-good1.0-dev \
        libgstreamer1.0-dev \
        libgtk-3-dev \
        libjpeg-dev \
        libjpeg8-dev \
        libjpeg-turbo8-dev \
        liblapack-dev \
        liblapacke-dev \
        libopenblas-dev \
        libpng-dev \
        libpostproc-dev \
        libswscale-dev \
        libtbb-dev \
        libtbb2 \
        libtesseract-dev \
        libtiff-dev \
        libv4l-dev \
        libxine2-dev \
        libxvidcore-dev \
        libx264-dev \
        pkg-config \
        python-dev \
        python-numpy \
        python3-dev \
        python3-numpy \
        python3-matplotlib \
        qv4l2 \
        v4l-utils \
        v4l2ucp \
        qt4-default \
        libgtk2.0-dev \
        pkg-config \
        zlib1g-dev
}


configure () {
    local CMAKEFLAGS="
        -D BUILD_EXAMPLES=OFF
        -D BUILD_opencv_python2=ON
        -D BUILD_opencv_python3=ON
        -D CMAKE_BUILD_TYPE=RELEASE
        -D CMAKE_INSTALL_PREFIX=${PREFIX}
        -D BUILD_opencv_world=OFF
        -D CUDA_ARCH_BIN=5.3,6.2,7.2
        -D CUDA_ARCH_PTX=
        -D CUDA_FAST_MATH=ON
        -D CUDNN_VERSION='8.0'
        -D OPENCV_DNN_CUDA=ON
        -D WITH_CUBLAS=ON
        -D WITH_CUDA=ON
        -D WITH_CUDNN=ON
        -D OPENCV_EXTRA_MODULES_PATH=~/build_opencv/opencv_contrib/modules
        -D EIGEN_INCLUDE_PATH=/usr/include/eigen3 
        -D ENABLE_NEON=ON
        -D WITH_OPENCL=ON
        -D WITH_OPENMP=OFF
        -D WITH_TBB=ON
        -D WITH_1394=OFF
        -D OPENCV_ENABLE_NONFREE=ON
        -D OPENCV_GENERATE_PKGCONFIG=ON
        -D WITH_GSTREAMER=ON
        -D WITH_LIBV4L=ON
        -D WITH_OPENGL=ON
        -D WITH_GTK=ON
        -D WITH_QT=4
        -D BUILD_opencv_sfm=OFF"

    if [[ "$1" != "test" ]] ; then
        CMAKEFLAGS="
        ${CMAKEFLAGS}
        -D BUILD_PERF_TESTS=OFF
        -D BUILD_TESTS=OFF"
    fi

    echo "cmake flags: ${CMAKEFLAGS}"

    cd opencv
    mkdir build
    cd build
    cmake ${CMAKEFLAGS} .. 2>&1 | tee -a configure.log
}
main () {

    local VER=${DEFAULT_VERSION}

    # parse arguments
    if [[ "$#" -gt 0 ]] ; then
        VER="$1"  # override the version
    fi

    if [[ "$#" -gt 1 ]] && [[ "$2" == "test" ]] ; then
        DO_TEST=1
    fi

    # prepare for the build:
    setup
    install_dependencies
    git_source ${VER}

    if [[ ${DO_TEST} ]] ; then
        configure test
    else
        configure
    fi

    # start the build
    make -j${JOBS} 2>&1 | tee -a build.log

    if [[ ${DO_TEST} ]] ; then
        make test 2>&1 | tee -a test.log
    fi

    # avoid a sudo make install (and root owned files in ~) if $PREFIX is writable
    if [[ -w ${PREFIX} ]] ; then
        make install 2>&1 | tee -a install.log
    else
        sudo make install 2>&1 | tee -a install.log
    fi

    #cleanup --test-warning

}

main "$@"

まとめ

ROSを使いたいときは、cv_bridgeなどがOpenCVの3を前提にしているので、自前でビルドする必要があります。
Jetsonはいろいろめんどくさいですが、これで一通りCUDAなどを活用した画像処理ができると思っていますが、本当にちゃんと動くかはよくわからないのでご注意くだされ。

8
11
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
8
11