是否可以在C#中使用分支预测提示?

时间:2012-01-15 22:33:22

标签: c# .net optimization clr

例如,我知道它是为gcc定义的,并在Linux内核中用作:

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

如果在C#中没有这样的可能,那么手动重新排序if语句是最好的选择,最可能的情况是第一种吗?是否有其他方法可以根据这种类型的外部知识进行优化?

在相关的说明中,CLR知道如何识别保护条款并假设将采用备用分支,使得这种优化不适合用于保护条款,是否正确?

(请注意,我意识到这可能是微观优化;我只对学术目的感兴趣。)

1 个答案:

答案 0 :(得分:25)

简短回答:不。

更长的答案:在大多数情况下,你并不需要 。您可以通过更改语句中的逻辑来 提供提示。使用性能工具更容易,例如内置于Visual Studio的更高(和更昂贵)版本的工具,因为您可以捕获错误预测的分支计数器。我意识到这是出于学术目的,但很高兴知道JITer非常非常擅长为您优化代码。作为一个例子(几乎逐字地从CLR via C#

此代码:

public static void Main() {
    Int32[] a = new Int32[5];
    for(Int32 index = 0; index < a.Length; index++) {
        // Do something with a[index]
    }
}

似乎效率低下,因为a.Length是一个属性,正如我们在C#中所知,属性实际上是一组或两个方法(get_XXXset_XXX)。但是,JIT知道它是一个属性,并将长度存储在局部变量中,或者内联方法,以防止开销。

  

......一些开发人员低估了这些能力   JIT编译器并尝试编写“聪明的代码”以试图帮助JIT   编译器。但是,任何你提出的聪明尝试几乎肯定会产生影响   性能负面,使您的代码更难阅读,降低其可维护性。

除此之外,它实际上更进一步,并且边界检查一次外部而不是在循环内部,这会降低性能。

我意识到它与你的问题没什么关系,但我想我想要做的是这样的微优化在C#中并没有真正帮助你,因为JIT通常会这样做更好,因为它是专门为此设计的。 (有趣的是,x86 JIT编译器比x64编译器执行更积极的优化)

This article解释了.NET 3.5 SP1中添加的一些优化,其中包括改进分支分支以改进预测和缓存局部性。

所有这一切,如果你想阅读一本关于编译器生成和CLR性能的好书,我推荐我从上面引用的书,CLR通过C#。

编辑:我应该提一下,如果目前在.NET中可以使用,您可以在EMCA-335 standardworking draft中找到相关信息。没有标准可以支持这一点,并且在像IlDasm或CFF Explorer这样的内容中查看元数据时,没有任何特殊元数据的迹象可以暗示分支预测。