1

使用以下简单的删除器

struct CudaDeleter{ void operator()(void * ptr) { cudaFree( ptr ); } };

在使用 nvcc 编译的代码中使用删除器时出现以下错误。相同的删除器适用于 vs2012 编译器

warning : "std::unique_ptr<_Ty, _Dx>::unique_ptr(
const std::unique_ptr<_Ty, _Dx>::_Myt &)
[with _Ty=const int, _Dx=cuda::CudaDeleter]"

error : function "cuda::CudaDeleter::operator()"
cannot be called with the given argument list

warning : "std::unique_ptr<_Ty, _Dx>::unique_ptr(
const std::unique_ptr<_Ty, _Dx>::_Myt &)
[with _Ty=float, _Dx=cuda::CudaDeleter]"

@talonmies:智能指针仅使用此函数构造

template <typename T>
std::unique_ptr<T, CudaDeleter> make_unique(size_t size)
{
    void * pMemory = nullptr;
    check( cudaMalloc(&pMemory, size) );
    return std::unique_ptr<T, CudaDeleter>( static_cast<T*>(pMemory) );
}
4

2 回答 2

5

以下对我有用。尝试下面的独立代码,如果它有效,那么您需要识别与您的代码的差异,如果不是,那么您的设置会有所不同。

#include <iostream>
#include <memory>

struct CudaDeleter
{
    void operator()(void *p)
    {
        std::cout << "Free..." << std::endl;
        cudaError_t res = cudaFree(p);
        if (res != cudaSuccess)
        {
            std::cout << "Error freeing: " << cudaGetErrorString(res) << std::endl;
        }
    }
};

template <typename T>
std::unique_ptr<T, CudaDeleter> make_unique(size_t size)
{
    void *pMemory = nullptr;
    std::cout << "Allocate..." << std::endl;
    cudaError_t res = cudaMalloc(&pMemory, size);
    if (res != cudaSuccess)
    {
        std::cout << "Error allocating pMemory: " << cudaGetErrorString(res) << std::endl;
        throw;
    }
    return std::unique_ptr<T, CudaDeleter>(static_cast<T*>(pMemory));
}

int main(void)
{
    {
        std::cout << "Create..." << std::endl;
        std::unique_ptr<float, CudaDeleter> x = make_unique<float>(100*sizeof(float));
        std::cout << "Destroy..." << std::endl;
    }
    std::cout << "Done." << std::endl;
}
于 2013-02-19T17:38:11.757 回答
0

我找到了我遇到的问题,最后这是我的错误

并不是说任何 T * 都不能转换为 void *,而是 const T * 不能转换为 void *。

此外,指向 const 的指针不能被 cudaFree 释放,这意味着 Eric 的建议

template<class T> struct CudaDeleter{ void operator()(T* ptr){...}}

不管用。

像这样的东西会起作用

template <typename T>
std::unique_ptr<typename std::remove_const<T>::type, CudaDeleter> make_unique(size_t size)
{
    typename std::remove_const<T>::type * pMemory = nullptr;
    check( cudaMalloc(&pMemory, size) );
    return std::unique_ptr<typename std::remove_const<T>::type, CudaDeleter>( pMemory );
}
于 2013-02-20T08:14:38.627 回答