在CUDA中初始化设备阵列

时间:2012-05-14 19:36:58

标签: memory-management cuda

如何初始化使用cudaMalloc()分配的设备阵列?

我尝试了cudaMemset,但无法初始化除0.code之外的所有值,因为cudaMemset如下所示,其中value初始化为5.

cudaMemset(devPtr,value,number_bytes)

2 个答案:

答案 0 :(得分:10)

正如您所发现的那样,cudaMemset的工作方式与C标准库memset类似。引自文档:

cudaError_t cudaMemset  (   void *      devPtr,
                            int         value,
                            size_t      count    
                        )           
  

填充devPtr指向的内存区域的第一个计数字节   具有恒定的字节值。

因此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;
}

(标准免责声明:用浏览器编写,从未编译,从未测试过,使用风险自负)。

只需为您需要的类型实例化模板,并使用合适的网格和块大小调用它,注意最后一个参数现在是字数,而不是{{>>中的字节数1}}。这与cudaMemset无论如何都没有任何不同,使用该API调用导致内核启动,这与我上面发布的内容完全不同。

或者,如果您可以使用驱动程序API,则cudaMemsetcuMemsetD16执行相同的操作,但是对于半字和完整的32位字类型。如果你需要设置64位或更大的类型(所以双打或矢量类型),你最好的选择是使用你自己的内核。

答案 1 :(得分:1)

我还需要一个解决这个问题的方法,但我并没有真正理解其他提议的解决方案。特别是我不明白为什么它迭代网格块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);
}