Cuda - 大数组初始化

时间:2015-06-24 18:36:29

标签: c cuda

为gpu初始化大量整数的最佳方法(有效)是什么?我需要为前两个元素分配1,为其他元素分配0(对于Eratosthenes的Sieve)。

  1. cudaMemcpy
  2. cudaMemset +设置内核中第一个元素的值
  3. 在内核中直接初始化
  4. sth else
  5. 注意:数组大小是动态的(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);
    

    我很感激一个例子。

1 个答案:

答案 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 C Programming Guide

  

CUDA in-kernel malloc()函数至少分配size个字节   从设备堆中返回指向已分配内存的指针   NULL如果内存不足以满足请求。该   保证返回的指针与16字节边界对齐。

遗憾的是,calloc()函数未实现,因此无论如何都需要对其进行memset。分配的内存具有CUDA上下文的生命周期,但您可以随时从此内核或后续内核中明确调用free()

  

由给定的CUDA线程通过malloc()分配的内存仍然存在   分配给CUDA上下文的生命周期,或直到它为止   通过致电free()明确发布。它可以被任何其他人使用   CUDA甚至可以从后续的内核启动开始。

尽管如此,我对补充cudaMemcpy()并不在意,因为只需要复制两个元素,可能占总执行量的0.01%时间(很容易描述)。选择使您的代码清晰的任何方式。否则它是premature optimization