caffe源码 之 数值计算类
2016-11-10 11:31
513 查看
本文主要解析caffe的源码文件/src/caffe/util/Math_functions.cpp,本文件主要实现caffe框架中的数值计算。
综述:::::
Math_functions.cpp实现了网络训练所需的一些矩阵运算,数值运算,以及一些权重的参数初始化的分布函数实现。大部分函数分为float型与double型两种实现。
综述:::::
Math_functions.cpp实现了网络训练所需的一些矩阵运算,数值运算,以及一些权重的参数初始化的分布函数实现。大部分函数分为float型与double型两种实现。
#include <boost/math/special_functions/next.hpp> #include <boost/random.hpp> #include <limits> #include "caffe/common.hpp" #include "caffe/util/math_functions.hpp" #include "caffe/util/rng.hpp" namespace caffe { /* 功能: C=alpha*A*B+beta*C A,B,C 是输入矩阵(一维数组格式) CblasRowMajor :数据是行主序的(二维数据也是用一维数组储存的) TransA, TransB:是否要对A和B做转置操作(CblasTrans CblasNoTrans) M: A、C 的行数 N: B、C 的列数 K: A 的列数, B 的行数 lda : A的列数(不做转置)行数(做转置) ldb: B的列数(不做转置)行数(做转置) */ template<> void caffe_cpu_gemm<float>(const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const float alpha, const float* A, const float* B, const float beta, float* C) { int lda = (TransA == CblasNoTrans) ? K : M; int ldb = (TransB == CblasNoTrans) ? N : K; cblas_sgemm(CblasRowMajor, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, N); } template<> void caffe_cpu_gemm<double>(const CBLAS_TRANSPOSE TransA, const CBLAS_TRANSPOSE TransB, const int M, const int N, const int K, const double alpha, const double* A, const double* B, const double beta, double* C) { int lda = (TransA == CblasNoTrans) ? K : M; int ldb = (TransB == CblasNoTrans) ? N : K; cblas_dgemm(CblasRowMajor, TransA, TransB, M, N, K, alpha, A, lda, B, ldb, beta, C, N); } /* 功能: y=alpha*A*x+beta*y 其中X和Y是向量,A 是矩阵 M:A 的行数 N:A 的列数 cblas_sgemv 中的 参数1 表示对X和Y的每个元素都进行操作 */ template <> void caffe_cpu_gemv<float>(const CBLAS_TRANSPOSE TransA, const int M, const int N, const float alpha, const float* A, const float* x, const float beta, float* y) { cblas_sgemv(CblasRowMajor, TransA, M, N, alpha, A, N, x, 1, beta, y, 1); } template <> void caffe_cpu_gemv<double>(const CBLAS_TRANSPOSE TransA, const int M, const int N, const double alpha, const double* A, const double* x, const double beta, double* y) { cblas_dgemv(CblasRowMajor, TransA, M, N, alpha, A, N, x, 1, beta, y, 1); } /* 功能: Y=alpha*X+Y N:为X和Y中element的个数 */ template <> void caffe_axpy<float>(const int N, const float alpha, const float* X, float* Y) { cblas_saxpy(N, alpha, X, 1, Y, 1); } template <> void caffe_axpy<double>(const int N, const double alpha, const double* X, double* Y) { cblas_daxpy(N, alpha, X, 1, Y, 1); } /* 功能:用常数 alpha 对 Y 进行初始化 */ template <typename Dtype> void caffe_set(const int N, const Dtype alpha, Dtype* Y) { if (alpha == 0) { memset(Y, 0, sizeof(Dtype) * N); // NOLINT(caffe/alt_fn) return; } for (int i = 0; i < N; ++i) { Y[i] = alpha; } } template void caffe_set<int>(const int N, const int alpha, int* Y); template void caffe_set<float>(const int N, const float alpha, float* Y); template void caffe_set<double>(const int N, const double alpha, double* Y); /* 功能:给Y的每个element加上常数alpha */ template <> void caffe_add_scalar(const int N, const float alpha, float* Y) { for (int i = 0; i < N; ++i) { Y[i] += alpha; } } template <> void caffe_add_scalar(const int N, const double alpha, double* Y) { for (int i = 0; i < N; ++i) { Y[i] += alpha; } } /* 将X内存的N个数据拷贝到Y */ template <typename Dtype> void caffe_copy(const int N, const Dtype* X, Dtype* Y) { if (X != Y) { if (Caffe::mode() == Caffe::GPU) { #ifndef CPU_ONLY // NOLINT_NEXT_LINE(caffe/alt_fn) CUDA_CHECK(cudaMemcpy(Y, X, sizeof(Dtype) * N, cudaMemcpyDefault)); /*gpu拷贝*/ #else NO_GPU; #endif } else { memcpy(Y, X, sizeof(Dtype) * N); // NOLINT(caffe/alt_fn) } } } template void caffe_copy<int>(const int N, const int* X, int* Y); template void caffe_copy<unsigned int>(const int N, const unsigned int* X, unsigned int* Y); template void caffe_copy<float>(const int N, const float* X, float* Y); template void caffe_copy<double>(const int N, const double* X, double* Y); /* 功能: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); } template <> void caffe_scal<double>(const int N, const double alpha, double *X) { cblas_dscal(N, alpha, X, 1); } /* 功能: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); } template <> void caffe_cpu_axpby<double>(const int N, const double alpha, const double* X, const double beta, double* Y) { cblas_daxpby(N, alpha, X, 1, beta, Y, 1); } /* 按元素相加, n是a,b,y向量元素个数 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_add<double>(const int n, const double* a, const double* b, double* y) { vdAdd(n, a, b, y); } /* 按元素相减, n是a,b,y向量元素个数 y[i] = a[i] - b[i] */ template <> void caffe_sub<float>(const int n, const float* a, const float* b, float* y) { vsSub(n, a, b, y); } template <> void caffe_sub<double>(const int n, const double* a, const double* b, double* y) { vdSub(n, a, b, y); } /* 按元素相乘, n是a,b,y向量元素个数 y[i] = a[i] * b[i] */ template <> void caffe_mul<float>(const int n, const float* a, const float* b, float* y) { vsMul(n, a, b, y); } template <> void caffe_mul<double>(const int n, const double* a, const double* b, double* y) { vdMul(n, a, b, y); } /* 按元素相除, n是a,b,y向量元素个数 y[i] = a[i] * b[i] */ template <> void caffe_div<float>(const int n, const float* a, const float* b, float* y) { vsDiv(n, a, b, y); } template <> void caffe_div<double>(const int n, const double* a, const double* b, double* y) { vdDiv(n, a, b, y); } /* 按元素求幂,n是a元素个数 y[i] = a[i]^b */ template <> void caffe_powx<float>(const int n, const float* a, const float b, float* y) { vsPowx(n, a, b, y); } template <> void caffe_powx<double>(const int n, const double* a, const double b, double* y) { vdPowx(n, a, b, y); } /* 按元素求平方,n是a元素个数 y[i] = a[i]^2 */ template <> void caffe_sqr<float>(const int n, const float* a, float* y) { vsSqr(n, a, y); } template <> void caffe_sqr<double>(const int n, const double* a, double* y) { vdSqr(n, a, y); } /* 按元素求exp函数,n是a元素个数 y[i] = exp(a[i]) */ template <> void caffe_exp<float>(const int n, const float* a, float* y) { vsExp(n, a, y); } template <> void caffe_exp<double>(const int n, const double* a, double* y) { vdExp(n, a, y); } /* 按元素求log值,n是a元素个数 y[i] = log(a[i]) */ template <> void caffe_log<float>(const int n, const float* a, float* y) { vsLn(n, a, y); } template <> void caffe_log<double>(const int n, const double* a, double* y) { vdLn(n, a, y); } /* 按元素求取绝对值,n是a元素个数 y[i] = abs(a[i]) */ template <> void caffe_abs<float>(const int n, const float* a, float* y) { vsAbs(n, a, y); } template <> void caffe_abs<double>(const int n, const double* a, double* y) { vdAbs(n, a, y); } /*返回一个随机数*/ unsigned int caffe_rng_rand() { return (*caffe_rng())(); } /*返回比b大的最接近于b的能被表示的数,见nextafter函数描述http://en.cppreference.com/w/cpp/numeric/math/nextafter*/ template <typename Dtype> Dtype caffe_nextafter(const Dtype b) { return boost::math::nextafter<Dtype>( b, std::numeric_limits<Dtype>::max()); } template float caffe_nextafter(const float b); template double caffe_nextafter(const double b); /*用随机数生成a到b的均匀分布赋值给r,n是需要生成的数的个数*/ template <typename Dtype> void caffe_rng_uniform(const int n, const Dtype a, const Dtype b, Dtype* r) { CHECK_GE(n, 0); CHECK(r); CHECK_LE(a, b); boost::uniform_real<Dtype> random_distribution(a, caffe_nextafter<Dtype>(b)); boost::variate_generator<caffe::rng_t*, boost::uniform_real<Dtype> > variate_generator(caffe_rng(), random_distribution); for (int i = 0; i < n; ++i) { r[i] = variate_generator(); } } template void caffe_rng_uniform<float>(const int n, const float a, const float b, float* r); template void caffe_rng_uniform<double>(const int n, const double a, const double b, double* r); /*生成一个高斯分布的数据赋值给r,a是均值,r是方差*/ template <typename Dtype> void caffe_rng_gaussian(const int n, const Dtype a, const Dtype sigma, Dtype* r) { CHECK_GE(n, 0); CHECK(r); CHECK_GT(sigma, 0); boost::normal_distribution<Dtype> random_distribution(a, sigma); boost::variate_generator<caffe::rng_t*, boost::normal_distribution<Dtype> > variate_generator(caffe_rng(), random_distribution); for (int i = 0; i < n; ++i) { r[i] = variate_generator(); } } template void caffe_rng_gaussian<float>(const int n, const float mu, const float sigma, float* r); template void caffe_rng_gaussian<double>(const int n, const double mu, const double sigma, double* r); /*生成一个伯努利分布的数据赋值给r,p是概率*/ template <typename Dtype> void caffe_rng_bernoulli(const int n, const Dtype p, int* r) { CHECK_GE(n, 0); CHECK(r); CHECK_GE(p, 0); CHECK_LE(p, 1); boost::bernoulli_distribution<Dtype> random_distribution(p); boost::variate_generator<caffe::rng_t*, boost::bernoulli_distribution<Dtype> > variate_generator(caffe_rng(), random_distribution); for (int i = 0; i < n; ++i) { r[i] = variate_generator(); } } template void caffe_rng_bernoulli<double>(const int n, const double p, int* r); template void caffe_rng_bernoulli<float>(const int n, const float p, int* r); /*转化成整型*/ template <typename Dtype> void caffe_rng_bernoulli(const int n, const Dtype p, unsigned int* r) { CHECK_GE(n, 0); CHECK(r); CHECK_GE(p, 0); CHECK_LE(p, 1); boost::bernoulli_distribution<Dtype> random_distribution(p); boost::variate_generator<caffe::rng_t*, boost::bernoulli_distribution<Dtype> > variate_generator(caffe_rng(), random_distribution); for (int i = 0; i < n; ++i) { r[i] = static_cast<unsigned int>(variate_generator()); } } template void caffe_rng_bernoulli<double>(const int n, const double p, unsigned int* r); template void caffe_rng_bernoulli<float>(const int n, const float p, unsigned int* r); /*返回向量x与向量y的内积,incx, incy : 步长,即每隔incx 或 incy 个element 进行操作。*/ template <> float caffe_cpu_strided_dot<float>(const int n, const float* x, const int incx, const float* y, const int incy) { return cblas_sdot(n, x, incx, y, incy); } 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); } /*步长为1的内积*/ 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 float caffe_cpu_dot<float>(const int n, const float* x, const float* y); template double caffe_cpu_dot<double>(const int n, const double* x, const double* y); /*计算向量x的所有元素的绝对值之和。*/ template <> float caffe_cpu_asum<float>(const int n, const float* x) { return cblas_sasum(n, x, 1); } template <> double caffe_cpu_asum<double>(const int n, const double* x) { return cblas_dasum(n, x, 1); } /*y = alpha*x*/ template <> void caffe_cpu_scale<float>(const int n, const float alpha, const float *x, float* y) { cblas_scopy(n, x, 1, y, 1); cblas_sscal(n, alpha, y, 1); } template <> void caffe_cpu_scale<double>(const int n, const double alpha, const double *x, double* y) { cblas_dcopy(n, x, 1, y, 1); cblas_dscal(n, alpha, y, 1); } } // namespace caffe
相关文章推荐
- 大众点评Cat源码阅读(九)——报表部分内存数据结构及数值计算公式
- 修改MTCNN中caffe源码,时计算loss时以对应标签是否为“-1”判别
- caffe源码学习:softmaxWithLoss前向计算
- 修改MTCNN中caffe源码,时计算loss时以对应标签是否为“-1”判别
- ASP.NET数据格中计算数值总和DataGrid
- ASP.NET数据格中计算数值总和
- 数值计算程序大放送-矩阵运算
- 数值计算程序大放送-线性代数方程组
- J2ME(MIDP1.0)计算float,int,long数值的平方根
- C#数值计算之模拟退火法简介(一)
- Oracle中数值的计算
- 数值分析源码和库
- 一个只能输入数字的C#控件源码,并且可以限定数值类型,基本满足财务开发
- 数值计算问题--素数
- Oraclec常用函数 (数值转化及计算)
- java中如何将String类型的日期转换成数值及计算
- 利用commons-math-1.1进行java数值计算
- 希望和大家交流Dotnet数值计算
- ASP.NET数据格中计算数值总和
- Oracle函数参考(用于计算某个数值所表示的时间)