如何初始化使用cudaMalloc()
分配的设备数组?
我尝试使用cudaMemset
,但它无法初始化除0.code
之外的所有值。下面是cudaMemset
的示例,其中值初始化为5。
cudaMemset(devPtr,value,number_bytes)
如何初始化使用cudaMalloc()
分配的设备数组?
我尝试使用cudaMemset
,但它无法初始化除0.code
之外的所有值。下面是cudaMemset
的示例,其中值初始化为5。
cudaMemset(devPtr,value,number_bytes)
正如您所发现的那样,cudaMemset
的工作方式类似于 C 标准库中的 memset
。引用文档:
cudaError_t cudaMemset ( void * devPtr,
int value,
size_t count
)
使用值value填充由devPtr指向的内存区域的前count个字节。
因此,value
是一个字节值。如果您执行以下操作:
int *devPtr;
cudaMalloc((void **)&devPtr,number_bytes);
const int value = 5;
cudaMemset(devPtr,value,number_bytes);
devPtr
的每个 字节 设置为 5。如果 devPtr
是一个整数数组,则结果将是每个整数单词都具有值 84215045。这可能不是您想要的。
使用运行时 API,您可以编写自己的通用内核来执行此操作。它可能非常简单,例如:
template<typename T>
__global__ void initKernel(T * devPtr, const T val, const size_t nwords)
{
int tidx = threadIdx.x + blockDim.x * blockIdx.x;
int stride = blockDim.x * gridDim.x;
for(; tidx < nwords; tidx += stride)
devPtr[tidx] = val;
}
(标准免责声明:在浏览器中编写,从未编译,从未测试,使用风险自负)。
只需为所需类型实例化模板,并使用适当的网格和块大小调用它,注意现在最后一个参数是单词计数,而不是像cudaMemset
中的字节计数。这与cudaMemset
的操作并没有什么不同,使用该API调用会导致内核启动,这与我上面发布的内容并没有太大区别。
或者,如果您可以使用驱动程序API,则有cuMemsetD16
和cuMemsetD32
,它们执行相同的操作,但针对半个和全32位单词类型。如果您需要设置64位或更大的类型(因此是双精度或矢量类型),则最好使用自己的内核。
cudaMemset
没有办法。要么运行自己的内核,要么使用驱动程序API中的cuMemsetD32
/cuMemsetD32
。 - talonmiesfor(; tidx < nwords; tidx += stride)
,以及内核调用和为什么使用反直觉的单词大小。template <typename T>
__global__ void kernelInitializeArray(T* __restrict__ a, const T value,
const size_t n, const size_t incx) {
int tid = threadIdx.x + blockDim.x * blockIdx.x;
if (tid*incx < n) {
a[tid*incx] = value;
}
}
template <typename T>
void deviceInitializeArray(T* a, const T value, const size_t n, const size_t incx) {
int number_of_blocks = ((n / incx) + BLOCK_SIZE - 1) / BLOCK_SIZE;
dim3 gridDim(number_of_blocks, 1);
dim3 blockDim(BLOCK_SIZE, 1);
kernelInitializeArray<T> <<<gridDim, blockDim>>>(a, value, n, incx);
}
cudaMemset
的代码吗? - geekcudaMemset
函数中,参数的值是 字节 值,而不是单词值,也就是和C标准库中的memset
函数一样吗? - talonmies