caffe--Blob

Blob数据结构

现有一段简单的代码(具体见《21天实战Caffe》)

#include <vector>
#include <iostream>
#include <caffe/blob.hpp>

using namespace caffe;
using namespace std;

int main(void)
{

    Blob<float> a;
    cout << "Size : " << a.shape_string() << endl;
    a.Reshape(1, 2, 3, 4);
    cout << "Size: " << a.shape_string() << endl;
    cout << "I am jiangcheng" <<endl;
    return 0;
}

在编译这段代码的时候,遇到了以下的问题, 具体解决方法如下
/home/laojiang/jiangcheng/caffe/anzhuangbao/caffe/include/caffe/util/device_alternate.hpp:34:23: fatal error: cublas_v2.h: 没有那个文件或目录

g++ Blob.cpp -I /home/laojiang/jiangcheng/caffe/anzhuangbao/caffe/include/  -I /home/laojiang/jiangcheng/caffe/anzhuangbao/caffe/.build_release/src/ -L /home/laojiang/jiangcheng/caffe/anzhuangbao/caffe/build/lib/ -lcaffe -I /usr/local/cuda-8.0/include/ -L /usr/local/cuda-8.0/lib64/

//home/laojiang/anaconda3/lib/libpng16.so.16:对‘inflateValidate@ZLIB_1.2.9’未定义的引用
首先到https://sourceforge.net/projects/libpng/?source=directory下载libpng-1.6.35.tar.xz
然后利用tar -xvf libpng-1.6.35.tar.xz来进行解压.
之后依次进行以下操作:

1. cd libpng-1.6.35
2. ./configure
3. make check
4. sudo make install
5. sudo ldconfig

至此, libpng16.so.16安装成功!


Blob数据结构

该数据结构的地址:
your_path/caffe/src/caffe/blob.cpp

template <typename Dtype>
void Blob<Dtype>::Reshape(const int num, const int channels, const int height,
    const int width) {
  vector<int> shape(4);
  shape[0] = num;
  shape[1] = channels;
  shape[2] = height;
  shape[3] = width;
  Reshape(shape);
}

template <typename Dtype>
void Blob<Dtype>::Reshape(const vector<int>& shape) {
  CHECK_LE(shape.size(), kMaxBlobAxes);
  count_ = 1;
  shape_.resize(shape.size());
  if (!shape_data_ || shape_data_->size() < shape.size() * sizeof(int)) {
    shape_data_.reset(new SyncedMemory(shape.size() * sizeof(int)));
  }
  int* shape_data = static_cast<int*>(shape_data_->mutable_cpu_data());
  for (int i = 0; i < shape.size(); ++i) {
    CHECK_GE(shape[i], 0);
    if (count_ != 0) {
      CHECK_LE(shape[i], INT_MAX / count_) << "blob size exceeds INT_MAX";
    }
    count_ *= shape[i];
    shape_[i] = shape[i];
    shape_data[i] = shape[i];
  }
  if (count_ > capacity_) {
    capacity_ = count_;
    data_.reset(new SyncedMemory(capacity_ * sizeof(Dtype)));
    diff_.reset(new SyncedMemory(capacity_ * sizeof(Dtype)));
  }
}

源码注释
1. Dtype* mutable\_cpu\_data();
由函数声明可以看出,mutable_cpu_data()函数返回的实际上是一个Dtype指针.
mutable_cpu_data函数定义如下:

template <typename Dtype>
Dtype* Blob<Dtype>::mutable_cpu_data() {
  CHECK(data_);
  return static_cast<Dtype*>(data_->mutable_cpu_data());
}

其核心代码如下

return static_cast<Dtype*>(data_->mutable_cpu_data());

shared_ptr<SyncedMemory> data_; 这说明data_是智能指针,指向SyncedMemory类型. 所以在SyncedMemory类中应当有成员函数mutable_cpu_data().
查阅caffe/include/caffe/syncedmem.hpp以及caffe/src/caffe/syncedmem.cpp,可发现该函数定义如下:

void* SyncedMemory::mutable_cpu_data() {
  check_device();
  to_cpu(); //首先同步一下cpu和gpu的数据
  head_ = HEAD_AT_CPU; //将head_重置为HEAD_AT_CPU
  return cpu_ptr_;
}

check_device()函数的定义如下:

void SyncedMemory::check_device() {
#ifndef CPU_ONLY
#ifdef DEBUG
  ......
#endif
#endif
}
}

这说明check_device()只会用于debug以及使用GPU的情况. 从逻辑上来看,可以暂时不用管他.
to_cpu()函数的定义如下:

inline void SyncedMemory::to_cpu() {
  check_device();
  switch (head_) {
  case UNINITIALIZED:
  ......
  case HEAD_AT_GPU:
#ifndef CPU_ONLY
    if (cpu_ptr_ == NULL) {
      CaffeMallocHost(&cpu_ptr_, size_, &cpu_malloc_use_cuda_);
      own_cpu_data_ = true;
    }
    caffe_gpu_memcpy(size_, gpu_ptr_, cpu_ptr_);
    head_ = SYNCED;
#else
    NO_GPU;
#endif
    break;
  case HEAD_AT_CPU:
  case SYNCED:
    break;
  }
}

其中head_如下:

enum SyncedHead { UNINITIALIZED, HEAD_AT_CPU, HEAD_AT_GPU, SYNCED };
SyncedHead head_;

至此可以看出to_cpu()函数的主要目的是同步cpu和gpu的数据.具体可见相关文章.

cpu_ptr_指向cpu上分配的内存,如果cpu_ptr = NULL, 说明没有分配内存;

下面来分析一下blob中定义的三个智能指针:
1. shape_data_指针;
2. data_指针;
3. diff_指针;

shape_data_指针

shape_data_是指向SyncedMemory类型对象的智能指针.
shape_data_所指向的空间里存放着num, channels, height, width.

data_指针

data_也是指向SyncedMemory类型对象的智能指针. 访问其的接口是public成员函数data().
data_所指空间存放着的是每次Forward时会用到的数据

diff_指针

diff_是指向SyncedMemory类型对象的智能指针,访问其的接口是public成员函数diff().

其他

SyncedMemory类中size()函数的定义如下:
size_t size() const { return size_; } 那么size_是指啥?分配的内存大小,单位为字节.

猜你喜欢

转载自blog.csdn.net/weixin_37486217/article/details/82562248