caffe源码中的check宏方法学习

在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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容