データ構造

gpu::DevMem2D_

Comments from the Wiki

gpu::DevMem2D_

これは,GPU 上の(アラインメントが調整された)pitched memory をカプセル化した,シンプルな軽量クラスです.これは,nvcc でコンパイルされたコード,つまり,CUDA カーネルに渡すことを意図したものです.したがって,これは,OpenCV 内部やユーザが書いたデバイスコードで利用されます.そのメンバは,ホスト側とデバイス側の両方のコードから呼び出すことができます.

template <typename T> 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 <typename U>
    explicit DevMem2D_(const DevMem2D_<U>& 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;
};

gpu::PtrStep_

Comments from the Wiki

gpu::PtrStep_

これは DevMem2D _ と似た構造体ですが,内部にはポインタと行ステップ値のみが含まれています.パフォーマンス上の理由で,幅と高さのフィールドは除外されています.この構造体は,内部的利用や,デバイスコードを書くユーザのためのものです.

template<typename T> struct PtrStep_
{
        T* data;
        size_t step;

        PtrStep_();
        PtrStep_(const DevMem2D_<T>& 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;
};

gpu::PtrElemStrp_

Comments from the Wiki

gpu::PtrElemStrp_

これは DevMem2D _ と似た構造体ですが,内部にはポインタと要素毎の行ステップ値のみが含まれています.パフォーマンス上の理由で,幅と高さのフィールドは除外されています.この構造体は, sizeof(T) が 256 の倍数である場合のみ,作成することができます.この構造体は,内部的利用や,デバイスコードを書くユーザのためのものです.

template<typename T> struct PtrElemStep_ : public PtrStep_<T>
{
        PtrElemStep_(const DevMem2D_<T>& mem);
        __CV_GPU_HOST_DEVICE__ T* ptr(int y = 0);
        __CV_GPU_HOST_DEVICE__ const T* ptr(int y = 0) const;
};

gpu::GpuMat

Comments from the Wiki

gpu::GpuMat

参照カウンタを持つ,GPU メモリ用の基底ストレージクラス.このインタフェースは, Mat() インタフェースにいくつかの制限を加えたものとほぼ同様なので,使い方が問題になることはないでしょう.この制限とは,任意の次元がサポートされない(2次元のみ),データの参照を返す関数がない(GPU 上の参照は,CPUにとっては意味がないので),式テンプレートテクニックがサポートされない,という事です.最後の制限事項があるので,メモリの割り当てを引き起こす,行列の演算子オーバーロードには注意してください.GpuMat クラスは, cv::gpu::DevMem2D_ および cv::gpu::PtrStep_ に変換可能なので,カーネルに直接渡すことができます.

注意事項: Mat() とは対照的に,多くの場合 GpuMat::isContinuous() == false ,つまり,ハードウェア依存のサイズに行アラインメントが調整されます.また,1行の GpuMat は常に連続した行列になります.

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 <class T> operator DevMem2D_<T>() const;
        template <class T> operator PtrStep_<T>() 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 メモリ解放関数がエラーを返すからです.

参考: Mat()

gpu::CudaMem

Comments from the Wiki

gpu::CudaMem

参照カウントを持つ,CUDAの特殊な種類のメモリ割り当て関数をラップしたクラス.このインタフェースも, 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” を参照してください.

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;
};

cv::gpu::CudaMem::createMatHeader

Comments from the Wiki

Mat()

Mat CudaMem::createMatHeader() const
CudaMem::operator Mat() const

CudaMem データ への参照カウンタを持たない ヘッダを作成します.

cv::gpu::CudaMem::createGpuMatHeader

Comments from the Wiki

gpu::GpuMat() _

GpuMat CudaMem::createGpuMatHeader() const
CudaMem::operator GpuMat() const

CPU メモリを GPU アドレス空間にマップし,参照カウンタを持たない ヘッダを作成します.これは, ALLOCZEROCOPYフラグを指定してメモリを割り当てが行われ,かつハードウェアがサポートしている場合のみ,実行できます(ノートPCでは,ビデオメモリとCPUメモリを共有する場合が多いので,アドレス空間のマップが可能で,余計なコピーが行われなくなります).

cv::gpu::CudaMem::canMapHostMemory

Comments from the Wiki

_

static bool CudaMem::canMapHostMemory()

現在のハードウェアが,アドレス空間マッピング,および ALLOCZEROCOPYメモリ割り当てをサポートする場合に true を返します.

gpu::Stream

Comments from the Wiki

gpu::Stream

このクラスは,非同期呼び出しのキューがカプセル化されたクラスです.いくつかの関数は,オーバーロードで gpu::Stream() パラメータが追加されています.このオーバーロードは,初期化処理(出力バッファの割り当て,データのアップロード,など)を行い,GPUカーネルを開始し,結果が用意されるよりも前に retrun します.すべての処理が完了したかどうかのチェックは, gpu::Stream::queryIfComplete() でできます.非同期アップロード/ダウンロードは,ページロックバッファとの間で行われなければいけません.つまり, gpu::CudaMem() ,または gpu::CudaMem() 領域を指す Mat() ヘッダを利用する必要があります.

注意する制限事項: 現在のところ,1つの処理が異なるデータを伴って2度キューに入った場合,すべての処理が適切に動作する保障はありません.関数によっては,固定の GPU メモリを利用し,以前の処理が終わる前に,次の呼び出しでメモリ内容を更新してしまう可能性があるものが存在します.しかし,異なる処理はそれぞれの固有バッファを持つので,異なる処理の非同期呼び出しは安全です.また,ユーザが保持するバッファへの,メモリのコピー/アップロード/ダウンロード/セット処理も安全です.

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);
};

cv::gpu::Stream::queryIfComplete

Comments from the Wiki

bool Stream::queryIfComplete()

現在のストリームキューが完了した場合に true を返し,それ以外は false を返します.

cv::gpu::Stream::waitForCompletion

Comments from the Wiki

void Stream::waitForCompletion()

ストリーム内のすべての処理が完了するまでブロックします.

gpu::StreamAccessor

Comments from the Wiki

gpu::StreamAccessor

このクラスは, gpu::Stream() から cudaStream_t を取得する手段を提供します. stream_accessor.hpp は,Cuda ランタイム API に依存する唯一の public なヘッダなので,このクラスはそこで宣言されています.これをインクルードすることで,ユーザのコードに依存関係が発生します.

struct StreamAccessor
{
        CV_EXPORTS static cudaStream_t getStream(const Stream& stream);
};

cv::gpu::createContinuous

Comments from the Wiki

void createContinuous(int rows, int cols, int type, GpuMat& m)

GPUメモリ上に(データが連続した)行列を作成します.

パラメタ:
  • rows – 行数.
  • cols – 列数.
  • type – 行列の型.
  • m – 出力行列.適切な型と範囲( rows \times cols )であれば,変形されるだけです.

以下のラッパーも利用できます:

GpuMat createContinuous(int rows, int cols, int type)
void createContinuous(Size size, int type, GpuMat& m)
GpuMat createContinuous(Size size, int type)

要素が途切れることなく格納されている行列,つまり,行間にギャップが存在しない行列を,連続している行列,と呼びます.

cv::gpu::ensureSizeIsEnough

Comments from the Wiki

void ensureSizeIsEnough(int rows, int cols, int type, GpuMat& m)

行列のサイズが十分に大きく,適切な型であることを保証します.この関数は,行列が既に適切な性質のものであれば,メモリの再割り当てを行いません

パラメタ:
  • rows – 必要な最小の行数.
  • cols – 必要な最小の列数.
  • type – 必要な行列の型.
  • m – 出力行列.

以下のラッパーも利用できます:

void ensureSizeIsEnough(Size size, int type, GpuMat& m)