OpenCVをCUDA付きでビルドする際にサポートされる範囲



# はじめに
 - NVIDIAの手島です
 - 本日はアドベントカレンダーが空いたので、OpenCVをCUDA付きでビルドする際のバージョンの組み合わせについて紹介します。
 - 本記事は[OpenCV アドベントカレンダー 2020](https://qiita.com/advent-calendar/2020/opencv)、第22日目の記事です。
 - 他の記事は[目次](https://qiita.com/advent-calendar/2020/opencv)を参照して下さい。


# TL;DR

| OpenCV | CUDA | CUDA(Minimum) | CC(x86) | CC(Arm) | リリース日 |
|:-:|:-:|:-:|:-:|:--|:--|
| next (5.0.0相当)| 11.2  | 6.5 | 5.0 - 8.6  | 3.2,5.3,6.2,7.0,7.2 | - |
| 4.5.1  | 11.2  | 6.5 | 5.0 - 8.6  | 3.2,5.3,6.2,7.0,7.2| [2020/Dec/22](https://github.com/opencv/opencv/commit/1363496c1106606684d40447f5d1149b2c66a9f8) |
| 3.4.13 | 11.2  | 6.5 | 5.0 - 8.6  | 3.2,5.3,6.2,7.0,7.2| [2020/Dec/22](https://github.com/opencv/opencv/commit/8869dc776287a1b43b252a91ceb36cc26a56eed4) |
| 4.5.0  | 11.1  | 6.5 | 5.0 - 8.6  | 3.2,5.3,6.2,7.0,7.2 | [2020/Oct/12](https://github.com/opencv/opencv/commit/d5fd2f0155ffad366f9ac912dfd6d189a7a6a98e) |
| 3.4.12 | 11.1  | 6.5 | 5.0 - 8.6  | 3.2,5.3,6.2,7.0,7.2| [2020/Oct/11](https://github.com/opencv/opencv/commit/dc15187f1b6784ef2ece30dae223570811eaddff) |
| 4.4.0  | 11.0  | 6.5 | 2.0 - 8.0  | 3.2,5.3,6.2,7.0,7.2 | [2020/Jul/18](https://github.com/opencv/opencv/commit/c3bb57afeaf030f10939204d48d7c2a3842f4293)  |
| 4.3.0  | 10.2  | 6.5 | 2.0 - 7.5  | 3.2,5.3,6.2,7.2 | [2020/Apr/3](https://github.com/opencv/opencv/commit/01b2c5a77ca6dbef3baef24ebc0a5984579231d9)  |
| 4.2.0  | 10.2  | 6.5 | 2.0 - 7.5  | 3.2,5.3,6.2,7.2 | [2019/Dec/20](https://github.com/opencv/opencv/commit/bda89a6469aa79ecd8713967916bd754bff1d931)  |
| 4.1.0  | 10.1  | 6.5 | 2.0 - 7.5  | 3.2,5.3,6.2,7.2 | [2019/Apr/8](https://github.com/opencv/opencv/commit/371bba8f54560b374fbcd47e7e02f015ac4969ad)  |
| 4.0.0  | 10.0  | 6.5 | 2.0 - 7.5  | 3.2,5.3,6.2,[7.0,7.5](https://qiita.com/tomoaki_teshima/items/4401349431ce266dc319) | [2018/Nov/18](https://github.com/opencv/opencv/commit/75ed282b20770a7a9b490102fd2e0b4fa26223e5)  |
| 3.4.0  | 9.0 | 6.5 |  2.0 - 7.0 | 3.2,5.3,6.2,[7.0 7.5](https://qiita.com/tomoaki_teshima/items/4401349431ce266dc319)  | [2017/Dec/23](https://github.com/opencv/opencv/commit/6d4f66472e14b29b8e1623859cfebfdc67f677c3)  |
| 3.3.0  | 8.0 | 6.5 |  2.0 - 6.1 | 3.2,5.3,6.2  | [2017/Aug/4](https://github.com/opencv/opencv/commit/4af3ca4e4d7be246a49d751a79c6392e848ac2aa)  |
| 3.2.0  | 8.0 | 6.5 |  2.0 - 6.1 | 3.2,5.3  | [2016/Dec/23](https://github.com/opencv/opencv/commit/70bbf17b133496bd7d54d034b0f94bd869e0e810)  |
| 3.1.0  | 7.5 | 4.2 |  1.1 - 3.5 | 3.2,5.3  | [2015/Dec/19](https://github.com/opencv/opencv/commit/92387b1ef8fad15196dd5f7fb4931444a68bc93a) |
| 3.0.0  | 7.0 | 4.2 | 1.1 - 3.5  | 3.2,5.3  | [2015/Jun/4](https://github.com/opencv/opencv/commit/c12243cf4fccf5df7b0270a32883986b373dca7b)|
| 2.4.13.7  | 9.2 | 3.0 | 1.1 - 3.5  | 3.2,5.3  | [2018/Jul/2](https://github.com/opencv/opencv/commit/51cfa519249c89d24035b3f96315ad997deb300f) |

 - 多分に推測を交えて書いているので、この早見表の正確性は保証しない
 - 2.4系列は古いので、最後のリリース以外は割愛
 - 今日、3.4.13と4.5.1がリリースされた

# OpenCVとCUDAを連携してビルドする際の注意点
 - CUDAは後方互換性を破壊したバージョンアップをしばしばする
   - 古くはCUDA graphcutsが除外されたり、NVCUVIDが別パッケージに移動したり、nppiライブラリが細かく分割されたり、nppicomが除外されたりしました。
 - 基本的に後方互換性が維持されなかった場合、OpenCV側でfixが入るのを待つ必要がある
 - なので、新しいCUDAを使いたかったら新しいOpenCVを使う必要がある
 - 古いCUDAと新しいOpenCVの組み合わせは、基本的に動くことが期待される
   - ただし、使う人が少ないと地雷を踏む可能性があるので、特段理由が無い限り、CUDAもOpenCVも新しいものを使うことをお勧めします。
 - また、CUDAのバージョンとは別に、`CC`(Compute Capability)のサポート範囲もある
   - 要は新しいGPUに対応しているかどうか、という点を表す。
   - x86マシンで`CC`を明示的に指定しなかった場合、OpenCVでは基本的に全部乗せのライブラリを生成する。これにより、古いGPUのマシンにライブラリをコピーした際にも動くように、安全に設計されている。
     - 一方で、自分のマシンでビルドして、自分のマシンでだけOpenCVを利用する場合、不要な`CC`分のバイナリは単純にディスクの肥やしになるので、その場合は`-DCUDA_ARCH_BIN`オプションを使って`CC`を決め打ちすることをお勧めする。
     - また、CMake時点で、`CC`単位でなく、世代単位でまとめてビルドする方法もある。こちらは@dandelion1124 [先生のissue提起](https://github.com/opencv/opencv/issues/16649)と[私が投げたPR](https://github.com/opencv/opencv/pull/17478)の結果、3.4.12から範囲が狭まった[^note-deprecated]
   - Arm環境では、使えるGPUが限られているため、自動検出を行い、それでも見つからなかった場合は決め打ちでいくつかの`CC`分のビルドを生成する
 - また、古いCUDAのサポートに関しては、明示的に[`cmake/OpenCVMinDepVersions.cmake` (リンク)](https://github.com/opencv/opencv/blob/d92af2aa85e55e46c11a9c7732efe7177694fa35/cmake/OpenCVMinDepVersions.cmake)に記載されており、現状の3.4系、4系ではCUDA 6.5が古い後方互換性の限度である[^note-not-guaranteed]


[^note-deprecated]: FermiとKepler世代がCMake時点での候補リストに現れなくなった。ただし、全部乗せでは依然ビルド対象となる。あと`CUDA_ENABLE_DEPRECATED_GENERATION`オプションを`ON`にすると候補リストに現れるようになる
[^note-not-guaranteed]: ただし、正しく動くことを筆者が今日確認した訳ではない。あくまで、6.5より古いCUDAを使うと、CMake側でスルーされ、`WITH_CUDA`オプションが`ON`にならない。



# おわりに
 - OpenCVをビルドする際のサポートされているCUDAの範囲をまとめました。
 - 明日は23日目で発起人の@dandelion1124 先生の記事です！