CUDA 真的没有类似 calloc() 的 API 调用吗?
Posted
技术标签:
【中文标题】CUDA 真的没有类似 calloc() 的 API 调用吗?【英文标题】:Does CUDA really not have a calloc()-like API call? 【发布时间】:2014-01-20 12:10:51 【问题描述】:从CUDA 5.5 API Reference 和CUDA C Programming Guide 看来,似乎没有cudaCalloc()
,在GPU 上相当于标准C 库的calloc()
。
cudaMalloc()
然后cudaMemset()
更好的办法吗?
【问题讨论】:
编译器库可能将 calloc 实现为 malloc + memset 的包装器。 @Lundin:我会说可能不会。您可以分配归零的内存块而无需实际设置任何数据,只需将块标记为空(例如,未从虚拟内存映射到物理内存,写入它们会导致页面错误)。当然,这取决于您使用的是什么机器。我不确定 GPU 上的内存归零是如何发生的,但很可能你可以做得比 malloc+memset 更好。 使用thrust::device_vector
。
@JaredHoberock:你能回答这个问题并解释为什么在这种情况下使用thrust::device_vector
是一个好主意吗?
下面的答案有没有让你满意的?如果是,请接受。你有扔石头藏手的坏习惯。
【参考方案1】:
真的没有用于分配初始化为全零的缓冲区的 API 功能吗?
真的没有。
我可以在 cudaMalloc() 之后执行 cudaMemset() 吗?
如果为了方便起见,您可以使用宏(如果第一个问题的答案是否定的,您还没有告诉我们您所说的更好是什么意思):
#define cudaCalloc(A, B, C) \
do \
cudaError_t __cudaCalloc_err = cudaMalloc(A, B*C); \
if (__cudaCalloc_err == cudaSuccess) cudaMemset(*A, 0, B*C); \
while (0)
上面的宏可以和我通常做的那种错误检查一起工作(它基于使用cudaGetLastError()
;或者如果你愿意,你可以直接在宏中构建你喜欢的错误检查。有关错误,请参阅this question处理。
【讨论】:
重新审视您的答案 - 为什么使用宏而不是标记为inline
的函数?
你可以这样做。
我可能在想,在我们更加文明的时代(好吧,无论如何编程),最好编辑你的答案来推荐它。除非绝对必要 IMO,否则不应鼓励使用宏。顺便说一句,Nikolay Sakharnykh 打招呼。或者更确切地说,我提到了你的名字,他承认了:-)
为什么不添加答案?然后,您将因更加文明而受到赞誉。我会赞成。你甚至可以不接受这个并接受你自己的。【参考方案2】:
如果您想要的只是一种将新分配归零的简单方法,您可以使用thrust::device_vector
,它默认构造其元素。对于原始类型,这与calloc
的行为相同。
【讨论】:
【参考方案3】:CUDA 运行时 API 中没有类似 calloc()
的功能,也没有其他较低级别的等效功能。相反,您可以执行以下操作:
cudaMalloc(&ptr, size);
cudaMemset(ptr, 0, size);
请注意,这都是同步的。还有一个cudaMemsetAsync()
,虽然,坦率地说,cudaMalloc()
s 目前速度很慢,这并不重要。
【讨论】:
我认为使用 Memcpy 将缓冲区归零是一个相当糟糕的主意。cudaMemset()
无论如何都会与主机异步运行(请参阅ref manual)。
不正确,该函数在大多数情况下都表现出同步行为【参考方案4】:
这是一个带有内联函数的解决方案。 devPtr
应该是指向任何东西的指针。使用void*
作为函数参数会从applying a cast 释放调用者。
inline cudaError_t
_cuda_calloc( void *devPtr, size_t size )
cudaError_t err = cudaMalloc( (void**)devPtr, size );
if( err == cudaSuccess ) err = cudaMemset( *(void**)devPtr, 0, size );
return err;
【讨论】:
已经推荐了。以上是关于CUDA 真的没有类似 calloc() 的 API 调用吗?的主要内容,如果未能解决你的问题,请参考以下文章