caffe 源碼解讀 Part1
1. 基礎知識
- inline
C++關鍵字,在函數聲明或定義中函數返回類型前加上關鍵字inline,即可以把函數指定爲在計算機科學中,內聯函數(有時稱作在線函數或編譯時期展開函數)是一種編程語言結構,用來建議編譯器對一些特殊函數進行內聯擴展(有時稱作在線擴展);也就是說建議編譯器將指定的函數體插入並取代每一處調用該函數的地方(上下文),從而節省了每次調用函數帶來的額外時間開支。但在選擇使用內聯函數時,必須在程序佔用空間和程序執行效率之間進行權衡,因爲過多的比較複雜的函數進行內聯擴展將帶來很大的存儲資源開支。另外還需要特別注意的是對遞歸函數的內聯擴展可能引起部分編譯器的無窮編譯。。關鍵字inline必須與函數定義放在一起才能使函數成爲內聯,僅僅將inline放在函數聲明前面不起任何作用。inline是一種“用於實現的關鍵字”,而不是一種“用於聲明的關鍵字”。
內聯函數:在計算機科學中,內聯函數(有時稱作在線函數或編譯時期展開函數)是一種編程語言結構,用來建議編譯器對一些特殊函數進行內聯擴展(有時稱作在線擴展);也就是說建議編譯器將指定的函數體插入並取代每一處調用該函數的地方(上下文),從而節省了每次調用函數帶來的額外時間開支。但在選擇使用內聯函數時,必須在程序佔用空間和程序執行效率之間進行權衡,因爲過多的比較複雜的函數進行內聯擴展將帶來很大的存儲資源開支。另外還需要特別注意的是對遞歸函數的內聯擴展可能引起部分編譯器的無窮編譯。
- CHECK
//CHECK(...)相當於assert ...
2.主要變量
shared_ptr<SyncedMemory> data_;
shared_ptr<SyncedMemory> diff_;
shared_ptr<SyncedMemory> shape_data_;
vector<int> shape_;
int count_;
int capacity_;
BLob只是一個基本的數據結構,因此內部的變量相對較少,首先是data_指針,指針類型是shared_ptr,屬於boost庫的一個智能指針,這一部分主要用來申請內存存儲data,data主要是正向傳播的時候用的。同理,diff_主要用來存儲偏差,update data,shape_data和shape_都是存儲Blob的形狀,一個是老版本一個是新版本。count表示Blob中的元素個數,也就是個數* 通道數 * 高度 *寬度,capacity表示當前的元素個數,因爲Blob可能會reshape。
3. 函數
inline int LegacyShape(int index) const {
CHECK_LE(num_axes(), 4)
<< "Cannot use legacy accessors on Blobs with > 4 axes.";
CHECK_LT(index, 4);
CHECK_GE(index, -4);
if (index >= num_axes() || index < -num_axes()) {
return 1;
}
return shape(index);
}
- num(), channels(), height(), width()
inline int num() const {
return LegacyShape(0);
}
inline int channels() const {
return LegacyShape(1);
}
inline int height() const {
return LegacyShape(2);
}
inline int width() const {
return LegacyShape(3);
}
cpu_data()
mutable_cup_data()
cpu_diff()
mutable_cup_diff()
gpu_data()
mutable_gpu_data()
gpu_diff()
mutable_gpu_data()
//讀數據的時候要加cpu_data(),寫數據的時候加mutable_cpu_data()
if (dist_matrix.cpu_data()[anc * nums + neg] > dist_matrix.cpu_data()[anc * nums + pos])
correct_rank_count += Dtype(1)
dist_matrix.mutable_cpu_data()[j * nums + i] = dist_matrix.mutable_cpu_data()[i * nums + j]
/*****************************************************************
*name: caffe_scal
*function: X = alpha * X
*N: X中element的個數
*****************************************************************/
template <>
void caffe_scal<float>(const int N, const float alpha, float *X) {
cblas_sscal(N, alpha, X, 1);
}
/*****************************************************************
*這四個函數分別實現element-wise的加減乘除(y[i] = a[i] + - * \ b[i])
*****************************************************************/
template <>
void caffe_add<float>(const int n, const float* a, const float* b, float* y) {
vsAdd(n, a, b, y);
}
template <>
void caffe_sub<float>(const int n, const float* a, const float* b, float* y) {
vsSub(n, a, b, y);
}
template <>
void caffe_mul<float>(const int n, const float* a, const float* b, float* y) {
vsMul(n, a, b, y);
}
template <>
void caffe_div<float>(const int n, const float* a, const float* b, float* y) {
vsDiv(n, a, b, y);
}
/*****************************************************************
功能: 返回 vector X 和 vector Y 的內積。
incx, incy : 步長,即每隔incx 或 incy 個element 進行操作。
*****************************************************************/
template <typename Dtype>
Dtype caffe_cpu_dot(const int n, const Dtype* x, const Dtype* y) {
return caffe_cpu_strided_dot(n, x, 1, y, 1);
}
template <>
double caffe_cpu_strided_dot<double>(const int n, const double* x, const int incx, const double* y, const int incy) {
return cblas_ddot(n, x, incx, y, incy);
}
/*****************************************************************
功能:Y= alpha*X+beta*Y
*****************************************************************/
template <>
void caffe_cpu_axpby<float>(const int N, const float alpha, const float* X, const float beta, float* Y) {
cblas_saxpby(N, alpha, X, 1, beta, Y, 1);
}