caffe common 程序分析 类中定义类

caffe中 有 common.hpp 和common.cpp

// The main singleton of Caffe class and encapsulates the boost and CUDA random number
// generation function, providing a unified interface.

caffe的singleton 类, 封装boost和cuda等操作。 提供一个统一的接口, 是一种常见的设计模式

(1) 设置cuda 随机数


在具体实现中,这里还在类中定义一个类,例如:

class Caffe {
 public:
  ~Caffe();
  inline static Caffe& Get() {
    if (!singleton_.get()) {
      singleton_.reset(new Caffe());
    }
    return *singleton_;
  }
  enum Brew { CPU, GPU };


  // This random number generator facade hides boost and CUDA rng
  // implementation from one another (for cross-platform compatibility).
  class RNG {
   public:
    RNG();
    explicit RNG(unsigned int seed);
    explicit RNG(const RNG&);
    RNG& operator=(const RNG&);
    void* generator();
   private:
    class Generator;
    shared_ptr<Generator> generator_;
  };

}

类中定义一个类,虽然可以,但是建议尽量不要用,可读性不好。类都应当对是可以独立存在的抽象

这种方法主要是用于封装,要访问 RNG类,可以通过使用Caffe::RNG来用

这种方法可以 在类中封装结构体。但是在c++中结构体和类其实是一个东西,唯一区别是类的成员默认是private,而结构体是public

但是由于一直以来的习惯,结构体一般只是作为存储数据用的数据结构,没有具体行为,这点也可以看做和类的区别, 因为类是有行为的(成员函数)

结构体定义在类的内部和外部都是可以的,但是为了程序的可读性, 一般定义在类的外部。

----------------------------------------------------------------------------------------------------------------------------

其中用到一个宏定义CUDA_KERNEL_LOOP

common.hpp中有。


#defineCUDA_KERNEL_LOOP(i,n) \

for(inti = blockIdx.x * blockDim.x + threadIdx.x; \

i < (n); \

i +=blockDim.x * gridDim.x)



先看看caffe采取的线程格和线程块的维数设计,

还是从common.hpp可以看到

CAFFE_CUDA_NUM_THREADS

CAFFE_GET_BLOCKS(constintN)

明显都是一维的。


整理一下CUDA_KERNEL_LOOP格式看看,

for(inti = blockIdx.x * blockDim.x + threadIdx.x;

i< (n);

i+= blockDim.x * gridDim.x)

blockDim.x* gridDim.x表示的是该线程格所有线程的数量。

n表示核函数总共要处理的元素个数。

有时候,n会大于blockDim.x* gridDim.x,因此并不能一个线程处理一个元素。

由此通过上面的方法,让一个线程串行(for循环)处理几个元素。

这其实是常用的伎俩,得借鉴学习一下。




再来看一下这个核函数的实现。


template<typename Dtype>

__global__void mul_kernel(const int n, const Dtype* a,

constDtype* b, Dtype* y)

{

CUDA_KERNEL_LOOP(index,n)

{

y[index]= a[index] * b[index];

}

}


明显就是算两个向量的点积了。

由于向量的维数可能大于该kernel函数线程格的总线程数量。

因此有些线程可以要串行处理几个元素。



其中用到一个宏定义CUDA_KERNEL_LOOP

common.hpp中有。


#defineCUDA_KERNEL_LOOP(i,n) \

for(inti = blockIdx.x * blockDim.x + threadIdx.x; \

i < (n); \

i +=blockDim.x * gridDim.x)



先看看caffe采取的线程格和线程块的维数设计,

还是从common.hpp可以看到

CAFFE_CUDA_NUM_THREADS

CAFFE_GET_BLOCKS(constintN)

明显都是一维的。


整理一下CUDA_KERNEL_LOOP格式看看,

for(inti = blockIdx.x * blockDim.x + threadIdx.x;

i< (n);

i+= blockDim.x * gridDim.x)

blockDim.x* gridDim.x表示的是该线程格所有线程的数量。

n表示核函数总共要处理的元素个数。

有时候,n会大于blockDim.x* gridDim.x,因此并不能一个线程处理一个元素。

由此通过上面的方法,让一个线程串行(for循环)处理几个元素。

这其实是常用的伎俩,得借鉴学习一下。




再来看一下这个核函数的实现。


template<typename Dtype>

__global__void mul_kernel(const int n, const Dtype* a,

constDtype* b, Dtype* y)

{

CUDA_KERNEL_LOOP(index,n)

{

y[index]= a[index] * b[index];

}

}


明显就是算两个向量的点积了。

由于向量的维数可能大于该kernel函数线程格的总线程数量。

因此有些线程可以要串行处理几个元素。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值