Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是否可以在C#中使用分支预测提示?_C#_.net_Optimization_Clr - Fatal编程技术网

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

是否可以在C#中使用分支预测提示?,c#,.net,optimization,clr,C#,.net,Optimization,Clr,例如,我知道它是为gcc定义的,在Linux内核中用作: #define likely(x) __builtin_expect((x),1) #define unlikely(x) __builtin_expect((x),0) 如果在C#中不可能出现类似的情况,那么将最有可能的情况放在首位,是手动重新排序If语句的最佳选择吗?基于这种外部知识,还有其他优化方法吗 另一方面,CLR知道如何识别保护子句,并假设将采用备用分支,使得此优化不适合在保护类上使用,对吗 (请注意,我

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

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)
如果在C#中不可能出现类似的情况,那么将最有可能的情况放在首位,是手动重新排序If语句的最佳选择吗?基于这种外部知识,还有其他优化方法吗

另一方面,CLR知道如何识别保护子句,并假设将采用备用分支,使得此优化不适合在保护类上使用,对吗

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

简短回答:不

更长的回答:在大多数情况下,你真的不需要这么做。您可以通过更改语句中的逻辑来给出提示。使用性能工具更容易做到这一点,就像Visual Studio更高(也更昂贵)版本中内置的工具一样,因为您可以捕获预测失误的分支计数器。我意识到这是出于学术目的,但很高兴知道JITer非常擅长为您优化代码。例如(几乎一字不差地取自)

此代码:

public static void Main() {
    Int32[] a = new Int32[5];
    for(Int32 index = 0; index < a.Length; index++) {
        // Do something with a[index]
    }
}
publicstaticvoidmain(){
Int32[]a=新的Int32[5];
对于(Int32索引=0;索引
可能看起来效率很低,因为
a.Length
是一个属性,正如我们在C#中所知道的,属性实际上是一组一个或两个方法(
get_XXX
set_XXX
)。但是,JIT知道它是一个属性,它要么将长度存储在局部变量中,要么将方法内联,以防止开销

…一些开发人员低估了这些能力 并试图编写“聪明的代码”来帮助JIT 编译器。然而,你想出的任何聪明的尝试几乎肯定会产生影响 性能下降,使代码更难阅读,降低了可维护性

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

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

解释了.NET3.5SP1中添加的一些优化,其中包括对拉直分支以改进预测和缓存局部性的改进

综上所述,如果你想读一本关于编译器生成内容和CLR性能的好书,我推荐我上面引用的那本书,CLR via C#


编辑:我应该提到,如果这在.NET中目前是可行的,您可以在或中找到信息。没有标准支持这一点,在IlDasm或CFF Explorer中查看元数据时,没有任何迹象表明有任何特殊的元数据可以提示分支预测。

当C#编译成IL(一种字节码,最终可以编译到任何本机CPU)时,您将如何做到这一点?答案是“不,这是不可能的。”Oded指出了这种不可能的原因。我想我希望它可以在IL中完成,因为IL被编译成本机代码,在本机代码中可以使用暗示指令。或者,任何其他类似的技术,即使不是在处理器级别,也会引起人们的兴趣(尽管我不确定这是否可能)。@Oded,Heath:这并不是说它不可能。MSIL携带各种元数据,描述局部变量的类型、异常try/catch块等。如果.NET设计器为分支预测包含了一个编码,那么将元数据用于分支预测是可能的。@BenVoigt-True,但是,没有这样的编码,所以实际上,这目前是不可能的。尽管这令人失望,但有关JIT的信息令人放心。谢谢你的提示,我肯定会去看看那本书,因为我对CLR不太熟悉,但最近对“幕后”发生的事情非常感兴趣。虽然我很喜欢那本书,但我不喜欢你的引用。事实上,这是准确的,但我不喜欢“聪明代码”的语气,尤其是考虑到当有人想知道为什么没有进行给定的优化时,人们也同样鄙视。我们可以想象一个神奇的完美抖动,它总是产生尽可能最高效的代码,更容易想象一个可怕的天真抖动,它从来没有优化过任何东西,我们知道真相就在这两者之间。不知道中间点在哪里,人们只能在热点尝试这些东西,看看它们是否有效。@JonHanna-我想我在很大程度上同意你的观点。我不认为开发人员应该忽略JITer正在做什么;有点遗憾的是,我们实际上并不确切知道什么正在得到优化。我知道这并不完美。我也知道这并不可怕。不过,你说得很简洁,我们根本不知道它优化的程度。要知道(对于单一版本的框架)的唯一方法是,使用Windbg之类的工具查看它正在做什么。但这说起来容易做起来难。另一方面,如果我们在我们所知道的方面做得太过分,我们最终可能会过度优化我们面前的情况(特定的框架、机器、网络速度等),从而损害整体质量。对于实现细节(无论是通过推断还是分析得出的)依赖太多或太少都是一种不完美的平衡,无论执行此操作的人员有多么熟练或知识渊博。”(
get_Length
set_Length