我现在开始使用CUDA并且不得不承认我对C API有点失望。我理解选择C的原因但是语言基于C ++而不是,有几个方面会更简单,例如:设备内存分配(via cudaMalloc)。

我的计划是自己这样做,使用重载的operator new with placement new和RAII(两个替代方案)。我想知道到目前为止我是否有任何警告。代码似乎可以工作,但我仍然想知道潜在的内存泄漏。

RAII 代码的用法如下:

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

在这种情况下,也许一个类是矫枉过正的(特别是因为你仍然必须使用cudaMemcpy,这个类只封装了RAII)所以另一种方法是 placement cudaDevice

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

此处,<=>仅用作触发重载的标记。但是,由于在正常位置<=>这将指示放置,我发现语法奇怪地一致,甚至可能更适合使用类。

我很欣赏各种批评。是否有人知道是否计划在下一版本的CUDA中使用这个方向(正如我所听到的那样,它将改进其C ++支持,无论它们是什么意思)。

所以,我的问题实际上有三个:

  1. 我的展示位置<=>超载在语义上是否正确?它会泄漏内存吗?
  2. 是否有人了解有关未来CUDA发展的信息(请参阅C ++ s * ck中的C接口)?
  3. 如何以一致的方式进一步采取这种方式(还有其他需要考虑的API,例如,不仅有设备内存,还有常量内存和纹理内存)?

  4. // 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&);
    };
    

    关于这里使用的单身人士:是的,我知道它的缺点。但是,这些与此无关。我在这里需要的只是一个不可复制的小型标签。其他所有内容(即多线程注意事项,初始化时间)都不适用。

有帮助吗?

解决方案

我会选择新的方法。然后我将定义一个符合std :: allocator <!> lt; <!> gt;的类;接口。理论上,您可以将此类作为模板参数传递给std :: vector <!> lt; <!> gt;和std :: map <!> lt; <!> gt;等等。

要注意,我听说做这些事情充满了困难,但至少你会以这种方式学习更多关于STL的知识。而且您不需要重新发明容器和算法。

其他提示

与此同时,还有一些进一步的发展(在CUDA API方面并没有那么多,但至少在尝试类似STL的CUDA数据管理方法的项目方面)。

最值得一提的是NVIDIA研究项目:推力

有几个项目尝试类似的东西,例如 CUDPP

然而,与此同时,我已经实现了我自己的分配器,它运行良好且很简单(<!> gt; 95%样板代码)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top