在现代的奔腾处理器上,似乎不再可能给处理器分支提示。假设一个像gcc这样的带有概要引导优化的概要编译器获得了关于可能的分支行为的信息,那么它能做些什么来产生执行得更快的代码呢?
我知道的唯一选择是将不太可能的分支移动到函数的末尾。还有别的吗?
更新。
http://download.intel.com/products/processor/manual/325462.pdf2a卷2.1.1节说
“分支提示前缀(2EH,3EH)允许程序向处理器给出关于分支最可能的代码路径的提示。仅在条件分支指令(Jcc)中使用这些前缀。保留在英特尔64或IA-32指令中使用分支提示前缀和/或其他未定义的操作码;这种使用可能会导致不可预测的行为。
然而,我不知道这些是否真的有任何效果。
另一方面,第3.4.1节。的 http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf 说
“编译器生成的代码可以提高英特尔处理器中分支预测的效率。英特尔C编译器通过以下方式实现这一点:
通过配置文件引导的优化,编译器可以布置基本块来消除函数最常执行的路径的分支,或者至少提高它们的可预测性。分支预测不必是源代码级别的问题。如需更多信息,请参阅英特尔C编译器文档。"
http://cache-www.intel.com/cd/00/00/40/60/406096_406096.pdf在“PGO性能改进”中说道
“ PGO 最适合具有许多频繁执行的分支的代码,这些分支在编译时难以预测。一个例子是具有密集错误检查的代码,其中大多数时间错误条件为假。可以重新定位不经常执行的(冷)错误处理代码,因此很少错误地预测分支。最大限度地减少交错到频繁执行(热)代码中的冷代码可以改善指令缓存行为。
在我的头顶上,你有两个选择。
选项1:通知编译器提示,让编译器适当地组织代码。例如,GCC支持以下内容...
__builtin_expect((long)!!(x), 1L) /* GNU C to indicate that <x> will likely be TRUE */
__builtin_expect((long)!!(x), 0L) /* GNU C to indicate that <x> will likely be FALSE */
如果你把它们放在宏观形式,如...
#if <some condition to indicate support>
#define LIKELY(x) __builtin_expect((long)!!(x), 1L)
#define UNLIKELY(x) __builtin_expect((long)!!(x), 0L)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif
…您现在可以将它们用作…
if (LIKELY (x != 0)) {
/* DO SOMETHING */
} else {
/* DO SOMETHING ELSE */
}
这使得编译器可以根据静态分支预测算法组织分支,和/或如果处理器和编译器支持,则可以使用指示更可能执行哪个分支的指令。
选项#2:使用数学来避免分支。
if (a < b)
y = C;
else
y = D;
这可以重写为...
x = -(a < b); /* x = -1 if a < b, x = 0 if a >= b */
x &= (C - D); /* x = C - D if a < b, x = 0 if a >= b */
x += D; /* x = C if a < b, x = D if a >= b */
希望这有所帮助。
如果很明显很少进入循环,或者循环通常迭代很少,那么编译器可能会避免展开循环,因为这样做会增加处理边缘条件(奇数次迭代等)的复杂性。).在这种情况下,尤其应该避免矢量化。
编译器可能会重新安排嵌套测试,以便最经常导致捷径的测试可以用来避免对通过率为50%的测试执行测试。
可以优化寄存器分配,以避免在常见情况下出现很少使用的块强制寄存器溢出。
这些只是一些例子。我肯定还有其他我没想到的。
您想要的信息有两种可能的来源:
现在,我不知道你所说的“现代奔腾”处理器是什么意思,这是2013年,对吧?现在已经没有任何奔腾了。。。
指令集支持告诉处理器分支是否预期被条件分支指令(如 JC、JZ 等)的前缀所获取。请参阅 (1) 卷 2A 第 2.1.1 节(我拥有的版本)指令前缀。有2E和3E前缀分别用于未采取和采取。
至于这些前缀是否真的有任何影响,如果我们能得到这些信息,它将出现在《优化参考手册》上,这是您想要的微体系结构的部分(我相信它不会是奔腾)。
除了使用它们之外,优化参考手册上还有一整节关于这个主题,那就是第3.4.1节(我拥有的版本)。
在这里重现这一点是没有意义的,因为您可以免费下载手册。简要:
此外,一些编译器,例如GCC,即使CMOV是不可能的,也经常执行按位算术来选择计算的两个不同事物中的一个,从而避免分支。当向量化循环时,它尤其对SSE指令这样做。
基本上,静态条件是:
您可能想阅读整个第3.4.1节。
问题内容: 我目前正在Mac OS X上工作,现在我需要构建一个.exe文件,以便Go程序可以在Windows上运行。所以这是一个问题,如何在MacOS amd64下为Win X86构建可执行文件?还是不可能这样做? 问题答案: 如果您不使用CGo而是纯粹的Go,那么它是完全可行且标准的。 首先,您必须在开发计算机上为目标创建Go环境。假设您的Go安装位于,则可能是这样的: 然后,使用良好的GOO
问题内容: TL; DR; 我正在寻找一个可以查找特定中间操作或终端操作的地方。在哪里可以找到此类文档? 编辑 这不是如何确保java8流中的处理顺序的重复项?,因为该问题未提供完整的操作列表。 该软件包的文件说: 流是否具有遇到顺序取决于源和中间操作 为了确保在整个流操作中维持顺序,您必须研究流源,所有中间操作和终端操作的文档,以了解它们是否维持顺序(或源是否在第一个顺序中具有顺序)地点)。 一
问题内容: 是的,我知道FAQ会假装回答此问题,但实际上并非如此。相反,它指示您从源代码构建项目(并且构建说明非常复杂)。那种打败了整个观点:) 让我们省去世界上每个人的麻烦,即不必再构建另一个开源项目,以了解它是否真正解决了他们的问题。Xuggler支持哪些编解码器? 问题答案: FAQ不能回答这个问题的原因是,随着我们发布新版本,它会不断变化,并且要使文档中的列表保持最新状态会花费很长时间。但
GHC有很多可以执行的优化,但我不知道它们都是什么,也不知道它们在什么情况下执行的可能性有多大。 我的问题是:我可以期望它每次应用什么转换,或者几乎如此?如果我看一段经常执行(评估)的代码,我的第一个想法是“嗯,也许我应该优化它”,在这种情况下,我的第二个想法应该是“不要想它,GHC得到了这个”? 我在读《流融合:从列表到流再到什么都没有》这篇论文,他们使用的将列表处理改写成另一种形式的技术,GH
1、mybatis有三种基本的Executor执行器: (1)、SimpleExecutor 每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。 (2)、PauseExecutor 执行update或select,以sql做为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而且放置于Map内
本文向大家介绍MyBatis 有哪些执行器(Executor)?相关面试题,主要包含被问及MyBatis 有哪些执行器(Executor)?时的应答技巧和注意事项,需要的朋友参考一下 MyBatis 有三种基本的Executor执行器: SimpleExecutor:每执行一次 update 或 select 就开启一个 Statement 对象,用完立刻关闭 Statement 对象; Reus