美文网首页
caffe源码中的check宏方法学习

caffe源码中的check宏方法学习

作者: 小明大白 | 来源:发表于2018-08-29 16:49 被阅读150次

    在caffe的源码中存在很多的CHECK_LE等方法,由于使用pycharm无法直接跳转源码查看,因此在此记录:

    在如下softmax_loss层的Reshape方法存在CHECK_EQ方法。下面就详细说一下该方法的来源以及用处:

    void SoftmaxWithLossLayer<Dtype>::Reshape(
        const vector<Blob<Dtype>*>& bottom, const vector<Blob<Dtype>*>& top) {
      LossLayer<Dtype>::Reshape(bottom, top);
      softmax_layer_->Reshape(softmax_bottom_vec_, softmax_top_vec_);
      softmax_axis_ =
          bottom[0]->CanonicalAxisIndex(this->layer_param_.softmax_param().axis());
      outer_num_ = bottom[0]->count(0, softmax_axis_);
      inner_num_ = bottom[0]->count(softmax_axis_ + 1);
      CHECK_EQ(outer_num_ * inner_num_, bottom[1]->count())
          << "Number of labels must match number of predictions; "
          << "e.g., if softmax axis == 1 and prediction shape is (N, C, H, W), "
          << "label count (number of labels) must be N*H*W, "
          << "with integer values in {0, 1, ..., C-1}.";
      if (top.size() >= 2) {
        // softmax output
        top[1]->ReshapeLike(*bottom[0]);
      }
    }
    

    该方法来源于google glog库
    该库实现了应用级的日志记录,提供了C++ 风格的流操作和各种助手宏。有关该库的详细说明可以直接查看此篇文章

    本文主要讲述该库提供的caffe中常用的check方法:

    google glog提供了如下的CHECK方法:

    #define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==,val1, val2)    //相当于assert(val1 == val2)  release下可用,如果检测为true,则返回NULL,否则就会返回一个有明确提示信息的字符串指针,并输出该信息,然后是程序宕掉。以下同理
    #define CHECK_NE(val1, val2) CHECK_OP(_NE, !=,val1, val2)    //相当于assert(val1 != val2)
    #define CHECK_LE(val1, val2) CHECK_OP(_LE, <=,val1, val2)    //相当于assert(val1 <= val2)
    #define CHECK_LT(val1, val2) CHECK_OP(_LT, < ,val1, val2)    // 相当于assert(val1 < val2)
    #define CHECK_GE(val1, val2) CHECK_OP(_GE, >=,val1, val2)    //相当于assert(val1 >= val2)
    #define CHECK_GT(val1, val2) CHECK_OP(_GT, > ,val1, val2)    //相当于assert(val1 > val2)
    

    如果仅需要知道各个方法的意义以及使用方法,那么到此处即可。想要深一步了解该方法内部实现的,从接着往下看!!!

    所有的宏定义均为CHECK_OP方法实现,再查看CHECK_OP宏定义如下:

    // check_op 宏定义
    #define CHECK_OP(name, op, val1, val2) \
    CHECK_OP_LOG(name, op, val1, val2, google::LogMessageFatal)
    
    

    再查看CHECK_OP_LOG宏定义如下:

    typedef std::string_Check_string;
     
    // check_op_log 宏定义
    #define CHECK_OP_LOG(name, op, val1, val2,log)          \
      while(google::_Check_string* _result =               \
            google::Check##name##Impl(                      \
                google::GetReferenceableValue(val1),        \
                google::GetReferenceableValue(val2),        \
                #val1 " " #op " " #val2))                   \
       log(__FILE__, __LINE__,                              \
           google::CheckOpString(_result)).stream()
    

    接下来用CHECK_EQ(1,2)为例来说明具体的执行过程

    CHECK_EQ(1, 2) 
     
      ------>CHECK_OP(_LE, ==, 1, 2) 
     
      ------>CHECK_OP_LOG(_EQ, ==, 1, 2,google::LogMessageFatal)
     
      ------>#define CHECK_OP_LOG(_EQ, ==, 1, 2,google::LogMessageFatal)                         \
       while (std::string* _result =  \
     
             google::Check_EQImpl(    \
     
                  1,                   \
     
                  2,                   \
     
                  "1== 2"))           \
     
         log(__FILE__,__LINE__,       \
     
            google::CheckOpString(_result)).stream()
    

    其中google::Check_LEImpl也是通过宏预先实现的,这个宏就是DEFINE_CHECK_OP_IMPL(Check_LE,<=),如下:

    #define DEFINE_CHECK_OP_IMPL(name, op) \
       template<typename T1, typename T2>  \
       inlinestd::string* name##Impl(const T1& v1, const T2& v2,    \
                                const char*exprtext) {  \
        if(GOOGLE_PREDICT_TRUE(v1 op v2)) return NULL; \
         else return MakeCheckOpString(v1, v2, exprtext); \
       } \
    
    

    最后我们就会发现程序的真正执行过程如下:

    CHECK_EQ(1, 2) ------>
     
      while (std::string* _result =google::Check_EQImpl(1, 2, "1== 2")) 
     
        log(__FILE__,__LINE__,google::CheckOpString(_result)).stream()
    
    

    其中google::Check_EQImpl又调用了模板实现的Check_EQImpl,该函数根据两个参数v1、v2和操作符op决定了要么返回NULL,要么返回一个string*,如果返回NULL,则不再执行下面的输出,否则则输出日志信息。

    至此,就完成了CHECK_EQ(1,2)的扩展,如果检测为true,则返回NULL,否则就会返回一个有明确提示信息的字符串指针,并输出该信息,然后是程序宕掉。

    其他集合操作过程与EQ类似,如果只是要用,直接从字面意思理解即可不需要直接查看源码。

    参考:

    [1]https://www.cnblogs.com/zhoug2020/p/5884598.html

    相关文章

      网友评论

          本文标题:caffe源码中的check宏方法学习

          本文链接:https://www.haomeiwen.com/subject/hevwkftx.html