OpenCV 4.13.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 4.13.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
CUDAモジュール入門

概要

OpenCV CUDA モジュールは、CUDA の計算能力を活用するためのクラスと関数の集合である。NVIDIA* CUDA* Runtime API を用いて実装されており、NVIDIA GPU のみをサポートする。OpenCV CUDA モジュールには、ユーティリティ関数、低レベルのビジョンプリミティブ、および高レベルのアルゴリズムが含まれる。ユーティリティ関数と低レベルプリミティブは、CUDA を活用した高速なビジョンアルゴリズムを開発するための強力な基盤を提供し、一方で高レベルの機能には、アプリケーション開発者がすぐに使用できる最先端のアルゴリズム(ステレオ対応、顔・人物検出器など)が含まれる。

CUDAモジュールはホストレベルのAPIとして設計されている。つまり、事前にコンパイルされたOpenCV CUDAバイナリがあれば、CUDAを利用するためにCUDA Toolkitをインストールしたり追加のコードを書いたりする必要はない。

OpenCV CUDAモジュールは使いやすさを重視して設計されており、CUDAの知識を一切必要としない。ただし、自明でないケースに対処したり最高の性能を引き出したりする上では、そうした知識は確かに役立つ。各種演算のコスト、GPUが何を行うか、好ましいデータ形式は何か、といったことを理解しておくと有益である。CUDAモジュールはCUDAで高速化したコンピュータビジョンアルゴリズムを手早く実装するための効果的な手段である。ただし、アルゴリズムが多数の単純な演算を含む場合は、中間結果に対する余分な書き込みと読み込みを避けるために、最高の性能を得るには独自のカーネルを書く必要が依然としてあるかもしれない。

CUDAサポートを有効にするには、CMakeでOpenCVを WITH_CUDA=ON として構成する。このフラグが設定され、かつCUDAがインストールされている場合、フル機能のOpenCV CUDAモジュールがビルドされる。そうでない場合もモジュールはビルドされるが、cuda::getCudaEnabledDeviceCount() を除き、実行時にモジュール内のすべての関数が CV_GpuNotSupported エラーコードで Exception をスローする。この場合、後者の関数はGPU数として0を返す。CUDAサポートなしでOpenCVをビルドするとデバイスコードのコンパイルは行われないため、CUDA Toolkitのインストールは不要である。したがって、cuda::getCudaEnabledDeviceCount() 関数を使えば、実行時にGPUの有無を検出し、それに応じて適切な実装(CPUまたはGPU)を選択する高レベルなアルゴリズムを実装できる。

異なるNVIDIA*プラットフォーム向けのコンパイル

NVIDIA*コンパイラはバイナリコード(cubinおよびfatbin)と中間コード(PTX)の生成を可能にする。バイナリコードはしばしば特定のGPUアーキテクチャと世代を前提とするため、他のGPUとの互換性は保証されない。PTXは、能力や機能の集合によって完全に定義される仮想プラットフォームを対象とする。選択した仮想プラットフォームによっては、実際のハードウェアがすべての機能をサポートしていても、一部の命令がエミュレートされたり無効化されたりする。

最初の呼び出し時に、PTXコードはJITコンパイラによって特定のGPU向けのバイナリコードへコンパイルされる。対象GPUのコンピュート能力(CC)がPTXコードより低い場合、JITは失敗する。デフォルトでは、OpenCV CUDAモジュールには以下が含まれる:

  • コンピュート能力1.3および2.0向けのバイナリ(CMakeの CUDA_ARCH_BIN で制御)
  • コンピュート能力1.1および1.3向けのPTXコード(CMakeの CUDA_ARCH_PTX で制御)

これは、CC 1.3および2.0のデバイスではバイナリイメージがそのまま実行可能であることを意味する。それより新しいすべてのプラットフォームでは、1.3向けPTXコードがJITによってバイナリイメージへ変換される。CC 1.1および1.2のデバイスでは、1.1向けPTXがJITされる。CC 1.0のデバイスでは利用可能なコードがなく、関数は Exception をスローする。JITコンパイルが最初に行われるプラットフォームでは、実行が遅くなる。

CC 1.0のGPUでも、CUDAモジュールをコンパイルでき、ほとんどの関数は問題なく動作する。これを実現するには、バイナリのリストに "1.0" を追加する。例えば CUDA_ARCH_BIN="1.0 1.3 2.0" のようにする。CC 1.0のGPUで実行できない関数は例外をスローする。

OpenCVのGPUビルドバイナリ(またはPTXコード)が自分のGPUと互換性があるかどうかは、実行時に常に判定できる。cuda::DeviceInfo::isCompatible 関数は互換性の状態(true/false)を返す。

複数GPUの活用

現バージョンでは、OpenCV CUDAアルゴリズムのそれぞれは単一のGPUしか使用できない。したがって、複数GPUを活用するには、GPU間で処理を手動で分配する必要がある。アクティブなデバイスの切り替えは cuda::setDevice() 関数で行える。詳細はCuda C Programming Guideを参照のこと。

複数GPU向けにアルゴリズムを開発する際は、データ受け渡しのオーバーヘッドに注意すること。プリミティブな関数や小さな画像では、それが大きくなり、複数GPUを持つ利点をすべて打ち消してしまうことがある。しかし高レベルなアルゴリズムでは、マルチGPUによる高速化を検討するとよい。例えば、Stereo Block Matchingアルゴリズムは次のアルゴリズムを用いて並列化に成功している:

  1. ステレオペアの各画像を、水平方向に重なり合う2つのストライプに分割する。
  2. 各ストライプのペア(左画像と右画像から)を別々のFermi*GPU上で処理する。
  3. 結果を単一の視差マップにマージする。

このアルゴリズムにより、デュアルGPUは単一のFermi GPUと比べて180%の性能向上をもたらした。ソースコードの例については、https://github.com/opencv/opencv/tree/4.x/samples/gpu/ を参照のこと。