14
9

More than 5 years have passed since last update.

Jetson XavierでOpenCV 4.0 + CUDAをビルドすると、Xavierで実行できないプログラムが出来上がる

Last updated at Posted at 2018-12-13

はじめに

  • エヌビディアの手島です
  • 私が所属を明示して記事を書くのは、所属を明示せずに「Tegra最高!一番好きなGPUです」などと書くとステマ以外の何物でもなくなってしまうからであって、内容自体は会社としての見解ではなく個人的なものです。(cf.)
  • 本記事はOpenCV Advent Calendar 201813日目の記事です
  • 他の記事は目次にまとめられています

TL;DR

  • このOpenCVをリリースしたのは誰じゃぁ!
  • Xavier の CC は7.2です。
  • 迂回策は-DCUDA_ARCH_BIN=7.2をつけること
  • (2018-12-25追記)OpenCV 4.0.1 が2018-12-22(日本時間)にリリースされましたので、そちらでは本件fixされております

OpenCV をCUDA付きでビルドすると

  • CMakeが終わった時点でビルドするCCが表示されます。(GPU archの行。以降Compute Capabilityの略でCCで表記)
  NVIDIA CUDA
    Use CUFFT:                   YES
    Use CUBLAS:                  NO
    USE NVCUVID:                 NO
    NVIDIA GPU arch:             30 35 37 50 52 60 61 70 75
    NVIDIA PTX archs:            30
    Use fast math:               NO
  • このCCの値は、OpenCVでは、可能な限り何でもビルドしようとします。
cmake/OpenCVDetectCUDA.cmake
      if(CUDA_VERSION VERSION_LESS "9.0")
        set(__cuda_arch_bin "2.0 3.0 3.5 3.7 5.0 5.2 6.0 6.1")
      elseif(CUDA_VERSION VERSION_LESS "10.0")
        set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0")
      else()
        set(__cuda_arch_bin "3.0 3.5 3.7 5.0 5.2 6.0 6.1 7.0 7.5")
      endif()

OpenCV をJetson上でCUDA付きでビルドすると

  • Jetsonの場合は少し事情が違います
  • JetsonはSoCでGPU付きで出てくるため、そもそも使えるGPUの組み合わせが決まっています。
  • 具体的には以下の組み合わせしかありません
プラットフォーム SoCの名前 CC
Arm (32bit) Tegra K1 3.2
Arm (64bit) Tegra X1 5.3
Arm (64bit) Parker 6.2
Arm (64bit) Xavier 7.2
  • Arm 32bitのプラットフォームでのビルドはJetson TK1しかありえないので、CCは3.2で決め打ちです。
  • 実際にOpenCVのソースコードにも決め打ちです
cmake/OpenCVDetectCUDA.cmake
  if(NOT DEFINED __cuda_arch_bin)
    if(ARM)
      set(__cuda_arch_bin "3.2")
      set(__cuda_arch_ptx "")
    elseif(AARCH64)
  • 問題は64bitの場合です
  • 64bitのプラットフォームの場合は5.3、6.3、7.2のいずれにも当てはまるので、OpenCV では全部ビルドします。
cmake/OpenCVDetectCUDA.cmake
        message(STATUS "Automatic detection of CUDA generation failed. Going to build for all known architectures.")
        set(__cuda_arch_bin "5.3 6.2 7.0 7.5") #  <--- んんんんん???????????
  • で、なんとこのままOpenCV 4.0がリリースされているので、4.0 でビルドすると、Xavierでは動かないコードが吐き出されます。
error: (-217:Gpu API call) no kernel image is available for execution on the device in function 'xxxxxxx'
  • Jetson Xavier は2018年9月から販売されていたので、2018年11月のOpenCV 4.0のリリースにはぜひとも修正してもらいたかったな、と思います。
  • そもそも、ここはフェイルセーフのバックアッププランでして、本来なら、コメント文にある通り、CCの自動検出コードが走ってCCの値を一意に決めてくれます。やったねCMake!

自動検出させてみる

  • 自動検出コードは、cmake/checks/OpenCVDetectCudaArch.cuをビルドし、CMakeが裏で実行してくれるので本当に自動で検出されます。
  • さてCMakeのログを見てみましょう
$ cmake -DWITH_CUDA=ON -DOPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules/  ..
<中略>
-- CUDA detected: 10.0
-- Automatic detection of CUDA generation failed. Going to build for all known architectures.  
↑↑↑↑↑ んんんんん???????????
-- CUDA NVCC target flags: -gencode;arch=compute_53,code=sm_53;-gencode;arch=compute_62,code=sm_62;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-D_FORCE_INLINES
  • ん!?!?!?!?自動検出に失敗してる!?!?
  • そうなんです。今日気づいたのですが、自動検出のソースコードcmake/checks/OpenCVDetectCudaArch.cuには、単純なシンタックスエラー1があり、自動検出する前に自動検出のコードのビルドに失敗するのです
    • 自動検出のソースコードのビルドにこける
    • 全部乗せでビルドするも、そもそも誤ったCCが指定されている
    • Xavierで実行できないコードが生成される←イマココ

解決策

cmake -DWITH_CUDA=ON -DCUDA_ARCH_BIN=7.2 -DOPENCV_EXTRA_MODULES_PATH=~/opencv_contrib/modules ..
  • ってな具合に、-DCUDA_ARCH_BIN=7.2と指定することでこの問題を迂回できます。

終わりに

  • Jetson のセットアップ時にOpenCVも一緒にセットアップされるので、そちらは問題無いのですが、ソースコードからビルドするとどうしても本記事のような条件にぶちあたります。
  • 3.4系列では自動検出の問題バグが混入されてないので、問題なくビルドできます
  • また本件は「OpenCV 4.0.0」を「Xavier上」で、「OpenCVをソースから」かつ「CUDA付きでビルドした場合」の限定状況下でのバグです。
  • 同じ状況に陥った人は是非参考にして下さい

  1. CUDAのコードなのにコメント文の開始が"#"になっている 

14
9
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
14
9