了解CUDA设备代码中memset的用法

时间:2018-07-29 09:44:16

标签: c++ cuda pycuda

我有一个线性int数组arr,它位于CUDA全局存储器上。我想将arr的子数组设置为已定义的值。子数组的起始索引由starts数组给定,而每个子数组的长度在counts数组中给定。

我想要做的是将子数组i的值从starts[i]开始设置,一直到counts[i]到值starts[i]。也就是说,操作是:

arr[starts[i]: starts[i]+counts[i]] = starts[i]

我想到了在内核中使用memset()来设置值。但是,它没有被正确地写入(为数组元素分配了一些随机值)。我正在使用的代码是:

#include <stdlib.h>
__global__ void kern(int* starts,int* counts, int* arr,int* numels)
{
    unsigned int idx = threadIdx.x + blockIdx.x*blockDim.x;

    if (idx>=numels[0])
        return;

    const int val = starts[idx];
    memset(&arr[val], val, sizeof(arr[0])*counts[idx]) ;
    __syncthreads();
}

请注意,numels[0]包含starts数组中的元素数。

我已经用cuda-memcheck()检查了代码,但没有收到任何错误。如果相关,我正在使用PyCUDA。在学习CUDA时,我可能误解了memset的用法。

能否请您提出一种纠正此问题的方法?或其他有效方式来执行此操作。

P.S:我知道thrust::fill()可以很好地做到这一点,但是由于我正在学习CUDA,所以我想知道如何在不使用外部库的情况下做到这一点。

1 个答案:

答案 0 :(得分:0)

CUDA设备代码中的memset和memcpy实现发出简单的,串行的字节值操作(请注意,memset除了字节值之外不能设置其他任何内容,这可能会导致问题出在您尝试使用的值如何设置大于8位。

您可以将memset调用替换为以下内容:

const int val = starts[idx];
//memset(&arr[val], val, sizeof(arr[0])*counts[idx]) ;
for(int i = 0; i < counts[idx]; i++)
    arr[val + i] = val;

该代码的性能可能会优于内置内存集。

还请注意,在内核末尾的__syncthreads()调用既不必要,又是潜在的死锁源,应将其删除。有关更多信息,请参见here