CUDA中动态分配的数组副本

时间:2017-02-23 10:11:21

标签: cuda

我们可以使用任何方法在CUDA内核中复制数组吗?

例如:

__device__ int number_element; __device__ void copyData(float* input, float* output){}

我想将某些输入数组中的数据复制到满足某些条件的输出,并将复制的元素数量复制到 number_element

谢谢。

2 个答案:

答案 0 :(得分:1)

您真正描述的内容称为流压缩。推力库内置了一系列流压缩函数,可以在内核中调用。作为一个简单的例子:

#include <iostream>
#include <thrust/copy.h>
#include <thrust/execution_policy.h>

struct op
{
  __host__ __device__
  bool operator()(const int x) { return (x % 3) == 0; }
};

__global__ void kernel(int* input, int* output, int Nin, int* Nout)
{
    auto output_end = thrust::copy_if(thrust::device, input, input + Nin, output, op());
    *Nout = output_end - output;
}

int main()
{
    const int N = 10;
    const size_t sz = sizeof(int) * size_t(N);

    int* in;
    cudaMallocManaged((void **)&in, sz);
    int* out;
    cudaMallocManaged((void **)&out, sz);
    int* Nout;
    cudaMallocManaged((void **)&Nout, sizeof(int));

    for(int i=0; i<N; i++) {
        in[i] = 1+i;
        out[i] = -1;
    }

    kernel<<<1,1>>>(in, out, N, Nout);
    cudaDeviceSynchronize();

    for(int i=0; i < *Nout; i++) {
        std::cout << i << " " << out[i] << std::endl;
    }

    return 0;
}

编译和运行如下:

$ nvcc -std=c++11 -arch=sm_52 thrust_device_compact.cu 
$ ./a.out 
0 3
1 6
2 9

这可能是在内核中对少量数据执行流压缩的快速简便方法。如果您有大量数据,那么使用来自主机的推力并代表您推送内核可能更有意义。

答案 1 :(得分:0)

是的,你可以写一个。

例如,你可以按照这个答案的方式进行:Best way to copy global into shared memory,只需跳过涂抹部分。

//assumes sizeof(T) is multiple of sizeof(int) and is aligned to at least alignof(int)
//assumes single-dimention kernel
//assumes it is launched for all threads in block
template <typename T>
__device__ void memCopy(T* dest, T* src, size_t size) {
    int* iDest = (int*)dest;
    int* iSrc = (int*)src;
    for(size_t i = threadIdx.x; i<size*sizeof(T)/sizeof(int); i+=blockDim.x)
        iDest[i] = iSrc[i];
    __syncthreads();
}

这假定单个块操作,旨在用于该特定块。 如果你想要一个完整的网格,你可以,但需要将它作为一个单独的内核启动,以确保所有其他块都可以看到所有写入。在这种情况下,cudaMemcpy可能比内核调用更好。

在任何情况下,对于网格操作,您需要更改循环:

for(size_t i = threadIdx.x+blockIdx.x*blockDim.x;
    i<size*sizeof(T)/sizeof(int);
    i+=blockDim.x*gridDim.x)