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函数线程格的总线程数量。
因此有些线程可以要串行处理几个元素。
---------------------
作者:deep_learninger
来源:CSDN
原文:https://blog.csdn.net/u014114990/article/details/47606635
版权声明:本文为博主原创文章,转载请附上博文链接!