从查看CUDA 5.5 API参考和CUDA C程序员指南得知,似乎没有cudaCalloc()
,这是标准C库的calloc()
在GPU上的等效函数。
- 真的没有API功能可以分配一个以全零初始化的缓冲区吗?
- 有没有比调用
cudaMalloc()
和cudaMemset()
更好的方法?
从查看CUDA 5.5 API参考和CUDA C程序员指南得知,似乎没有cudaCalloc()
,这是标准C库的calloc()
在GPU上的等效函数。
cudaMalloc()
和cudaMemset()
更好的方法?是否真的没有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()
);或者,如果您愿意,您可以直接将您喜欢的错误检查构建到宏中。有关错误处理,请参见 此问题。
以下是一个内联函数的解决方案。devPtr
应该是指向任何东西的指针。将 void*
作为函数参数可以使调用者免除进行 类型转换 的烦恼。
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;
}
cudaMalloc
修改了它的第一个参数,因此需要一个指向指针变量的指针。我们想要像 _cuda_calloc(&p,...)
这样调用函数,其中 p
可以是指向 int、float 或任何其他类型的指针。如果 devPtr
声明为 void**
,则调用该函数将需要进行转换。请参见答案中的链接。"应该是"有什么不准确之处? - Claas Bontusthrust::device_vector
,它会默认构造其元素。对于原始类型来说,这与 calloc
的行为相同。CUDA Runtime API中没有类似于calloc()
的功能,也没有其他低级别的等效功能。相反,您可以执行以下操作:
cudaMalloc(&ptr, size);
cudaMemset(ptr, 0, size);
cudaMemsetAsync()
函数,但实话说,cudaMalloc()
目前的速度已经足够慢了,所以并不重要。
thrust::device_vector
。 - Jared Hoberockthrust::device_vector
是一个好主意的原因吗? - einpoklum