cuda数组任意长度归约求和

cuda数组任意长度求和

既是记录自己书写的代码 也是方便以后用到代码的时候可以直接复制粘贴,有什么问题或者好的建议 可以私信我 我会耐心回复

本文出现的一些常用宏定义

#define CUDA_ID            \
    uint3 tid = threadIdx; \
    uint3 bid = blockIdx;  \
    uint3 bdim = blockDim; \
    uint3 gdim = gridDim

#define MYID \
    CUDA_ID; \
    const int id = bid.x * bdim.x + tid.x

#define MYSRD(T) extern SRD int srd[];  T *tsrd = (T *)srd

#define CDTSYNC __syncthreads()

#define IFBIGEQ(eq, big) if(eq < big)  eq = big
#define IFSMLEQ(eq, small) if(eq > small) eq = small

#define _IN_OUT_
#define _IN_
#define _OUT_

#define _ARR_
#define _VAL_

工具方法

默认线程块和线程格的y和z都是1,自动计算线程格和线程块的规模

void calculateScalar_grid_block(const int size, dim3& grid, dim3& block, int device_num)
{
    cudaSetDevice(device_num);
    cudaDeviceProp property;
    cudaGetDeviceProperties(&property, device_num);

    grid.x = grid.y = grid.z = block.x = block.y = block.z = 1;

    int maxThreadsPerBlock = property.maxThreadsPerBlock;
    if (size <= maxThreadsPerBlock)
    {
        block.x = size;
    }
    else
    {
        block.x = maxThreadsPerBlock;
        grid.x = std::ceil(size / flt(maxThreadsPerBlock));
    }
}

调用的cuda的内核方法

方法命名还有待改善

template <typename T>
GLB void summation_reduction(_IN_ARR_ const T *data, _IN_VAL_ const int *datasize, _OUT_ARR_ T *dest)
{
    MYID;

    if (id < *datasize)
    {
        MYSRD(T);

        tsrd[tid.x] = data[id];
        CDTSYNC;

        for (int a = 1; a < bdim.x; a *= 2)
        {
            if (tid.x % (a * 2) == 0)
            {
                if (tid.x + a < bdim.x)
                {
                    tsrd[tid.x] += tsrd[tid.x + a];
                }
            }
            CDTSYNC;
        }

        if(tid.x == 0)
        
            dest[bid.x] = tsrd[0];
        
    }
}

主要方法

找max和找min同理, 只需要把内部的大小写逻辑修改一下就可以了

代码还不算完善 可以再增加一个变量 来确定寻找的是最大值还是最小值

template <typename T>
void summation(_IN_ARR_ const T *data, _IN_VAL_ cint size, _OUT_VAL_ T *dest)
{
    CDACCPY(T, d_arr, size, data);

    CDCCPYV(int, d_arr_size, size);

    dim3 grid, block;
    calculateScalar_grid_block(size, grid, block);

    int srdsize = block.x * sizeof(T);
    
    CDANV(T, d_sum, grid.x);

    while (true)
    {
        summation_reduction<<<grid, block, srdsize>>>(d_arr, d_arr_size, d_sum);
        BASE_SYNC;

        if (grid.x == 1)
        {
            break;
        }
        else
        {
            CDACPYDTD(T, d_arr, d_sum, grid.x);
            CDCPYHTDV(int, d_arr_size, grid.x);
            calculateScalar_grid_block(grid.x, grid, block);
            srdsize = block.x * sizeof(T);
        }
    }

    CDCPYDTH(T, dest, d_sum);

    cudaFree(d_arr);
    cudaFree(d_arr_size);
    cudaFree(d_sum);
}

核心思想就是使用cuda多线程的优势,将数组分成多段 每一段同时独立的进行求和 将求和的结果组成一个新的数组 再次将新数组 分段独立求和 直到只剩下一个结果
因为可以每一段分组可以同时进行排序 在速度上会比cpu更有优势一些

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值