Caffe源碼中math_functions文件分析

Caffe源碼中有一些重要文件配乓,這里介紹下math_functions文件。

include文件:

  1. <glog/logging.h>:GLog庫惠毁,它是google的一個開源的日志庫犹芹,其使用可以參考:http://blog.csdn.net/fengbingchun/article/details/48768039

  2. <caffe/common.hpp>鞠绰、<caffe/util/device_alternate.hpp>:這兩個文件的介紹可以參考: http://blog.csdn.net/fengbingchun/article/details/54955236 腰埂;

caffe/util/mkl_alternate.hpp文件:

這個文件里包含兩種庫,一個是Intel MKL蜈膨,一個是OpenBLAS屿笼,這里用的是OpenBLAS。如果商用Intel MKL是需要付費的丈挟,下面僅對Intel MKL進行簡單介紹刁卜。

Intel MKL(Math Kernel Library)即Intel數(shù)學(xué)核心函數(shù)庫,它是一套高度優(yōu)化和廣泛線程安全的數(shù)學(xué)例程曙咽,專為需要極致性能的科學(xué)、工程及金融等領(lǐng)域的應(yīng)用而設(shè)計挑辆。核心數(shù)學(xué)函數(shù)包括BLAS例朱、LAPACK、ScaLAPACK鱼蝉、Sparse Solver洒嗤、快速傅里葉變換、矢量數(shù)學(xué)及其它函數(shù)魁亦。它可以為當(dāng)前及下一代英特爾處理器提供性能優(yōu)化渔隶,包括更出色地與Microsoft Visual Studio、Eclipse和XCode相集成洁奈。英特爾MKL支持完全集成英特爾兼容性O(shè)penMP運行時庫间唉,以實現(xiàn)更出色的Windows/Linux跨平臺兼容性。

關(guān)于OpenBLAS的介紹可以參考: http://blog.csdn.net/fengbingchun/article/details/55509764利术;

在github/fengbingchun/Caffe_Test中<mkl_alternate.hpp>中走的是OpenBLAS分支呈野。

math_functions文件

math_functions文件內(nèi)函數(shù):封裝了一些基礎(chǔ)的數(shù)學(xué)運算函數(shù)

(1)、caffe_cpu_gemm:C=alphaAB+beta*C印叁;

(2)被冒、caffe_cpu_gemv:y=alphaAx+beta*y军掂;

(3)、caffe_axpy:Y=alpha*X+Y昨悼;

(4)蝗锥、caffe_cpu_axpby:Y=alphaX+betaY;

(5)率触、caffe_copy:從X中拷貝前N個元素到Y(jié)中玛追;

(6)、caffe_set:將X中的前N個元素置為alpha闲延;

(7)痊剖、caffe_add_scalar:給Y中的前N個元素分別加上常數(shù)alpha;

(8)垒玲、caffe_scal:X = alpha*X陆馁;

(9)、caffe_sqr/ caffe_exp/caffe_log/caffe_abs:會調(diào)用mkl_alternate.hpp中的vsSqr合愈、vsExp叮贩、vsLn、vsAbs佛析、vdSqr益老、vdExp、vdLn寸莫、vdAbs函數(shù)捺萌;

(10)、caffe_add/caffe_sub/caffe_mul/caffe_div:會調(diào)用mkl_alternate.hpp中的vsAdd膘茎、vsSub桃纯、vsMul、vsDiv披坏、vdAdd态坦、vdSub、vdMul棒拂、vdDiv函數(shù)伞梯;

(11)、caffe_powx:會調(diào)用mkl_alternate.hpp中的vsPowx和vdPowx函數(shù)帚屉;

(12)谜诫、caffe_rng_rand:返回一個unsignedint類型的隨機數(shù);

(13)涮阔、caffe_nextafter:在最大方向上猜绣,返回b可以表示的最接近的數(shù)值;

(14)敬特、caffe_rng_uniform:產(chǎn)生指定范圍內(nèi)的均勻分布隨機數(shù)掰邢;

(15)牺陶、caffe_rng_gaussian:產(chǎn)生高斯分布隨機數(shù);

(16)辣之、caffe_rng_bernoulli:產(chǎn)生伯努利分布隨機數(shù)掰伸;

(17)、caffe_cpu_dot:計算步長為1的內(nèi)積怀估;

(18)狮鸭、caffe_cpu_strided_dot:計算指定步長的內(nèi)積;

(19)多搀、caffe_cpu_hamming_distance:計算x歧蕉、y之間的海明距離;

(20)康铭、caffe_cpu_asum:計算向量x中前n個元素的絕對值之和惯退;

(21)、caffe_sign:類似于正負號函數(shù)从藤,僅返回-1或1催跪;

(22)、caffe_cpu_scale:Y=alpha*X 夷野。

注: 本文的內(nèi)容參考博客:http://blog.csdn.net/fengbingchun/article/details/56280708

math_functions.hpp文件源碼注釋

#ifndef CAFFE_UTIL_MATH_FUNCTIONS_H_
#define CAFFE_UTIL_MATH_FUNCTIONS_H_

#include <stdint.h>
#include <cmath>  // for std::fabs and std::signbit

#include "glog/logging.h"

#include "caffe/common.hpp"
#include "caffe/util/device_alternate.hpp"
#include "caffe/util/mkl_alternate.hpp"

namespace caffe {

// Caffe gemm provides a simpler interface to the gemm functions, with the
// limitation that the data has to be contiguous in memory.
// C=alpha*A*B+beta*C
// A,B,C 是輸入矩陣(一維數(shù)組格式)
// CblasRowMajor :數(shù)據(jù)是行主序的(二維數(shù)據(jù)也是用一維數(shù)組儲存的)
// TransA, TransB:是否要對A和B做轉(zhuǎn)置操作(CblasTrans CblasNoTrans)
// M: A懊蒸、C 的行數(shù)
// N: B、C 的列數(shù)
// K: A 的列數(shù)悯搔, B 的行數(shù)
// lda : A的列數(shù)(不做轉(zhuǎn)置)行數(shù)(做轉(zhuǎn)置)
// ldb: B的列數(shù)(不做轉(zhuǎn)置)行數(shù)(做轉(zhuǎn)置)
template <typename Dtype>
void caffe_cpu_gemm(const CBLAS_TRANSPOSE TransA,
    const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K,
    const Dtype alpha, const Dtype* A, const Dtype* B, const Dtype beta,
    Dtype* C);

// y=alpha*A*x+beta*y
// 其中X和Y是向量骑丸,A 是矩陣
// M:A 的行數(shù)
// N:A 的列數(shù)
// cblas_sgemv 中的 參數(shù)1 表示對X和Y的每個元素都進行操作
template <typename Dtype>
void caffe_cpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, const int N,
    const Dtype alpha, const Dtype* A, const Dtype* x, const Dtype beta,
    Dtype* y);

// Y=alpha*X+Y
// N:為X和Y中element的個數(shù)
template <typename Dtype>
void caffe_axpy(const int N, const Dtype alpha, const Dtype* X,
    Dtype* Y);

// Y=alpha*X+beta*Y
template <typename Dtype>
void caffe_cpu_axpby(const int N, const Dtype alpha, const Dtype* X,
    const Dtype beta, Dtype* Y);

// 從X中拷貝前N個元素到Y(jié)中
template <typename Dtype>
void caffe_copy(const int N, const Dtype *X, Dtype *Y);

// 將X中的前N個元素置為alpha
template <typename Dtype>
void caffe_set(const int N, const Dtype alpha, Dtype *X);

//  一般為新申請的內(nèi)存做初始化,功能是將buffer所指向內(nèi)存中的每個字節(jié)的內(nèi)容全部設(shè)置為c指定的ASCII值, count為塊的大小
inline void caffe_memset(const size_t N, const int alpha, void* X) {
  memset(X, alpha, N);  // NOLINT(caffe/alt_fn)
}

// 給X中的前N個元素分別加上常數(shù)alpha
template <typename Dtype>
void caffe_add_scalar(const int N, const Dtype alpha, Dtype *X);

// X = alpha*X
// N: X中element的個數(shù)
template <typename Dtype>
void caffe_scal(const int N, const Dtype alpha, Dtype *X);

template <typename Dtype>
void caffe_sqr(const int N, const Dtype* a, Dtype* y);

template <typename Dtype>
void caffe_add(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_sub(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_mul(const int N, const Dtype* a, const Dtype* b, Dtype* y);

// 會調(diào)用mkl_alternate.hpp中的vsAdd鳖孤、vsSub者娱、vsMul、vsDiv苏揣、vdAdd、vdSub推姻、vdMul平匈、vdDiv函數(shù)
// caffe_add、 caffe_sub藏古、 caffe_mul增炭、 caffe_div 函數(shù)
// 這四個函數(shù)分別實現(xiàn)element-wise的加減乘除(y[i] = a[i] + - * \ b[i])
template <typename Dtype>
void caffe_div(const int N, const Dtype* a, const Dtype* b, Dtype* y);

// 會調(diào)用mkl_alternate.hpp中的vsPowx和vdPowx函數(shù)
// caffe_powx、 caffe_sqr拧晕、 caffe_exp隙姿、 caffe_abs 函數(shù)
// 同樣是element-wise操作,分別是y[i] = a[i] ^ b厂捞, y[i] = a[i]^2输玷,y[i] = exp(a[i] )队丝,y[i] = |a[i]|
template <typename Dtype>
void caffe_powx(const int n, const Dtype* a, const Dtype b, Dtype* y);

template <typename Dtype>
void caffe_bound(const int n, const Dtype* a, const Dtype min,
    const Dtype max, Dtype* y);

// 返回一個unsignedint類型的隨機數(shù)
unsigned int caffe_rng_rand();

// 在最大方向上,返回b可以表示的最接近的數(shù)值
template <typename Dtype>
Dtype caffe_nextafter(const Dtype b);

// 產(chǎn)生指定范圍內(nèi)的均勻分布隨機數(shù)
template <typename Dtype>
void caffe_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r);

// 產(chǎn)生高斯分布隨機數(shù)
template <typename Dtype>
void caffe_rng_gaussian(const int n, const Dtype mu, const Dtype sigma,
                        Dtype* r);

// 產(chǎn)生伯努利分布隨機數(shù)
template <typename Dtype>
void caffe_rng_bernoulli(const int n, const Dtype p, int* r);

template <typename Dtype>
void caffe_rng_bernoulli(const int n, const Dtype p, unsigned int* r);

template <typename Dtype>
void caffe_exp(const int n, const Dtype* a, Dtype* y);

template <typename Dtype>
void caffe_log(const int n, const Dtype* a, Dtype* y);

// 會調(diào)用mkl_alternate.hpp中的vsSqr欲鹏、vsExp机久、vsLn、vsAbs赔嚎、vdSqr膘盖、vdExp、vdLn尤误、vdAbs函數(shù)
template <typename Dtype>
void caffe_abs(const int n, const Dtype* a, Dtype* y);

// 計算步長為1的內(nèi)積
template <typename Dtype>
Dtype caffe_cpu_dot(const int n, const Dtype* x, const Dtype* y);

// 計算指定步長的內(nèi)積
// 功能: 返回 vector X 和 vector Y 的內(nèi)積侠畔。
// incx, incy : 步長损晤,即每隔incx 或 incy 個element 進行操作软棺。
template <typename Dtype>
Dtype caffe_cpu_strided_dot(const int n, const Dtype* x, const int incx,
    const Dtype* y, const int incy);

// Returns the sum of the absolute values of the elements of vector x
// 計算向量x中前n個元素的絕對值之和
template <typename Dtype>
Dtype caffe_cpu_asum(const int n, const Dtype* x);

// the branchless, type-safe version from
// http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
// 類似于正負號函數(shù),僅返回-1或1
template<typename Dtype>
inline int8_t caffe_sign(Dtype val) {
  return (Dtype(0) < val) - (val < Dtype(0));
}

// The following two macros are modifications of DEFINE_VSL_UNARY_FUNC
//   in include/caffe/util/mkl_alternate.hpp authored by @Rowland Depp.
// Please refer to commit 7e8ef25c7 of the boost-eigen branch.
// Git cherry picking that commit caused a conflict hard to resolve and
//   copying that file in convenient for code reviewing.
// So they have to be pasted here temporarily.
// 一元函數(shù)沉馆,類似于mkl_alternate.hpp中的宏DEFINE_VSL_UNARY_FUNC码党,包括:
//  (1)、caffe_cpu_sign:正負號函數(shù)斥黑,輸出-1揖盘、0、1锌奴;
//  (2)兽狭、caffe_cpu_sgnbit:作用類似于std::signbit,static_cast<bool>((std::signbit)(x))鹿蜀;x為負數(shù)輸出為1箕慧,其它輸出為0;
//  (3)茴恰、caffe_cpu_fabs:取絕對值颠焦,作用類似于std::fabs。
#define DEFINE_CAFFE_CPU_UNARY_FUNC(name, operation) \
  template<typename Dtype> \
  void caffe_cpu_##name(const int n, const Dtype* x, Dtype* y) { \
    CHECK_GT(n, 0); CHECK(x); CHECK(y); \
    for (int i = 0; i < n; ++i) { \
      operation; \
    } \
  }

// output is 1 for the positives, 0 for zero, and -1 for the negatives
DEFINE_CAFFE_CPU_UNARY_FUNC(sign, y[i] = caffe_sign<Dtype>(x[i]));

// This returns a nonzero value if the input has its sign bit set.
// The name sngbit is meant to avoid conflicts with std::signbit in the macro.
// The extra parens are needed because CUDA < 6.5 defines signbit as a macro,
// and we don't want that to expand here when CUDA headers are also included.
DEFINE_CAFFE_CPU_UNARY_FUNC(sgnbit, \
    y[i] = static_cast<bool>((std::signbit)(x[i])));

DEFINE_CAFFE_CPU_UNARY_FUNC(fabs, y[i] = std::fabs(x[i]));

// Y=alpha*X
template <typename Dtype>
void caffe_cpu_scale(const int n, const Dtype alpha, const Dtype *x, Dtype* y);

#ifndef CPU_ONLY  // GPU

// Decaf gpu gemm provides an interface that is almost the same as the cpu
// gemm function - following the c convention and calling the fortran-order
// gpu code under the hood.
template <typename Dtype>
void caffe_gpu_gemm(const CBLAS_TRANSPOSE TransA,
    const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K,
    const Dtype alpha, const Dtype* A, const Dtype* B, const Dtype beta,
    Dtype* C);

template <typename Dtype>
void caffe_gpu_gemv(const CBLAS_TRANSPOSE TransA, const int M, const int N,
    const Dtype alpha, const Dtype* A, const Dtype* x, const Dtype beta,
    Dtype* y);

template <typename Dtype>
void caffe_gpu_axpy(const int N, const Dtype alpha, const Dtype* X,
    Dtype* Y);

template <typename Dtype>
void caffe_gpu_axpby(const int N, const Dtype alpha, const Dtype* X,
    const Dtype beta, Dtype* Y);

void caffe_gpu_memcpy(const size_t N, const void *X, void *Y);

template <typename Dtype>
void caffe_gpu_set(const int N, const Dtype alpha, Dtype *X);

inline void caffe_gpu_memset(const size_t N, const int alpha, void* X) {
#ifndef CPU_ONLY
  CUDA_CHECK(cudaMemset(X, alpha, N));  // NOLINT(caffe/alt_fn)
#else
  NO_GPU;
#endif
}

template <typename Dtype>
void caffe_gpu_add_scalar(const int N, const Dtype alpha, Dtype *X);

template <typename Dtype>
void caffe_gpu_scal(const int N, const Dtype alpha, Dtype *X);

template <typename Dtype>
void caffe_gpu_add(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_gpu_sub(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_gpu_mul(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_gpu_div(const int N, const Dtype* a, const Dtype* b, Dtype* y);

template <typename Dtype>
void caffe_gpu_abs(const int n, const Dtype* a, Dtype* y);

template <typename Dtype>
void caffe_gpu_exp(const int n, const Dtype* a, Dtype* y);

template <typename Dtype>
void caffe_gpu_log(const int n, const Dtype* a, Dtype* y);

template <typename Dtype>
void caffe_gpu_powx(const int n, const Dtype* a, const Dtype b, Dtype* y);

// caffe_gpu_rng_uniform with two arguments generates integers in the range
// [0, UINT_MAX].
void caffe_gpu_rng_uniform(const int n, unsigned int* r);

// caffe_gpu_rng_uniform with four arguments generates floats in the range
// (a, b] (strictly greater than a, less than or equal to b) due to the
// specification of curandGenerateUniform.  With a = 0, b = 1, just calls
// curandGenerateUniform; with other limits will shift and scale the outputs
// appropriately after calling curandGenerateUniform.
template <typename Dtype>
void caffe_gpu_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r);

template <typename Dtype>
void caffe_gpu_rng_gaussian(const int n, const Dtype mu, const Dtype sigma,
                            Dtype* r);

template <typename Dtype>
void caffe_gpu_rng_bernoulli(const int n, const Dtype p, int* r);

template <typename Dtype>
void caffe_gpu_dot(const int n, const Dtype* x, const Dtype* y, Dtype* out);

template <typename Dtype>
void caffe_gpu_asum(const int n, const Dtype* x, Dtype* y);

template<typename Dtype>
void caffe_gpu_sign(const int n, const Dtype* x, Dtype* y);

template<typename Dtype>
void caffe_gpu_sgnbit(const int n, const Dtype* x, Dtype* y);

template <typename Dtype>
void caffe_gpu_fabs(const int n, const Dtype* x, Dtype* y);

template <typename Dtype>
void caffe_gpu_scale(const int n, const Dtype alpha, const Dtype *x, Dtype* y);

#define DEFINE_AND_INSTANTIATE_GPU_UNARY_FUNC(name, operation) \
template<typename Dtype> \
__global__ void name##_kernel(const int n, const Dtype* x, Dtype* y) { \
  CUDA_KERNEL_LOOP(index, n) { \
    operation; \
  } \
} \
template <> \
void caffe_gpu_##name<float>(const int n, const float* x, float* y) { \
  /* NOLINT_NEXT_LINE(whitespace/operators) */ \
  name##_kernel<float><<<CAFFE_GET_BLOCKS(n), CAFFE_CUDA_NUM_THREADS>>>( \
      n, x, y); \
} \
template <> \
void caffe_gpu_##name<double>(const int n, const double* x, double* y) { \
  /* NOLINT_NEXT_LINE(whitespace/operators) */ \
  name##_kernel<double><<<CAFFE_GET_BLOCKS(n), CAFFE_CUDA_NUM_THREADS>>>( \
      n, x, y); \
}

#endif  // !CPU_ONLY

}  // namespace caffe

#endif  // CAFFE_UTIL_MATH_FUNCTIONS_H_

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末往枣,一起剝皮案震驚了整個濱河市伐庭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌分冈,老刑警劉巖圾另,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異雕沉,居然都是意外死亡集乔,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進店門坡椒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扰路,“玉大人尤溜,你說我怎么就攤上這事∮姿ィ” “怎么了靴跛?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵,是天一觀的道長渡嚣。 經(jīng)常有香客問我梢睛,道長,這世上最難降的妖魔是什么识椰? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任绝葡,我火速辦了婚禮,結(jié)果婚禮上腹鹉,老公的妹妹穿的比我還像新娘藏畅。我一直安慰自己,他們只是感情好功咒,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布愉阎。 她就那樣靜靜地躺著,像睡著了一般力奋。 火紅的嫁衣襯著肌膚如雪榜旦。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天景殷,我揣著相機與錄音溅呢,去河邊找鬼。 笑死猿挚,一個胖子當(dāng)著我的面吹牛咐旧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播绩蜻,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼铣墨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了办绝?” 一聲冷哼從身側(cè)響起踏兜,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎八秃,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肉盹,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡昔驱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了上忍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片骤肛。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡纳本,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腋颠,到底是詐尸還是另有隱情繁成,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布淑玫,位于F島的核電站巾腕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏絮蒿。R本人自食惡果不足惜尊搬,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望土涝。 院中可真熱鬧佛寿,春花似錦、人聲如沸但壮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蜡饵。三九已至弹渔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間验残,已是汗流浹背捞附。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留您没,地道東北人鸟召。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像氨鹏,于是被迫代替她去往敵國和親欧募。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容