17

私は現在 CUDA を使い始めており、C API に少しがっかりしていることを認めなければなりません。C を選択した理由は理解できますが、代わりに言語が C++ に基づいていた場合、デバイス メモリの割り当て (経由cudaMalloc) など、いくつかの側面がより単純になったはずです。

operator new私の計画は、オーバーロードされた配置newと RAII (2 つの選択肢)を使用して、これを自分で行うことでした。今まで気付かなかった注意点があるのではないかと思っています。コードは機能しているように見えますが、メモリ リークの可能性についてまだ疑問に思っています。

RAIIコードの使用法は次のようになります。

CudaArray<float> device_data(SIZE);
// Use `device_data` as if it were a raw pointer.

おそらく、このコンテキストではクラスがやり過ぎなので(特に、cudaMemcpyRAIIをカプセル化するだけのクラスを使用する必要があるため)、他のアプローチは配置newになります:

float* device_data = new (cudaDevice) float[SIZE];
// Use `device_data` …
operator delete [](device_data, cudaDevice);

ここでは、cudaDevice単にオーバーロードをトリガーするタグとして機能します。ただし、通常の配置でnewはこれは配置を示しているため、構文が奇妙に一貫しており、おそらくクラスを使用するよりも好ましいとさえ思います。

あらゆる種類の批判をいただければ幸いです。この方向の何かがCUDAの次のバージョンで計画されているかどうか誰かがおそらく知っていますか(私が聞いたように、それが意味するものは何でも、C++サポートが改善されます)。

したがって、私の質問は実際には 3 つあります。

  1. プレースメントのnewオーバーロードは意味的に正しいですか? それはメモリをリークしますか?
  2. この一般的な方向に進む将来の CUDA 開発に関する情報を誰かが持っていますか (それに直面しましょう: C++ s*ck の C インターフェイス)?
  3. これを一貫した方法でさらに進めるにはどうすればよいですか (他にも考慮すべき API があります。たとえば、デバイス メモリだけでなく、定数メモリ ストアとテクスチャ メモリもあります)。

// Singleton tag for CUDA device memory placement.
struct CudaDevice {
    static CudaDevice const& get() { return instance; }
private:
    static CudaDevice const instance;
    CudaDevice() { }
    CudaDevice(CudaDevice const&);
    CudaDevice& operator =(CudaDevice const&);
} const& cudaDevice = CudaDevice::get();

CudaDevice const CudaDevice::instance;

inline void* operator new [](std::size_t nbytes, CudaDevice const&) {
    void* ret;
    cudaMalloc(&ret, nbytes);
    return ret;
}

inline void operator delete [](void* p, CudaDevice const&) throw() {
    cudaFree(p);
}

template <typename T>
class CudaArray {
public:
    explicit
    CudaArray(std::size_t size) : size(size), data(new (cudaDevice) T[size]) { }

    operator T* () { return data; }

    ~CudaArray() {
        operator delete [](data, cudaDevice);
    }

private:
    std::size_t const size;
    T* const data;

    CudaArray(CudaArray const&);
    CudaArray& operator =(CudaArray const&);
};

ここで採用されているシングルトンについて: はい、その欠点は認識しています。ただし、これらはこのコンテキストには関係ありません。ここで必要だったのは、コピーできない小さなタイプのタグだけでした。他のすべて (つまり、マルチスレッドの考慮事項、初期化の時間) は適用されません。

4

4 に答える 4

7

その間に、いくつかのさらなる開発がありました(CUDA APIに関してはそれほど多くはありませんが、少なくともCUDAデータ管理へのSTLのようなアプローチを試みるプロジェクトに関しては)。

最も注目すべきは、NVIDIAの研究からのプロジェクトがあります:推力

于 2010-07-22T06:51:47.827 に答える
5

私は配置の新しいアプローチを採用します。次に、std ::allocator<>インターフェイスに準拠するクラスを定義します。理論的には、このクラスをテンプレートパラメータとしてstd ::vector<>やstd::map<>などに渡すことができます。

注意してください、私はそのようなことをするのは難しいと聞いていますが、少なくともあなたはこの方法でSTLについてもっと多くを学ぶでしょう。また、コンテナやアルゴリズムを再発明する必要はありません。

于 2008-11-19T01:26:17.353 に答える
2

CUDPPなど、同様のことを試みるプロジェクトがいくつかあります。

しかし、それまでの間、独自のアロケータを実装しましたが、うまく機能し、簡単でした (> 95% ボイラープレート コード)。

于 2008-11-19T17:55:56.933 に答える