了解 memset 在 CUDA 设备代码中的使用
Understanding the use of memset in CUDA device code
我有一个线性 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
。我可能误解了这里的 memset 用法,因为我正在学习 CUDA。
能否请您建议一种更正此问题的方法?或其他高效 方法来完成此操作。
P.S:我知道thrust::fill()
可能可以很好地做到这一点,但是由于我正在学习CUDA,所以我想知道如何在不使用外部库的情况下做到这一点。
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;
该代码的性能可能会优于内置 memset。
另请注意,内核末尾的 __syncthreads()
调用既是不必要的,也是死锁的潜在来源,应将其删除。有关详细信息,请参阅 here。
我有一个线性 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
。我可能误解了这里的 memset 用法,因为我正在学习 CUDA。
能否请您建议一种更正此问题的方法?或其他高效 方法来完成此操作。
P.S:我知道thrust::fill()
可能可以很好地做到这一点,但是由于我正在学习CUDA,所以我想知道如何在不使用外部库的情况下做到这一点。
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;
该代码的性能可能会优于内置 memset。
另请注意,内核末尾的 __syncthreads()
调用既是不必要的,也是死锁的潜在来源,应将其删除。有关详细信息,请参阅 here。