【问题标题】:Speed of lambda vs. inlining the functionlambda 的速度与内联函数
【发布时间】:2013-11-25 12:38:29
【问题描述】:

我在使用 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_twatch_tertiary_t 会发生,即每个 lit_diff_watches 函数调用只应执行很少的指令。

你能告诉我我做错了什么吗? GCC 4.7 和当前的 llvm-svn(2013 年 11 月 25 日)的行为相同,时间差异很小。我猜函数调用不是内联的,但我不是专家。我想解决这个问题,因为这个switch(..){..} 在代码中的很多地方,使用 lambdas & for_each_lit 会显着清理代码。但是,我不能为此失去这么多的速度。 10-20% 就可以了,但几乎 2 倍的减速就太多了。

【问题讨论】:

  • 确保使用最高优化级别。除此之外,如果没有完整的示例,我们可能无法帮助您。
  • 不要转换为std::function。请改用模板。

标签: c++ c++11 lambda functor inlining


【解决方案1】:

cbreak-work 在#c++ freenode IRC 频道上帮助了我。他建议了上面在 cmets 中“Kerrek SB”所写的内容。我将for_each_lit的声明改为:

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

现在两种实现的速度相同。显然,编译器无法进行链接时优化以排除虚函数调用,因此开销很大。

感谢大家的帮助!

【讨论】:

    猜你喜欢
    • 2019-11-23
    • 2019-11-29
    • 2021-04-05
    • 1970-01-01
    • 2014-02-13
    • 2020-09-05
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多