参考:http://galoisplusplus.coding.me/blog/2018/05/22/cudaErrorCudartUnloading/

主要是在linux下,使用cuda安装包里的cuda-memcheck来检查内存,它是类似于valgrind的存在。

基本编译配置

首先添加path:

vim ~/.zshrc
export PATH=$PATH:/usr/local/cuda/bin

基于CMake编写C程,cuda相关的内容:

option(use_cuda "Use CUDA?" ON)

if (use_cuda)
    #list(APPEND CMAKE_PREFIX_PATH "/usr/local/cuda")
    if (CMAKE_SYSTEM_NAME MATCHES "Linux")
        set(CUDA_DIR "/usr/local/cuda")
        find_package(CUDA REQUIRED)
        include_directories("${CUDA_DIR}/include")
        link_directories("${CUDA_DIR}/lib64")
    elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
        set(CUDA_DIR "$ENV{CUDA_PATH}")
        find_package(CUDA REQUIRED)
        include_directories("${CUDA_DIR}/include")
        link_directories("${CUDA_DIR}/lib/x64")
    endif()
endif()

if(use_cuda)
    list(APPEND TESTBED_DEP_LIBS
        cudart
        cudart_static
        cuda
        cublas_device
        cudnn
        cublas
    )
endif()

target_link_libraries(testbed ${TESTBED_DEP_LIBS})

使用:

cd ~/work/mycode
mkdir build
cd build
cmake ..
make

cuda-memcheck ./run

一些常识

如果cudaMalloc()后忘记cudaFree(),用cuda-memcheck检查不出来这个错误。。据网友说是会自动回收,不知道cuda是否自带了gc功能2333

BN层的坑

如果是卷积层,可以直接调用cudnnConvolutionForward()函数,它使用caffe一样的padding方式:它的内部默默的做了对称的padding(pad_left == pad_right),调用起来挺容易的。

倒是BN层卡了好久,主要是官方文档有错误。官方文章这样写的:

Note: The input transformation performed by this function is defined as: y := alpha*y + beta *(bnScale * (x-estimatedMean)/sqrt(epsilon + estimatedVariance)+bnBias)

...

alpha, beta
Inputs. Pointers to scaling factors (in host memory) used to blend the layer output value with prior value in the destination tensor as follows: dstValue = alpha[0]*resultValue + beta[0]*priorDstValue.

按照贴出来的文档内容,按它第一行的说法,alpha应该设定为0,beta应该设定为1;按照后面几行的说法,应该是alpha设定为1,beta设定为0。

  • Caffe:已经很久没有人来修了,它压根没有调用cudnnBatchNormalizationForwardInference()
  • TensorFlow: 并没有调用。。不信你grep查一下,或者github上网页里在repo中搜索,找不到的。
  • PyTorch: 还是比较良心,调用了cudnnBatchNormalizationForwardInference( )
  • mini-caffe: 也是调用了cudnnBatchNormalizationForwardInference( )

主要参考mini-caffe和PyTorch,发现BN层应该设定alpha为1, beta为0,这样才能正确算出结果来。看看PyTorch的调用:

    AT_CUDNN_CHECK(cudnnBatchNormalizationForwardInference(
      handle, mode, &one, &zero, //这里,alpha是one, beta是zero
      idesc.desc(), input->data_ptr(),
      idesc.desc(), output->data_ptr(),
      wdesc.desc(),
      weight->data_ptr(),
      bias->data_ptr(),
      running_mean->data_ptr(),
      running_var->data_ptr(),
      epsilon));

当然这里还有一个教训:但凡用CuDNN的xxxDescriptor参数说明的地方,它后面紧接着的几个变量,应该是gpu指针,也就是其值为GPU上的地址,而如果是CPU上的地址就会导致内存错误,比如代码为4或77

举例:

cudnnStatus = cudnnBatchNormalizationForwardInference(
        layer_base->handle_cudnn,
        CUDNN_BATCHNORM_PER_ACTIVATION,
        &alpha,
        &beta,
        bnlayer->bn_layer_input_desc,
        layer_base->bottom_blobs_ptr[0]->gpu_data_ptr, //gpu上的
        bnlayer->bn_layer_output_desc,
        layer_base->top_blobs_ptr[0]->gpu_data_ptr, //gpu上的
        bnlayer->bn_layer_scale_bias_mean_var_desc,
        bnlayer->scale_dev,  //gpu上的
        bnlayer->shift_dev,    //gpu上的
        bnlayer->mean_dev,  //gpu上的
        bnlayer->variance_dev,//gpu上的
        bnlayer->eps
);

cuda基础

CUDA架构的目的,就是减轻早期GPU计算中存在的限制,这些限制使之前的GPU在通用计算中没有广泛应用。
换言之,CUDA就是为了让NVIDIA GPU用于通用计算的技术。

CUDA编程,使用C/C++即可,它仅仅是增加了个别关键字。不需要使用Shader Language,不需要掌握OpenGL,因此编程门槛降低。

编译器:CUDA C程序需要同时在CPU和N卡上执行计算,分别需要各自的编译器。GPU上的编译器,也就是nvcc了。CPU上的话cl.exe/gcc/clang等。

host和device: CPU以及main memory,叫做host;GPU上的memory称为device。 内存拷贝的时候,用cudaMemcpy(),要指定内存拷贝的来源和目的地,是host还是device。

kernel: GPU上执行的函数称为kernel。

向cuda核函数传入结构体指针?

C语言传参,本质上是拷贝一份,因此:简单数据类型直接传入即可,反正复制成本低;复杂类型则传入指针,复制成本低。

而如果需要向函数传入多个参数,就希望传入一个结构体或其指针,作为他们的一个封装。

然而,直接向cuda kernel函数传入CPU下的结构体指针是不行的。问题很明显:把host上的指针给device用,寻址会出现问题。

解决思路有三种:

  1. 使用host和device的统一寻址
  2. 分别创建host和device上的结构体指针,参考https://blog.csdn.net/u013701860/article/details/52605137
  3. 向cuda kernel函数传入多个参数

举个栗子:传入结构体的拷贝是OK的(just_demo),传入host上结构体指针的拷贝,cuda kernel函数会报废的(just_demo2):

#include <stdio.h>

#define CHECK_CUDA(call) \
{ \
    const cudaError_t cudaStatus = call; \
    if (cudaStatus != cudaSuccess) { \
        printf("Error! in file %s, line %d, ", __FILE__, __LINE__); \
        printf("code: %d, reason: %s\n", cudaStatus, cudaGetErrorString(cudaStatus)); \
        exit(1); \
    } \
}

typedef struct Pad{
    int left;
    int right;
    int top;
    int bottom;
}Pad;

__global__ void just_demo(Pad pad) {
    printf("blockIdx: (%d, %d, %d), threadIdx: (%d, %d, %d)",
            blockIdx.x, blockIdx.y, blockIdx.z,
            threadIdx.x, threadIdx.y, threadIdx.z);
    printf("pad: left=%d, right=%d, top=%d, bottom=%d\n",
            pad.left,
            pad.right,
            pad.top,
            pad.bottom);
}

__global__ void just_demo2(Pad* pad) {
    printf("blockIdx: (%d, %d, %d), threadIdx: (%d, %d, %d)",
            blockIdx.x, blockIdx.y, blockIdx.z,
            threadIdx.x, threadIdx.y, threadIdx.z);
    printf("pad: left=%d, right=%d, top=%d, bottom=%d\n",
            pad->left,
            pad->right,
            pad->top,
            pad->bottom);
}

int main(void){
    Pad pad;
    pad.left = 1;
    pad.right = 0;
    pad.top = 1;
    pad.bottom = 0;

    size_t buf_size = 3*4*4*sizeof(float);
    float* data_host = (float*)malloc(buf_size);

    float* data_dev;
    CHECK_CUDA(cudaMalloc(&data_dev, buf_size));

    just_demo<<<3, 5>>> (pad);  // this is OK
    //just_demo2<<<3, 5>>> (&pad); // this will cause unspecified launch failure

    CHECK_CUDA(cudaMemcpy(data_host, data_dev, buf_size, cudaMemcpyDeviceToHost));

    return 0;
}

封装cuda/cudnn写卷积网络前向计算程序的更多相关文章

  1. 2. CNN卷积网络-前向传播算法

    1. CNN卷积网络-初识 2. CNN卷积网络-前向传播算法 3. CNN卷积网络-反向更新 1. 前言 我们已经了解了CNN的结构,CNN主要结构有输入层,一些卷积层和池化层,后面是DNN全连接层 ...

  2. 3. CNN卷积网络-反向更新

    1. CNN卷积网络-初识 2. CNN卷积网络-前向传播算法 3. CNN卷积网络-反向更新 1. 前言 如果读者详细的了解了DNN神经网络的反向更新,那对我们今天的学习会有很大的帮助.我们的CNN ...

  3. 1. CNN卷积网络-初识

    1. CNN卷积网络-初识 2. CNN卷积网络-前向传播算法 3. CNN卷积网络-反向更新 1. 前言 卷积神经网络是一种特殊的深层的神经网络模型,它的特殊性体现在两个方面, 它的神经元间的连接是 ...

  4. 学习笔记CB009:人工神经网络模型、手写数字识别、多层卷积网络、词向量、word2vec

    人工神经网络,借鉴生物神经网络工作原理数学模型. 由n个输入特征得出与输入特征几乎相同的n个结果,训练隐藏层得到意想不到信息.信息检索领域,模型训练合理排序模型,输入特征,文档质量.文档点击历史.文档 ...

  5. 基于TensorFlow解决手写数字识别的Softmax方法、多层卷积网络方法和前馈神经网络方法

    一.基于TensorFlow的softmax回归模型解决手写字母识别问题 详细步骤如下: 1.加载MNIST数据: input_data.read_data_sets('MNIST_data',one ...

  6. 利用TensorFlow识别手写的数字---基于两层卷积网络

    1 为什么使用卷积神经网络 Softmax回归是一个比较简单的模型,预测的准确率在91%左右,而使用卷积神经网络将预测的准确率提高到99%. 2 卷积网络的流程 3 代码展示 # -*- coding ...

  7. EdgeFormer: 向视觉 Transformer 学习,构建一个比 MobileViT 更好更快的卷积网络

    ​  前言 本文主要探究了轻量模型的设计.通过使用 Vision Transformer 的优势来改进卷积网络,从而获得更好的性能. 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟 ...

  8. Pytorch从0开始实现YOLO V3指南 part3——实现网络前向传播

    本节翻译自:https://blog.paperspace.com/how-to-implement-a-yolo-v3-object-detector-from-scratch-in-pytorch ...

  9. [框架安装趟雷指南]Ubuntu+1060+cuda+cudnn+Keras+TH+TF+MXnet

    [框架安装趟雷指南]Ubuntu+1060+cuda+cudnn+Keras+TH+TF+MXnet https://zhuanlan.zhihu.com/p/23480983 天清 9 个月前 写这 ...

随机推荐

  1. .net中的设计模式---单例模式

    .net设计模式: Net设计模式实例之单例模式( Singleton Pattern)  一 : 单例模式的简介:(Brief Introduction) 单例模式(Singleton Patter ...

  2. 10分钟搭建Kubernetes容器集群平台【转】

    官方提供3种方式部署Kubernetes minikube Minikube是一个工具,可以在本地快速运行一个单点的Kubernetes,尝试Kubernetes或日常开发的用户使用.不能用于生产环境 ...

  3. cu命令

    选项: -b:仅显示行中指定直接范围的内容: -c:仅显示行中指定范围的字符: -d:指定字段的分隔符,默认的字段分隔符为“TAB”: -f:显示指定字段的内容: -n:与“-b”选项连用,不分割多字 ...

  4. hibernate框架学习之对象状态

    lHibernate对象共有三种状态 •瞬时状态:瞬时对象 •持久化状态:持久化对象 •托管状态:托管对象 l瞬时对象(Transient Object),简称TO l瞬时对象指的是应用程序创建出来的 ...

  5. sass个人学习笔记

    Materliu 在慕课的视频: http://www.imooc.com/learn/364 . http://www.imooc.com/wiki/371 sass入门:http://www.w3 ...

  6. 【MyEclipse】JSP默认打开方式 设置(双击)

    下图为MyEclipse8.5设置界面,通过window->Preferences打开,并在General选项下选择 Editors->File Associations ,然后选择要设置 ...

  7. $Django ajax简介 ajax简单数据交互,上传文件(form-data格式数据),Json数据格式交互

    一.ajax  1 什么是ajax:异步的JavaScript和xml,跟后台交互,都用json  2 ajax干啥用的?前后端做数据交互:  3 之前学的跟后台做交互的方式:   -第一种:在浏览器 ...

  8. FS 日志空间限定

    一.说明: FS默认安装的log文件,仅仅的限制了每个文件的大小,但是没有限制文件的个数.这种情况下,在FS运行很长时间之后,会出现物理空间不够的情况,导致FS或者mysql 或者其他应用没有空间使用 ...

  9. Multisim 经典学习教程Step by Step

    Tracy Shields编著 ftp://ftp.ni.com/pub/branches/china/Practical%20teaching%20Ideas%20for%20Multisim%20 ...

  10. 将文字数字转阿拉伯数字(Python)

    今天改进爬虫的时候有这样的需求,如果是文字的数字把他转化成数字存储. 然后百度了一下没什么能看的博客. 其实挺无奈的,搜出来的博客全是一样的代码,有的图都是COPY,尤指CSDN,博客质量大多很差.怀 ...