lambda与内联函数的速度

Speed of lambda vs. inlining the function

本文关键字:速度 函数 lambda      更新时间:2023-10-16

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.3秒。然而,当我取消对开关的注释,并注释掉for_each_line(它是开关的复制粘贴)时,对于相同的运行,我得到了1.7秒。请注意,99%的情况下,watch_binary_twatch_tertiary_t都会发生,即每个lit_diff_watches函数调用只应执行极少数指令。

你能告诉我我做错了什么吗?GCC 4.7和当前llvm svn(2013年11月25日)的行为相同,时间差异较小。我猜函数调用不是内联的,但我不是专家。我想修复这个问题,因为这个switch(..){..}在代码的很多地方,并且使用了lambdas&CCD_ 8将显著清理代码。然而,我不能在这件事上放松太多的速度。10-20%是可以的,但几乎2倍的速度太慢了。

cbreak的工作帮助了我在#c++freenode IRC频道上的工作。他在评论中提到了"Kerrek SB"在上面写的内容。我将for_each_lit的声明更改为:

template<class Function>
void for_each_lit(
    const OccurClause& cl
    ,  Function func
);

并且两种实现方式的速度现在是相同的。显然,编译器无法进行链接时间优化以避免虚拟函数调用,因此开销巨大。

感谢大家的帮助!