blob數據結構是caffe中基本的數據存儲單元,它主要存儲的數據是網絡中的中間數據變量,比如各層的輸入和輸出;代價函數關於網絡各層參數的梯度。
blob中除了存儲數據外,還有一些標記數據的參數,以下就是一些blob中的數據成員:
protected: shared_ptr<SyncedMemory> data_; shared_ptr<SyncedMemory> diff_; shared_ptr<SyncedMemory> shape_data_; vector<int> shape_; int count_; int capacity_
data_:表示網絡各層的輸入和輸出;
diff_:表示代價函數相對於各層參數的梯度;
shape_:是一個可變數組,shape_中主要存儲4個變量:num表示一個batch中的樣本數量,從這我們可以看出Blob的存儲是以batch為基本單位的;channels表示對應層的通道,比如卷積層有20個卷積核,channels的值就是20;height和width就表示單個數據的尺寸,可能是一副圖像的尺寸,也可能表示卷積核的尺寸,在每一層所代表的含義也不相同。
count_:表示這個Blob里已經存儲的元素的個數;
capacity_:表示這個Blob的容量;
Blob同時保存了data_和diff_,其類型為SyncedMemory的指針,注意是指針。
Blob中除了數據成員之外,也有很多用於操作數據的函數成員,下面就說幾個比較重要的:
void Blob<Dtype>::Reshape():這個函數是在原來分配的內存不夠的情況下重新分配內存。
const Dtype* Blob<Dtype>::cpu_data():這個是獲取Blob結構體中的data_數據的指針,同時限制不能對返回的指針指向的內容進行更改。
const Dtype* Blob<Dtype>::cpu_diff():這個是獲取Blob結構體中的diff_數據的指針,同時限制不能對返回的指針指向的內容進行更改。
Dtype* Blob<Dtype>::mutable_cpu_data():獲取Blob結構體中的data_數據的指針,同時可以對指針指向的內容更改。
Dtype* Blob<Dtype>::mutable_cpu_diff():獲取Blob結構體中的diff_數據的指針,同時可以對指針指向的內容更改。
void Blob<Dtype>::ShareData(const Blob& other):讓其他Blob的data_數據和當前Blob共享。
void Blob<Dtype>::ShareDiff(const Blob& other):讓其他Blob的diff_和當前的Blob共享。
在blob.hpp中還有這樣幾個定義:

按照注釋的意思,這幾個函數和shape()是一樣的作用。shape本身是一個vector,這個vector的size為4,第一個位置存儲圖片的個數,第二個存儲channel的個數,以此類推。
邏輯上看,blob是一個四維數組。但實際上,因為數組的存儲是在內存中開辟一塊連續的、大小相同的的空間,所以blob的存儲應該是一個一維的存儲結構。只不過是利用四個參數來進行尋址(shape_里的四個參數)。並且blob是行優先的存儲方式。
所以對於一個(n, k, h, w)的blob,他的維度就是n*k*h*w,在(n, k, h, w)位置的值物理位置為((n * K + k) * H + h) * W + w。
以Blob中二維矩陣為例(如全連接網絡shape (N, D)),如圖所示。同樣的存儲方式可以推廣到多維。

動態多維數組:Blob 類可以動態改變數組的尺寸,當拓展數組導致原有內存空間不足以存放下數據時 (count > capacity),就會重新分配內存。Blob 提供了一組 Reshape 函數來完成這個功能。
void Reshape(const int num, const int channels, const int height, const int width); // Deprecated void Reshape(const vector<int>& shape); void Reshape(const BlobShape& shape); void ReshapeLike(const Blob& other);
Blob 類在初始化時並沒有分配內存,也是通過調用 Reshape 來分配內存的。
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_ 未初始化或者內存太小 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); 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))); } }
http://blog.csdn.net/qq_14975217/article/details/51524042
http://blog.csdn.net/mounty_fsc/article/details/51085654
http://blog.csdn.net/buyi_shizi/article/details/51506853
http://blog.csdn.net/jyl1999xxxx/article/details/53981813
