caffe源碼中的check宏方法學(xué)習(xí)

在caffe的源碼中存在很多的CHECK_LE等方法,由于使用pycharm無(wú)法直接跳轉(zhuǎn)源碼查看,因此在此記錄:

在如下softmax_loss層的Reshape方法存在CHECK_EQ方法。下面就詳細(xì)說(shuō)一下該方法的來(lái)源以及用處:

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]);
  }
}

該方法來(lái)源于google glog庫(kù)
該庫(kù)實(shí)現(xiàn)了應(yīng)用級(jí)的日志記錄,提供了C++ 風(fēng)格的流操作和各種助手宏。有關(guān)該庫(kù)的詳細(xì)說(shuō)明可以直接查看此篇文章。

本文主要講述該庫(kù)提供的caffe中常用的check方法:

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

#define CHECK_EQ(val1, val2) CHECK_OP(_EQ, ==,val1, val2)    //相當(dāng)于assert(val1 == val2)  release下可用,如果檢測(cè)為true,則返回NULL,否則就會(huì)返回一個(gè)有明確提示信息的字符串指針,并輸出該信息,然后是程序宕掉。以下同理
#define CHECK_NE(val1, val2) CHECK_OP(_NE, !=,val1, val2)    //相當(dāng)于assert(val1 != val2)
#define CHECK_LE(val1, val2) CHECK_OP(_LE, <=,val1, val2)    //相當(dāng)于assert(val1 <= val2)
#define CHECK_LT(val1, val2) CHECK_OP(_LT, < ,val1, val2)    // 相當(dāng)于assert(val1 < val2)
#define CHECK_GE(val1, val2) CHECK_OP(_GE, >=,val1, val2)    //相當(dāng)于assert(val1 >= val2)
#define CHECK_GT(val1, val2) CHECK_OP(_GT, > ,val1, val2)    //相當(dāng)于assert(val1 > val2)

如果僅需要知道各個(gè)方法的意義以及使用方法,那么到此處即可。想要深一步了解該方法內(nèi)部實(shí)現(xiàn)的,從接著往下看?。?!

所有的宏定義均為CHECK_OP方法實(shí)現(xiàn),再查看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()

接下來(lái)用CHECK_EQ(1,2)為例來(lái)說(shuō)明具體的執(zhí)行過(guò)程

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()

其中g(shù)oogle::Check_LEImpl也是通過(guò)宏預(yù)先實(shí)現(xiàn)的,這個(gè)宏就是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); \
   } \

最后我們就會(huì)發(fā)現(xiàn)程序的真正執(zhí)行過(guò)程如下:

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

其中g(shù)oogle::Check_EQImpl又調(diào)用了模板實(shí)現(xiàn)的Check_EQImpl,該函數(shù)根據(jù)兩個(gè)參數(shù)v1、v2和操作符op決定了要么返回NULL,要么返回一個(gè)string*,如果返回NULL,則不再執(zhí)行下面的輸出,否則則輸出日志信息。

至此,就完成了CHECK_EQ(1,2)的擴(kuò)展,如果檢測(cè)為true,則返回NULL,否則就會(huì)返回一個(gè)有明確提示信息的字符串指針,并輸出該信息,然后是程序宕掉。

其他集合操作過(guò)程與EQ類似,如果只是要用,直接從字面意思理解即可不需要直接查看源碼。

參考:

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容