推力:变换\减少:一元运算运算符中的Cudamaloc

推力:变换\减少:一元运算运算符中的Cudamaloc,cuda,gpgpu,thrust,Cuda,Gpgpu,Thrust,在我的一元运算运算符中,我需要创建一个临时数组。 我想cudamaloc是一条路。 但是,它是性能高效还是有更好的设计 struct my_unary_op { __host__ __device__ int operator()(const int& index) const { int* array; cudaMalloc((void**)&array, 10*sizeof(int)); for(int i =

在我的
一元运算运算符中,我需要创建一个临时数组。
我想
cudamaloc
是一条路。
但是,它是性能高效还是有更好的设计

struct my_unary_op
{
    __host__ __device__ int operator()(const int& index) const
    {
        int* array;
        cudaMalloc((void**)&array, 10*sizeof(int));

        for(int i = 0; i < 10; i++)
            array[i] = index;

        int sum=0;
        for(int i=0; i < 10 ; i++)
            sum += array[i];

        return sum;
    };

};
int main()
{
    thrust::counting_iterator<int> first(0);
    thrust::counting_iterator<int> last = first+100;

    my_unary_op unary_op = my_unary_op();

    thrust::plus<int> binary_op;

    int init = 0;
    int sum = thrust::transform_reduce(first, last, unary_op, init, binary_op);

    return 0;
};
结构我的一元操作
{
__主机\uuuuuu\uuuu设备\uuuuuu int运算符()(常量int和索引)常量
{
int*数组;
cudamaloc((void**)和数组,10*sizeof(int));
对于(int i=0;i<10;i++)
数组[i]=索引;
整数和=0;
对于(int i=0;i<10;i++)
总和+=数组[i];
回报金额;
};
};
int main()
{
首先计算迭代器(0);
推力::计数迭代器last=first+100;
我的一元数=我的一元数;
推力:加上二进制运算;
int init=0;
int sum=推力::变换减少(第一,最后,一元运算,初始化,二进制运算);
返回0;
};

您将无法在
\uuu设备\uuu
函数中编译
cudamaloc()
,因为它是一个仅限主机的函数。但是,您可以使用普通的
malloc()
new
(在计算能力>=2.0的设备上),但在设备上运行时效率不高。这有两个原因。第一个是在内存分配调用期间序列化并发运行的线程。第二个是调用以块的形式分配全局内存,这些块的排列方式使得当内存加载和存储指令由一个warp中的32个线程运行时,它们不是相邻的,因此无法获得正确的合并内存访问

您可以通过在
\uuu设备
函数中使用固定大小的C样式数组(即
int-array[10];
)来解决这两个问题。小型、固定大小的数组有时可以由编译器进行优化,以便存储在寄存器文件中,以实现极快的访问。如果编译器将它们存储在全局内存中,它将使用本地内存。本地内存存储在全局内存中,但它是以这样一种方式交错的:当warp中的32个线程运行load或store指令时,每个线程访问内存中的相邻位置,从而使事务能够完全合并

如果您在运行时不知道C数组的大小,请在数组中分配一个最大大小,并保留一些未使用的大小

我认为固定大小数组使用的内存总量将取决于GPU上并发处理的线程总数,而不是内核启动的线程总数。@mharris中显示了如何计算并发线程的最大可能数量,对于GTX580,该数量为24576。因此,如果固定大小的数组是16个32位值,那么该数组使用的最大内存量可能是1536KiB

如果需要大范围的数组大小,可以使用模板编译具有多种不同大小的内核。然后,在运行时,选择一个能够容纳所需大小的。但是,如果您只分配可能需要的最大值,那么内存使用将不会限制您可以启动的线程数量