for (;;) {
if (normal) { // How to tell compiler to always branch predict true value?
doSomethingNormal();
} else {
exceptionalCase();
}
}
从C++20开始,可能和不太可能的属性应该是标准化的,并且在G++9中已经得到支持。因此,正如这里所讨论的,您可以编写
if (a > b) {
/* code you expect to run often */
[[likely]] /* last statement here */
}
例如,在下面的代码中,由于if
块中的[[不太可能]]
,else块得到了内联
int oftendone( int a, int b );
int rarelydone( int a, int b );
int finaltrafo( int );
int divides( int number, int prime ) {
int almostreturnvalue;
if ( ( number % prime ) == 0 ) {
auto k = rarelydone( number, prime );
auto l = rarelydone( number, k );
[[unlikely]] almostreturnvalue = rarelydone( k, l );
} else {
auto a = oftendone( number, prime );
almostreturnvalue = oftendone( a, a );
}
return finaltrafo( almostreturnvalue );
}
比较属性的存在/不存在的godbolt链接
从我的大学课程中,我听说,按照惯例,最好将更可能的条件放在中,而不是条件中,这可能有助于静态分支预测器。例如: 可以改写为: 我找到了一篇博客文章分支模式,使用GCC,它更详细地解释了这种现象: 为 if 语句生成转发分支。使它们不太可能被采用的理由是,处理器可以利用这样一个事实,即分支指令之后的指令可能已经放置在指令单元内的指令缓冲区中。 旁边写着(强调我的): 在编写if-else语句时,始终
这个问题主要是在阅读了Aater Suleman关于从软件方面改进分支预测的文章后的后续问题。作者提供了一种“展开”条件语句的方法,例如在2位饱和计数器方案的情况下增加预测分支的概率。这里有一个努力: 我举个例子解释一下。让我们假设X是0到99之间的随机变量。我想运行下面的代码: 如果(X 但是,如果我将代码编写为: 如果(X 分支预测器更有可能更准确地预测这两个分支,这可能会导致更好的性能,因为
我目前正在编写一个Intel 8042驱动程序,并编写了两个循环来等待一些缓冲区准备就绪: 如您所见,我在循环中插入了指令。我最近才知道它,很自然地想尝试一下。 由于 的内容是不可预测的,因为它是 I/O 读取,因此分支预测器将使用循环指令填充管道:经过一些迭代后,它会注意到总是采用一个分支,类似于这里的情况。 如果分支预测器真的在其预测中包含I/O指令,那么上述是正确的,我不确定。 那么分支预测
我在HashMap中存储的对象作为键覆盖equals(),但不是hashCode();当我在映射中放置一个对象时,equals()方法没有被调用。如果我还重写hashCode(),则会调用equals()方法。为什么? 为什么我不能使用自定义的equals方法来阻止向映射中添加对象,而不管我是否重写hashCode()? 谢谢 如果注释了hashCode(),则大小为2,否则大小为1。 我在想,如
在阅读了这篇漂亮的文章(预编译头的维护和输入)之后,我对这些在现实生活中如何实际工作产生了一些疑问。更具体地说,在以下场景中,我如何知道需要触发预编译头的重建: 我决定在我的一本书中定义一些东西。cpp文件,改变预处理器解释已包含在预编译头中的某些头的方式 预编译头的使用是否应该强制执行某种限制性的编码风格,比如将. cpp文件中包含的头的数量限制为一个,并且永远不要在. cpp文件中定义ing内
gcc 是 GNU 推出的功能强大、性能优越的多平台编译器,是 GNU 的代表作品之一。它能将C、C++语言源程序、汇编语言源程序和目标程序编译、链接成可执行文件,如果没有给出可执行文件的名字,gcc 将生成一个名为 a.out 的文件。 gcc 通过后缀来区分输入文件的类型: 后缀 类型 .c C语言源代码文件 .a 由目标文件构成的档案库文件 .C|.cc|.cxx C++源代码文件 .h 程