Cuda 为什么nvcc不允许将T*类型的指针强制转换为void*?

Cuda 为什么nvcc不允许将T*类型的指针强制转换为void*?,cuda,nvcc,Cuda,Nvcc,使用以下简单的deleter struct CudaDeleter{ void operator()(void * ptr) { cudaFree( ptr ); } }; 在使用nvcc编译的代码中使用deleter时,我遇到以下错误。同一个删除器可以与vs2012编译器配合使用 warning : "std::unique_ptr<_Ty, _Dx>::unique_ptr( const std::unique_ptr<_Ty, _Dx>::_Myt &)

使用以下简单的deleter

struct CudaDeleter{ void operator()(void * ptr) { cudaFree( ptr ); } };
在使用nvcc编译的代码中使用deleter时,我遇到以下错误。同一个删除器可以与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) );
}

以下内容适合我。尝试下面的独立代码,如果它可以工作,那么您需要识别代码的差异,如果不能,则说明您的设置有所不同

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

以下内容适合我。尝试下面的独立代码,如果它可以工作,那么您需要识别代码的差异,如果不能,则说明您的设置有所不同

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

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

并不是说任何T*都不能被丢进一个空*中,而是常数T*不能被丢进空*

此外,cudaFree无法释放指向const的指针,这意味着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 );
}

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

并不是说任何T*都不能被丢进一个空*中,而是常数T*不能被丢进空*

此外,cudaFree无法释放指向const的指针,这意味着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 );
}

nvcc编译器似乎有太多这些奇怪的怪癖,另一个可能是无法支持的范围,未能给予适当的错误时,模板失败。。。最好是用NVCC编译器尽可能少地编译代码吗?这是一个很好的解释错误——你正在把C++智能指针传递给DELTER函数,并且它期望空洞*。不要责怪编译器…..不,我在构造所述智能指针时将deleter函数传递给智能指针nvcc是否支持c++11的unique_ptr?使用unique_ptr时,您可能必须为nvcc/gcc启用c++11功能。另一方面,void*是c样式代码。模板结构CudaDeleter{void operator*ptr{…}}可能是用于unique_ptr的更好的删除函子。问题是nvcc不是编译器。它不编译代码,也不编译此代码,在本例中,主机编译器是vs2012。它所做的是引导编译并设置编译器参数。编译器选项可能会禁用对c++11的支持,但这就是可能发生的所有情况。nvcc编译器似乎有太多这些奇怪的怪癖,另一个怪癖是无法支持范围,无法在模板失败时给出正确的错误。。。最好是用NVCC编译器尽可能少地编译代码吗?这是一个很好的解释错误——你正在把C++智能指针传递给DELTER函数,并且它期望空洞*。不要责怪编译器…..不,我在构造所述智能指针时将deleter函数传递给智能指针nvcc是否支持c++11的unique_ptr?使用unique_ptr时,您可能必须为nvcc/gcc启用c++11功能。另一方面,void*是c样式代码。模板结构CudaDeleter{void operator*ptr{…}}可能是用于unique_ptr的更好的删除函子。问题是nvcc不是编译器。它不编译代码,也不编译此代码,在本例中,主机编译器是vs2012。它所做的是引导编译并设置编译器参数。编译器选项可能会禁用对c++11的支持,但这就是可能发生的一切。