【问题标题】:Use of __builtin_expected for bounds check使用 __builtin_expected 进行边界检查
【发布时间】:2015-09-02 10:54:20
【问题描述】:

我有这个函数,给定Gray code,返回下一个格雷码。你可以找到关于它如何工作的更完整的解释here。问题是我想让这个递增函数模块化,以便递增对应于UINT_MAX 的格雷码返回对应于0 的格雷码(分别是最高有效位和0)。由于这不是默认行为,因此我为这种特殊情况添加了检查。这是完整的算法:

unsigned next_gray(unsigned gray)
{
    static const unsigned msb
        = 1u << (CHAR_BITS - sizeof(unsigned) - 1u);

    // gray is odd
    if (__builtin_parity(gray))
    {
        if (__builtin_expect(gray == msb, false))
        {
            return 0u;
        }
        else
        {
            unsigned y = gray & -gray;
            return gray ^ (y << 1u);
        }
    }

    // gray is even
    return gray ^ 1;
}

所以,实际的问题实际上是关于分支预测的。我经常读到__builtin_expect 仅在确实可能选择或不太可能选择分支时使用,常见示例是在没有错误的情况下加速程序。

考虑到我没有处理错误情况,我不确定使用__builtin_expect 进行这样的边界检查是否是个好主意。这是使用__builtin_expect 的好地方吗?或者增加最大值是一种足够常见的操作来欺骗分支预测?

注意:与往常一样,cmets 和答案会突出显示我的问题中不清楚的内容 :)

我将提供更多背景信息:此函数旨在成为库的一部分,为成为库而开发,并且不被任何已知的实际项目使用。因此,添加__builtin_expect 意味着我希望人们主要增加其他值而不是最大值;手头没有任何实际项目,我想知道这是否是一个安全的假设。

【问题讨论】:

标签: c branch-prediction gray-code


【解决方案1】:

取自the GCC online docs

您可以使用__builtin_expect 为编译器提供分支预测信息。 一般来说,您应该更愿意为此使用实际的配置文件反馈 (-fprofile-arcs),因为众所周知,程序员不善于预测他们的程序的实际执行情况。 但是,有些应用程序很难获得这些数据收集。

这是使用 __builtin_expect 的好地方,还是增加最大值是一种足以欺骗分支预测的常见操作?

这一切都取决于您的应用程序。如果gray 的值是均匀分布的,那么它将是(UINT_MAX+1) 中的1,但你能肯定地说吗?这就是docs 推荐使用-fprofile-arcs 的原因。

gcov wikipedia article 实际上包含一个很好的简单示例,说明如何使用 -fprofile-arcsgcov 获取信息以做出明智的决定。

更新:

如果您无法分析,那么所有情况都相同,极端情况 gray == msb 的可能性很小,因此您可能使用 __builtin_expect 是安全的。但是,如果您因为不知道将如何使用您的库而无法配置文件,这听起来更像是pessimization,而不是优化。如果我使用您的库并始终传递gray 使其等于msb,那么您的库对我来说不会那么快。没有考虑到特定应用程序编写的通用库通常会尝试对一般情况有利,或者不对输入做出任何假设。这就是为什么您会看到 malloc 的不同实现,例如 jemalloctcmalloc。两者都针对非常特定的用例进行了优化,如果您以与优化的方式不同的方式使用它,它的效果也不会那么好。你也可能对this blog article 感兴趣。

【讨论】:

  • 我知道这个建议,但我正在开发一个库。而且由于我没有利用它的项目,因此运行分析数据将毫无意义。我的问题是,我认为使用该库的项目(截至今天没有)在大多数情况下(如 most 时间)不会调用特殊,但不能确定。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
  • 2015-03-08
  • 1970-01-01
  • 2015-07-06
  • 2011-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多