如何初始化使用分配的设备数组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
)
用常量字节值填充 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;
}
(标准免责声明:用浏览器编写,从未编译,从未测试,使用风险自负)。
只需为您需要的类型实例化模板并使用合适的网格和块大小调用它,注意最后一个参数现在是word count,而不是 byte count cudaMemset
。这与无论如何都没有什么不同cudaMemset
,使用该 API 调用会导致内核启动,这与我在上面发布的内容太不同了。
或者,如果您可以使用驱动程序 API,还有cuMemsetD16
and cuMemsetD32
,它们可以做同样的事情,但用于半和全 32 位字类型。如果您需要设置 64 位或更大的类型(所以双精度或向量类型),您最好的选择是使用您自己的内核。
我还需要这个问题的解决方案,但我并不真正理解其他提议的解决方案。特别是我不明白为什么它会迭代网格块for(; 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);
}