为gpu初始化大量整数的最佳方法(有效)是什么?我需要为前两个元素分配1,为其他元素分配0(对于Eratosthenes的Sieve)。
注意:数组大小是动态的(n作为参数传递)。
我当前的版本:
int array = (int*) malloc(array_size);
array[0] = 1;
array[1] = 1;
for (int i = 2; i < n; i++) {
array[i] = 0;
}
HANDLE_ERROR(cudaMemcpy(dev_array, array, array_size, cudaMemcpyHostToDevice));
kernel<<<10, 10>>>(dev_array);
我很感激一个例子。
答案 0 :(得分:5)
一种可能性是通过在文件范围内添加以下声明(即,在任何函数之外),在GPU上直接初始化__device__
数组(如果它具有常量):
__device__ int dev_array[SIZE] = {1, 1};
剩下的元素将用零初始化(你可以检查PTX程序集以确保这一点)。
然后,它可以在内核中使用,如:
__global__ void kernel(void)
{
int tid = ...;
int elem = dev_array[tid];
...
}
如果尺寸可变,您可以将cudaMalloc()
与cudaMemset()
合并:
int array_size = ...;
int *dev_array;
cudaMalloc((void **) &dev_array, array_size * sizeof(int));
cudaMemset(dev_array, 0, array_size * sizeof(int));
然后将前两个元素设置为:
int helper_array[2] = {1, 1};
cudaMemcpy(dev_array, helper_array, 2 * sizeof(int), cudaMemcpyHostToDevice);
从compute capability 2.0开始,您还可以通过malloc()
设备函数直接在内核中分配整个数组:
__global__ void kernel(int array_size)
{
int *dev_array;
int tid = ...;
if (tid == 0) {
dev_array = (int *) malloc(array_size * sizeof(int));
if (dev_array == NULL) {
...
}
memset(dev_array, 0, array_size * sizeof(int));
dev_array[0] = dev_array[1] = 1;
}
__syncthreads();
...
}
请注意,来自不同块的线程不知道屏障同步。
CUDA in-kernel
malloc()
函数至少分配size
个字节 从设备堆中返回指向已分配内存的指针NULL
如果内存不足以满足请求。该 保证返回的指针与16字节边界对齐。
遗憾的是,calloc()
函数未实现,因此无论如何都需要对其进行memset。分配的内存具有CUDA上下文的生命周期,但您可以随时从此内核或后续内核中明确调用free()
:
由给定的CUDA线程通过
malloc()
分配的内存仍然存在 分配给CUDA上下文的生命周期,或直到它为止 通过致电free()
明确发布。它可以被任何其他人使用 CUDA甚至可以从后续的内核启动开始。
尽管如此,我对补充cudaMemcpy()
并不在意,因为只需要复制两个元素,可能占总执行量的0.01%时间(很容易描述)。选择使您的代码清晰的任何方式。否则它是premature optimization。