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更有优势一些

  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数组归约是指将一个数组中的所有元素经过某种操作后,得到一个最终结果的过程。例如,将一个数组中的所有元素相加,就是一种数组归约操作。在CUDA中,可以使用reduce函数来实现数组归约。 示例代码如下: ```cuda #include <stdio.h> #define N 1024 __global__ void reduce(int *g_idata, int *g_odata) { extern __shared__ int sdata[]; // 每个线程加载一个元素到共享内存 unsigned int tid = threadIdx.x; unsigned int i = blockIdx.x * blockDim.x + threadIdx.x; sdata[tid] = g_idata[i]; __syncthreads(); // 归约操作 for (unsigned int s = blockDim.x / 2; s > 0; s >>= 1) { if (tid < s) { sdata[tid] += sdata[tid + s]; } __syncthreads(); } // 将归约结果存储到全局内存中 if (tid == 0) { g_odata[blockIdx.x] = sdata[0]; } } int main(void) { int *a, *d_a, *d_b; int size = N * sizeof(int); // 分配内存空间 a = (int *)malloc(size); cudaMalloc((void **)&d_a, size); cudaMalloc((void **)&d_b, size); // 初始化数组 for (int i = 0; i < N; i++) { a[i] = i; } // 将数组复制到设备上 cudaMemcpy(d_a, a, size, cudaMemcpyHostToDevice); // 归约操作 int block_size = 512; reduce<<<(N + block_size - 1) / block_size, block_size, block_size * sizeof(int)>>>(d_a, d_b); // 将结果从设备上复制回主机内存 int result; cudaMemcpy(&result, d_b, sizeof(int), cudaMemcpyDeviceToHost); printf("sum: %d\n", result); // 释放内存空间 free(a); cudaFree(d_a); cudaFree(d_b); return 0; } ``` 在上面的示例代码中,首先定义了一个大小为N的整型数组a,然后将该数组复制到设备上。接着定义了一个reduce函数,该函数使用共享内存实现了数组归约操作。最后,在主函数中调用reduce函数进行归约操作,并将结果从设备上复制回主机内存。最终,输出结果即为数组中所有元素的和。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值