定义Blob类中每个成员函数,void Blob<Dtype>::Reshape(const vector<int>&)
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| 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))); } }
|
这个函数的功能,当新的reshape后所有维度元素个数N之和小于原来元素个数M,只取M的前N个元素;
当等于时,元素不变。当大于时,所有元素变为零。不过正常的使用是元素个数相同间的reshape。
有了上述的方法,下面的方法调用上面的方法:
void Blob<Dtype>::ReshapeLike(const Blob<Dtype>&)
void Blob<Dtype>::Reshape(int,int,int,int)
:
读取Blob中已有的cpu_data
1 2 3 4 5 6
| template <typename Dtype> const Dtype* Blob<Dtype>::cpu_data() const { CHECK(data_); return (const Dtype*)data_->cpu_data(); }
|
为Blob设置cpu_data
1 2 3 4 5 6 7 8 9 10 11 12
| template <typename Dtype> void Blob<Dtype>::set_cpu_data(Dtype* data) { CHECK(data); size_t size = count_ * sizeof(Dtype); if (data_->size() != size) { data_.reset(new SyncedMemory(size)); diff_.reset(new SyncedMemory(size)); } data_->set_cpu_data(data); }
|
可写访问CPU_data
1 2 3 4 5
| template <typename Dtype> Dtype* Blob<Dtype>::mutable_cpu_data() { CHECK(data_); return static_cast<Dtype*>(data_->mutable_cpu_data()); }
|
其他关于访问,设置cpu,gpu的 data和diff都类似,略:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const Dtype* cpu_data() const; const Dtype* cpu_diff() const;
const int* gpu_shape() const; const Dtype* gpu_data() const; const Dtype* gpu_diff() const;
Dtype* mutable_cpu_data(); Dtype* mutable_gpu_data(); Dtype* mutable_cpu_diff(); Dtype* mutable_gpu_diff();
void set_cpu_data(Dtype* data); void set_gpu_data(Dtype* data);
|
共享BLob数据data:共享diff与下面代码一样。
1 2 3 4 5 6
| template <typename Dtype> void Blob<Dtype>::ShareData(const Blob& other) { CHECK_EQ(count_, other.count()); data_ = other.data(); }
|
执行Updata():
其中:caffe_axpy
在src/caffe/util/math_functions.cpp
中,
caffe_gpu_axpy
在src/caffe/util/math_functions.cu
中。
这两个操作实际是:data_[i] = data_[i] - diff_[i], 其中i=0,1,2,3,4...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| template <typename Dtype> void Blob<Dtype>::Update() { switch (data_->head()) { case SyncedMemory::HEAD_AT_CPU: caffe_axpy<Dtype>(count_, Dtype(-1), static_cast<const Dtype*>(diff_->cpu_data()), static_cast<Dtype*>(data_->mutable_cpu_data())); break; case SyncedMemory::HEAD_AT_GPU: case SyncedMemory::SYNCED: #ifndef CPU_ONLY caffe_gpu_axpy<Dtype>(count_, Dtype(-1), static_cast<const Dtype*>(diff_->gpu_data()), static_cast<Dtype*>(data_->mutable_gpu_data())); #else NO_GPU; #endif break; default: LOG(FATAL) << "Syncedmem not initialized."; } }
|
其他类似的函数结构相同,只是核心操作不同,略
1 2 3 4 5 6 7 8 9
| Dtype asum_data() const; Dtype asum_diff() const;
Dtype sumsq_data() const; Dtype sumsq_diff() const;
void scale_data(Dtype scale_factor); void scale_diff(Dtype scale_factor);
|
共享数据很直接,略
1 2 3
| void ShareData(const Blob& other); void ShareDiff(const Blob& other);
|
从其他blob拷贝数据到当前Blob:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| template <typename Dtype> void Blob<Dtype>::CopyFrom(const Blob& source, bool copy_diff, bool reshape) { if (source.count() != count_ || source.shape() != shape_) { if (reshape) { ReshapeLike(source); } else { LOG(FATAL) << "Trying to copy blobs of different sizes."; } } switch (Caffe::mode()) { case Caffe::GPU: if (copy_diff) { caffe_copy(count_, source.gpu_diff(), static_cast<Dtype*>(diff_->mutable_gpu_data())); } else { caffe_copy(count_, source.gpu_data(), static_cast<Dtype*>(data_->mutable_gpu_data())); } break; case Caffe::CPU: if (copy_diff) { caffe_copy(count_, source.cpu_diff(), static_cast<Dtype*>(diff_->mutable_cpu_data())); } else { caffe_copy(count_, source.cpu_data(), static_cast<Dtype*>(data_->mutable_cpu_data())); } break; default: LOG(FATAL) << "Unknown caffe mode."; } }
|
反序列化数据,将磁盘数据读入protobuff:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| template <typename Dtype> void Blob<Dtype>::FromProto(const BlobProto& proto, bool reshape) { if (reshape) { vector<int> shape; if (proto.has_num() || proto.has_channels() || proto.has_height() || proto.has_width()) { shape.resize(4); shape[0] = proto.num(); shape[1] = proto.channels(); shape[2] = proto.height(); shape[3] = proto.width(); } else { shape.resize(proto.shape().dim_size()); for (int i = 0; i < proto.shape().dim_size(); ++i) { shape[i] = proto.shape().dim(i); } } Reshape(shape); } else { CHECK(ShapeEquals(proto)) << "shape mismatch (reshape not set)"; } Dtype* data_vec = mutable_cpu_data(); if (proto.double_data_size() > 0) { CHECK_EQ(count_, proto.double_data_size()); for (int i = 0; i < count_; ++i) { data_vec[i] = proto.double_data(i); } } else { CHECK_EQ(count_, proto.data_size()); for (int i = 0; i < count_; ++i) { data_vec[i] = proto.data(i); } } if (proto.double_diff_size() > 0) { CHECK_EQ(count_, proto.double_diff_size()); Dtype* diff_vec = mutable_cpu_diff(); for (int i = 0; i < count_; ++i) { diff_vec[i] = proto.double_diff(i); } } else if (proto.diff_size() > 0) { CHECK_EQ(count_, proto.diff_size()); Dtype* diff_vec = mutable_cpu_diff(); for (int i = 0; i < count_; ++i) { diff_vec[i] = proto.diff(i); } } }
|
将数据序列化(写入磁盘):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| template <> void Blob<double>::ToProto(BlobProto* proto, bool write_diff) const { proto->clear_shape(); for (int i = 0; i < shape_.size(); ++i) { proto->mutable_shape()->add_dim(shape_[i]); } proto->clear_double_data(); proto->clear_double_diff(); const double* data_vec = cpu_data(); for (int i = 0; i < count_; ++i) { proto->add_double_data(data_vec[i]); } if (write_diff) { const double* diff_vec = cpu_diff(); for (int i = 0; i < count_; ++i) { proto->add_double_diff(diff_vec[i]); } } }
|