当我在正常的一天编程时,我确保所有的分支都不被占用。
int retval = do_somting();
if(!retval) { /* Less-than-likely event*/ }
这个乐观主义者分支预测,导致CPU的预测器位设置为“不接受”。然而,预测器位是否会被迫返回到for循环后的“获取”中?
// prediction = "likely take"
if(false) { }
// prediction = "probably take"
if(false) { }
// prediction = "probably not take"
if(false) { }
// prediction = "likely not take"
if(false) { }
/* ... thousands of other if(false) that are speedy-fast */
for(int i = 0; i < 5; i++) { }
// prediction = "likely take"?
我知道这是一个不切实际的微乎其微的优化,但是你知道的越多。
编辑:让我们假设GCC并没有破坏上面所有的代码,我们也只讨论amd64体系结构。因为我没有意识到这个问题有多低。
发布于 2017-01-26 16:48:27
结果表明,分支预测依赖于CPU的模型。
根据本论文,当循环与正常分支相关联时,分支预测被以无数的方式处理。有些CPU有一个独立的预测器循环。因此,这意味着if
语句根本不影响for
语句的预测。其他人则有相同的预测。
无论如何,这个问题没有一个真正的答案。当谈到分支效率时,不能测量循环。
当然,...Unless计划只在单个CPU模型上运行您的程序。
发布于 2017-01-26 19:05:26
大多数具有分支预测的体系结构(包括AMD64)都认为短向下/向前跳跃/分支不太可能,而短向上/后向分支/跳变很可能。这意味着预测大多数循环将继续循环。由于初始条件,这使得do-while循环比for循环或while循环略高一些;但是,大多数优化编译器将尽可能将这些情况优化为类似的代码。
通过使用带有条件的-O3,您可以在__builtin_expect()
优化级别上看到与gcc的程序集的差异。不太可能的分支通常是向前跳转,而可能的情况则是根本不分支或向后跳。这可能涉及颠倒逻辑。注意:在-O3,gcc经常会将代码复制到不太可能的分支中,这样在可能的情况下分支就可以最小化。
这是有意义的,因为一个适合缓存行的循环如果分支到它的开头,就不会有缓存失败。类似地,由于程序通常在函数内线性向前推进,因此最近执行的代码也很可能已经在缓存中。当您用一堆额外的“优化”条件替换一个循环时,在某个时候(可能大约有4个条件),缓存丢失将覆盖以可读性和可维护性为代价的任何微小的好处。
https://stackoverflow.com/questions/41877720
复制相似问题