データ構造 =============== .. highlight:: cpp .. index:: gpu::DevMem2D_ .. _gpu::DevMem2D_: gpu::DevMem2D_ -------------- `id=0.401198002553 Comments from the Wiki `__ .. ctype:: gpu::DevMem2D_ これは,GPU 上の(アラインメントが調整された)pitched memory をカプセル化した,シンプルな軽量クラスです.これは,nvcc でコンパイルされたコード,つまり,CUDA カーネルに渡すことを意図したものです.したがって,これは,OpenCV 内部やユーザが書いたデバイスコードで利用されます.そのメンバは,ホスト側とデバイス側の両方のコードから呼び出すことができます. .. code-block:: c template struct DevMem2D_ { int cols; int rows; T* data; size_t step; DevMem2D_() : cols(0), rows(0), data(0), step(0){}; DevMem2D_(int rows_, int cols_, T *data_, size_t step_); template explicit DevMem2D_(const DevMem2D_& d); typedef T elem_type; enum { elem_size = sizeof(elem_type) }; __CV_GPU_HOST_DEVICE__ size_t elemSize() const; /* 画像の指定行の先頭を指すポインタを返します. */ __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0); __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const; }; .. .. index:: gpu::PtrStep_ .. _gpu::PtrStep_: gpu::PtrStep_ ------------- `id=0.854491610172 Comments from the Wiki `__ .. ctype:: gpu::PtrStep_ これは DevMem2D _ と似た構造体ですが,内部にはポインタと行ステップ値のみが含まれています.パフォーマンス上の理由で,幅と高さのフィールドは除外されています.この構造体は,内部的利用や,デバイスコードを書くユーザのためのものです. .. code-block:: c template struct PtrStep_ { T* data; size_t step; PtrStep_(); PtrStep_(const DevMem2D_& mem); typedef T elem_type; enum { elem_size = sizeof(elem_type) }; __CV_GPU_HOST_DEVICE__ size_t elemSize() const; __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0); __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const; }; .. .. index:: gpu::PtrElemStrp_ .. _gpu::PtrElemStrp_: gpu::PtrElemStrp_ ----------------- `id=0.576560931994 Comments from the Wiki `__ .. ctype:: gpu::PtrElemStrp_ これは DevMem2D _ と似た構造体ですが,内部にはポインタと要素毎の行ステップ値のみが含まれています.パフォーマンス上の理由で,幅と高さのフィールドは除外されています.この構造体は, sizeof(T) が 256 の倍数である場合のみ,作成することができます.この構造体は,内部的利用や,デバイスコードを書くユーザのためのものです. .. code-block:: c template struct PtrElemStep_ : public PtrStep_ { PtrElemStep_(const DevMem2D_& mem); __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0); __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const; }; .. .. index:: gpu::GpuMat .. _gpu::GpuMat: gpu::GpuMat ----------- `id=0.296260742285 Comments from the Wiki `__ .. ctype:: gpu::GpuMat 参照カウンタを持つ,GPU メモリ用の基底ストレージクラス.このインタフェースは, :func:`Mat` インタフェースにいくつかの制限を加えたものとほぼ同様なので,使い方が問題になることはないでしょう.この制限とは,任意の次元がサポートされない(2次元のみ),データの参照を返す関数がない(GPU 上の参照は,CPUにとっては意味がないので),式テンプレートテクニックがサポートされない,という事です.最後の制限事項があるので,メモリの割り当てを引き起こす,行列の演算子オーバーロードには注意してください.GpuMat クラスは, cv::gpu::DevMem2D\_ および cv::gpu::PtrStep\_ に変換可能なので,カーネルに直接渡すことができます. **注意事項:** :func:`Mat` とは対照的に,多くの場合 ``GpuMat::isContinuous() == false`` ,つまり,ハードウェア依存のサイズに行アラインメントが調整されます.また,1行の GpuMat は常に連続した行列になります. .. code-block:: c class CV_EXPORTS GpuMat { public: //! デフォルトコンストラクタ GpuMat(); GpuMat(int rows, int cols, int type); GpuMat(Size size, int type); ..... //! Mat から GpuMat を作成.デバイスへのブロッキングアップロードを行います. explicit GpuMat (const Mat& m); //! nvcc でコンパイルされたコードに渡すための軽量な DevMem2D_ 構造体 // を返します.ここには,サイズ,データポインタ,ステップが含まれます. template operator DevMem2D_() const; template operator PtrStep_() const; //! GpuMat へ,データをブロッキングアップロードします. void upload(const cv::Mat& m); void upload(const CudaMem& m, Stream& stream); //! デバイスからホストメモリへデータをダウンロードします.ブロッキング呼び出しでs. operator Mat() const; void download(cv::Mat& m) const; //! 非同期ダウンロードを行います. void download(CudaMem& m, Stream& stream) const; }; .. **注意事項:** static または global に割り当てられた GpuMat 変数をそのままに,つまりデストラクタ任せにするのは悪習です.何故なら,このような変数や CUDA コンテキストのデストラクトの順序は未定義であり,CUDAコンテキストが既に破壊されていた場合には,GPU メモリ解放関数がエラーを返すからです. 参考: :func:`Mat` .. index:: gpu::CudaMem .. _gpu::CudaMem: gpu::CudaMem ------------ `id=0.854979855022 Comments from the Wiki `__ .. ctype:: gpu::CudaMem 参照カウントを持つ,CUDAの特殊な種類のメモリ割り当て関数をラップしたクラス.このインタフェースも, :func:`Mat` と似ていますが,メモリ割り当ての種類を指定するパラメータが追加されています. * ``ALLOC_PAGE_LOCKED`` ページロックされたメモリを設定します.通常,GPUとの間で高速で非同期なデータのアップロード/ダウンロードを行う場合に利用されます. * ``ALLOC_ZEROCOPY`` ゼロコピーメモリ割り当てを指定します.つまり,もしサポートされていて可能であれば,ホストメモリとGPUアドレス空間とのマッピングを行います. * ``ALLOC_WRITE_COMBINED`` CPU にキャッシュされない,書き込み結合バッファを設定します.このようなバッファは,GPUが読み込みのみ行う場合に,GPU にデータを提供するために利用されます.CPUのキャッシュ管理が良くなるという利点があります. 通常,この様な種類のメモリ割り当ては,サイズが制限される事に注意してください.詳細は, "CUDA 2.2 Pinned Memory APIs" ドキュメント,および "CUDA _ C Programming Guide" を参照してください. .. code-block:: c class CV_EXPORTS CudaMem { public: enum { ALLOC_PAGE_LOCKED = 1, ALLOC_ZEROCOPY = 2, ALLOC_WRITE_COMBINED = 4 }; CudaMem(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); //! cv::Mat からデータをコピーして作成します. explicit CudaMem(const Mat& m, int alloc_type = ALLOC_PAGE_LOCKED); ...... void create(Size size, int type, int alloc_type = ALLOC_PAGE_LOCKED); //! CudaMem データへの参照カウンタを持たない行列ヘッダを返します. Mat createMatHeader() const; operator Mat() const; //! ホストメモリをデバイスアドレス空間にマップします. GpuMat createGpuMatHeader() const; operator GpuMat() const; // ホストメモリを GPU アドレス空間にマップできる否か. static bool canMapHostMemory(); int alloc_type; }; .. .. index:: gpu::CudaMem::createMatHeader cv::gpu::CudaMem::createMatHeader --------------------------------- `id=0.654063049533 Comments from the Wiki `__ :func:`Mat` .. cfunction:: Mat CudaMem::createMatHeader() const .. cfunction:: CudaMem::operator Mat() const CudaMem データ への参照カウンタを持たない ヘッダを作成します. .. index:: gpu::CudaMem::createGpuMatHeader cv::gpu::CudaMem::createGpuMatHeader ------------------------------------ `id=0.788025138825 Comments from the Wiki `__ :func:`gpu::GpuMat` ``_`` .. cfunction:: GpuMat CudaMem::createGpuMatHeader() const .. cfunction:: CudaMem::operator GpuMat() const CPU メモリを GPU アドレス空間にマップし,参照カウンタを持たない ヘッダを作成します.これは, ALLOCZEROCOPYフラグを指定してメモリを割り当てが行われ,かつハードウェアがサポートしている場合のみ,実行できます(ノートPCでは,ビデオメモリとCPUメモリを共有する場合が多いので,アドレス空間のマップが可能で,余計なコピーが行われなくなります). .. index:: gpu::CudaMem::canMapHostMemory cv::gpu::CudaMem::canMapHostMemory ---------------------------------- `id=0.0871387994344 Comments from the Wiki `__ ``_`` .. cfunction:: static bool CudaMem::canMapHostMemory() 現在のハードウェアが,アドレス空間マッピング,および ALLOCZEROCOPYメモリ割り当てをサポートする場合に true を返します. .. index:: gpu::Stream .. _gpu::Stream: gpu::Stream ----------- `id=0.62396850942 Comments from the Wiki `__ .. ctype:: gpu::Stream このクラスは,非同期呼び出しのキューがカプセル化されたクラスです.いくつかの関数は,オーバーロードで :func:`gpu::Stream` パラメータが追加されています.このオーバーロードは,初期化処理(出力バッファの割り当て,データのアップロード,など)を行い,GPUカーネルを開始し,結果が用意されるよりも前に retrun します.すべての処理が完了したかどうかのチェックは, :func:`gpu::Stream::queryIfComplete()` でできます.非同期アップロード/ダウンロードは,ページロックバッファとの間で行われなければいけません.つまり, :func:`gpu::CudaMem` ,または :func:`gpu::CudaMem` 領域を指す :func:`Mat` ヘッダを利用する必要があります. **注意する制限事項:** 現在のところ,1つの処理が異なるデータを伴って2度キューに入った場合,すべての処理が適切に動作する保障はありません.関数によっては,固定の GPU メモリを利用し,以前の処理が終わる前に,次の呼び出しでメモリ内容を更新してしまう可能性があるものが存在します.しかし,異なる処理はそれぞれの固有バッファを持つので,異なる処理の非同期呼び出しは安全です.また,ユーザが保持するバッファへの,メモリのコピー/アップロード/ダウンロード/セット処理も安全です. .. code-block:: c class CV_EXPORTS Stream { public: Stream(); ~Stream(); Stream(const Stream&); Stream& operator=(const Stream&); bool queryIfComplete(); void waitForCompletion(); //! 非同期ダウンロード. // 注意! cv::Mat は,必ずページロックメモリ // (つまり,CudaMem データやその ROI )を指します. void enqueueDownload(const GpuMat& src, CudaMem& dst); void enqueueDownload(const GpuMat& src, Mat& dst); //! 非同期アップロード. // 注意! cv::Mat は,必ずページロックメモリ // (つまり,CudaMem データやその ROI )を指します. void enqueueUpload(const CudaMem& src, GpuMat& dst); void enqueueUpload(const Mat& src, GpuMat& dst); void enqueueCopy(const GpuMat& src, GpuMat& dst); void enqueueMemSet(const GpuMat& src, Scalar val); void enqueueMemSet(const GpuMat& src, Scalar val, const GpuMat& mask); // 例えば, float から uchar のように,行列の型を type で指定されたものに変換します. void enqueueConvert(const GpuMat& src, GpuMat& dst, int type, double a = 1, double b = 0); }; .. .. index:: gpu::Stream::queryIfComplete cv::gpu::Stream::queryIfComplete -------------------------------- `id=0.174132648228 Comments from the Wiki `__ .. cfunction:: bool Stream::queryIfComplete() 現在のストリームキューが完了した場合に true を返し,それ以外は false を返します. .. index:: gpu::Stream::waitForCompletion cv::gpu::Stream::waitForCompletion ---------------------------------- `id=0.97846334946 Comments from the Wiki `__ .. cfunction:: void Stream::waitForCompletion() ストリーム内のすべての処理が完了するまでブロックします. .. index:: gpu::StreamAccessor .. _gpu::StreamAccessor: gpu::StreamAccessor ------------------- `id=0.462479792507 Comments from the Wiki `__ .. ctype:: gpu::StreamAccessor このクラスは, :func:`gpu::Stream` から ``cudaStream_t`` を取得する手段を提供します. ``stream_accessor.hpp`` は,Cuda ランタイム API に依存する唯一の public なヘッダなので,このクラスはそこで宣言されています.これをインクルードすることで,ユーザのコードに依存関係が発生します. .. code-block:: c struct StreamAccessor { CV_EXPORTS static cudaStream_t getStream(const Stream& stream); }; .. .. index:: gpu::createContinuous cv::gpu::createContinuous ------------------------- `id=0.792588687849 Comments from the Wiki `__ .. cfunction:: void createContinuous(int rows, int cols, int type, GpuMat\& m) GPUメモリ上に(データが連続した)行列を作成します. :param rows: 行数. :param cols: 列数. :param type: 行列の型. :param m: 出力行列.適切な型と範囲( ``rows`` :math:`\times` ``cols`` )であれば,変形されるだけです. 以下のラッパーも利用できます: .. cfunction:: GpuMat createContinuous(int rows, int cols, int type) .. cfunction:: void createContinuous(Size size, int type, GpuMat\& m) .. cfunction:: GpuMat createContinuous(Size size, int type) 要素が途切れることなく格納されている行列,つまり,行間にギャップが存在しない行列を,連続している行列,と呼びます. .. index:: gpu::ensureSizeIsEnough cv::gpu::ensureSizeIsEnough --------------------------- `id=0.799199434776 Comments from the Wiki `__ .. cfunction:: void ensureSizeIsEnough(int rows, int cols, int type, GpuMat\& m) 行列のサイズが十分に大きく,適切な型であることを保証します.この関数は,行列が既に適切な性質のものであれば,メモリの再割り当てを行いません :param rows: 必要な最小の行数. :param cols: 必要な最小の列数. :param type: 必要な行列の型. :param m: 出力行列. 以下のラッパーも利用できます: .. cfunction:: void ensureSizeIsEnough(Size size, int type, GpuMat\& m)