Class
Blob
A wrapper aroundSyncedMemory
holders serving as the basic
computational unit through which Layer, Net, and Solver interact.
Caffe 由Blob、Layer、Net、Solver四大部分组成,其中Blob是之中最底层的结构。caffe的理念就是自下而上不断封装,使得上层代码不需要理会下层的具体操作,使代码变得清晰简洁。为了能够理解其它几层,我们需要从Blob开始。
首先,我们看看Blob类的声明,下面是Blob的成员变量
protected:
shared_ptr<SyncedMemory> data_;
shared_ptr<SyncedMemory> diff_;
shared_ptr<SyncedMemory> shape_data_;
vector<int> shape_;
int count_;
int capacity_;
对于上述代码段,我们先从SyncedMemory
这个类型着手分析。SyncedMemory
封装了在CPU/GPU之间的数据传输同步的操作。Caffe既支持CPU又支持GPU运算,那么我们可能需要处理在CPU host和GPU device上传输数据的操作,Caffe把这些操作全部封装在SyncedMemory这个类中。SyncedMemory
提供给外部的接口如下:
const void* cpu_data(); ①
void* mutable_cpu_data(); ②
对数据的访问提供了两种不同的方法: 第①个方式(const),不会改变数据,而第②个方式(mutable)会改变指针cpu_ptr指向的数据。gpu访问的方法与cpu类似。以上两个函数都是调用了SyncedMemory
的to_cpu方法,不同在于mutable方法会改变head_成员的值。(head_是枚举类型,包含四种状态):
enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };
具体的操作也比较简单,就不一一展开介绍了,大家可以查看SyncedMemory 实现的源码。
我们回到Blob上来,Blob包含两个重要的成员变量data_
和 diff_
,类型为SyncedMemory
的智能指针。 Blob既能用来表示大小为shape_的网络权重W(eg.卷积层的参数n_output × n_input × kernel_size_h × kernel_size_w),也可表示前向传播中数据运算的中间结果(eg. feature map or inut with shape: batch × channel × height × width)。diff表示E对该blob的导数。`count为Blob的中Dtype元素个数(即
shape中各元素的乘积),
capacity`是Blob的容量大小。
!Note
在Blob类的声明关于Blob形状的部分有很多标注为Deprecated的注释,Blob的形状早期用n,c,h,w的四维tensor表示(batch n,channel c, height h , width w),后来直接采用vector去表示Blob的形状,当然现在的代码同时包含这两种接口。
我们再来看Blob的几个成员函数:
template <typename Dtype>
const Dtype* Blob<Dtype>::cpu_data() const {
CHECK(data_);
return (const Dtype*)data_->cpu_data();
}
template <typename Dtype>
Dtype* Blob<Dtype>::mutable_cpu_data() {
CHECK(data_);
return static_cast<Dtype*>(data_->mutable_cpu_data());
}
是的,对cpu_data的访问Blob只是CHECK了下data,然后直接调用的SyncedMemory
的方法cpu_data()
和mutable_cpu_data()
。对于gpu版本和diff_的访问与上述代码相似。
另外还有几个比较重要的函数:
void ShareData(const Blob& other);
void ShareDiff(const Blob& other);
void Update();
void FromProto(const BlobProto& proto, bool reshape = true);
void ToProto(BlobProto* proto, bool write_diff = false) const;
ShareData()
、ShareDiff()
用来共享Blob中的data和diff智能指针指向的内存单元。Update()
是用做Net中的参数Blobs的方法,该函数实现了data = data -diff
的操作。FromProto()
和ToProto()
是用作对caffemodel读写时使用的。具体的分析,在后面的博文中再介绍,也可参考这篇博文。
还有几个常用的函数,例如offset()
用来计算(n,c,w,h)处的存储位置索引,还有cpu版的diff_at(n,c,h,w)
, data_at(n,c,h,w)
等。
Reference
评论 (0)