C++

Blob in Caffe

人工智能炼丹师
2019-09-17 / 0 评论 / 153 阅读 / 正在检测是否收录...

Class Blob
A wrapper around SyncedMemory 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类似。以上两个函数都是调用了SyncedMemoryto_cpu方法,不同在于mutable方法会改变head_成员的值。(head_是枚举类型,包含四种状态):
enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };

  • UNINITIALIZED 未初始化
  • HEAD_AT_CPU 数据在CPU
  • HEAD_AT_GPU 数据在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

评论 (0)

取消
粤ICP备2021042327号