CUDA编程练习(六) 卷积

穷且益坚 不坠青云之志

1 前言与想法

CUDA编程还有以下内容需要整:

  1.  排序的样本排序、双调排序网络和奇偶排序;
  2.  矩阵转置(访存密集型讨论);
  3.  前缀和;
  4.  归约(可以写短点,前面多少涉及过);
  5.  thrust、CUBLAS、cuDNN等库的使用;
  6.  profiler、nsight、CUDA GDB的使用;
  7.  回头看;

这么一看,从数量上,也到一半了。

卷积是很经典的图像处理的方法了,很好理解,我想实现一个贴近应用的卷积,即可设置步长(一般是偶数),核一般是奇数,我见过的的卷积核有:15 8,7 4,5 2,3 2,3 1

全程都使用增广法,判断不了一点!

实现以下几个版本:

  • CPU版;
  • 全局内存版本(1D线程);
  • 核常量版本(1D线程);
  • 核常量,共享内存版本(2D线程);

顺带提一嘴,优化想法并非总是有效,因为牵一发而动全身,线程数量与映射方式、共存、寄存器、全局存储,彼此有联系。L1和L2缓存的加入,有时让共存很尴尬。外带编译器自带的优化,啥时候变了我都不懂!

还有,矩阵乘法已经可以用硬件实现了,那什么Tensor Core。不会没事,以后肯定不让你写这个

2 代码

2.1 预定义

#define MAT_SIZE 640  // 统一方阵
#define KERNEL_SIZE 7  // 常见的最大尺寸
#define STRIDE 4
#define ELEM_TYPE float
#define BLOCK_DIM 256
#define GRID_DIM 64
#define BLOCK_DIM_X 16
#define BLOCK_DIM_Y BLOCK_DIM_X
#define GRID_DIM_X 8
#define GRID_DIM_Y GRID_DIM_X
#define SHARED_SIZE ((BLOCK_DIM_X-1)*STRIDE+1+KERNEL_SIZE/2*2)

#define CUDA_CALL(x) do { if((x) != cudaSuccess) { printf("Error at %s:%d\n %s \n",__FILE__,__LINE__,cudaGetErrorString((x))); return EXIT_FAILURE;}} while(0)

2.2 CPU版本

兄弟,咱保证就用指针好不好?

// cpu 增广卷积 带步长
ELEM_TYPE* cpu_conv_2d(ELEM_TYPE* mat, ELEM_TYPE* kernel, int n, int size_out, int kernel_size, int stride) {
    int n1 = n+kernel_size/2*2;
    ELEM_TYPE* ret = new ELEM_TYPE[size_out*size_out];
    // 外循环,两层
    for (int i=0; i<n; i+=stride) {
        for (int j=0; j<n; j+=stride) {
            // 内循环,两层,二维嘛
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值