我有lambda函数的速度问题。这是代码:
Lit Simplifier::lit_diff_watches(const OccurClause& a, const OccurClause& b)
{
set_seen_for_lits(b, 1);
size_t num = 0;
Lit toret = lit_Undef;
const auto check_seen = [&] (const Lit lit) {
if (seen[lit.toInt()] == 0) {
toret = lit;
num++;
}
};
for_each_lit(a, check_seen);
/*switch(a.ws.getType()) {
case CMSat::watch_binary_t:
check_seen(a.lit);
check_seen(a.ws.lit2());
break;
case CMSat::watch_tertiary_t:
check_seen(a.lit);
check_seen(a.ws.lit2());
check_seen(a.ws.lit3());
break;
case CMSat::watch_clause_t: {
const Clause& clause = *solver->clAllocator->getPointer(a.ws.getOffset());
for(const Lit lit: clause) {
check_seen(lit);
}
break;
}
}*/
set_seen_for_lits(b, 0);
if (num == 1)
return toret;
else
return lit_Undef;
}
for_each_lit
函数的签名是:
void for_each_lit(
const OccurClause& cl
, std::function<void (const Lit lit)> func
);
函数lit_diff_watches
运行数百万次,一个例子需要3.3s。但是,当我取消注释开关,并注释掉for_each_line
(这是交换机的复制粘贴)时,我获得了相同的运行时间为1.7秒。请注意,99%的时间,watch_binary_t
或watch_tertiary_t
都会发生,即每个lit_diff_watches
函数调用只应执行非常少的指令。
switch(..){..}
在代码中的很多地方都有,并且使用了lambdas&amp; for_each_lit
会显着清理代码。但是,我不能放松这么快。 10-20%会好的,但减速几乎是2倍太多了。
答案 0 :(得分:1)
cbreak-work在#c ++ freenode IRC频道上帮助了我。他在评论中提出了“Kerrek SB”上面写的内容。我将for_each_lit
的声明更改为:
template<class Function>
void for_each_lit(
const OccurClause& cl
, Function func
);
现在两种实现的速度相同。显然,编译器无法进行链接时优化以避免虚拟函数调用,因此开销很大。
感谢所有人的帮助!