为啥 nvcc 失败允许将 T * 类型的指针转换为 void *?
Posted
技术标签:
【中文标题】为啥 nvcc 失败允许将 T * 类型的指针转换为 void *?【英文标题】:Why does nvcc fail allow casting a pointer of type T * to void *?为什么 nvcc 失败允许将 T * 类型的指针转换为 void *? 【发布时间】:2013-02-19 12:49:04 【问题描述】:使用以下琐碎的删除器
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) );
【问题讨论】:
nvcc 编译器似乎有太多这些奇怪的怪癖,还有一个是不支持 range-for,模板失败时无法给出正确的错误......最好编译为使用 nvcc 编译器尽可能少的代码? 这是一个非常不言自明的错误 - 您正在将 C++ 智能指针传递给删除函数,它需要void *
。不要责怪编译器.....
不,我在构造智能指针时将删除函数传递给智能指针
nvcc是否支持c++11的unique_ptr?使用 unique_ptr 时,您可能必须为 nvcc/gcc 启用 c++11 功能。另一方面,void*
是 c 风格的代码。 template<class T> struct CudaDeleter void operator()(T* ptr)...
可能是 unique_ptr 更好的删除函子。
问题是 nvcc 不是编译器。它不编译代码,也不编译此代码,主机编译器是(在这种情况下是 vs2012)。它所做的是引导编译并设置编译器参数。编译器选项可能会禁用 c++11 支持,但这就是可能发生的一切。
【参考方案1】:
以下内容对我有用。试试下面的独立代码,如果它可以工作,那么你需要确定与你的代码的区别,如果没有,那么你的设置有一些不同。
#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;
【讨论】:
【参考方案2】:我找到了我遇到的问题,最后这是我的错误
不是任何 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 );
【讨论】:
以上是关于为啥 nvcc 失败允许将 T * 类型的指针转换为 void *?的主要内容,如果未能解决你的问题,请参考以下文章
为啥C ++允许将指向基对象的指针转换为派生类的指针[重复]
为啥 nvcc 无法使用 boost::spirit 编译 CUDA 文件?
为啥新的 `Pick<T, K extends keyof T>` 类型允许在 React 的 `setState()` 中使用 `K` 的子集?