首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法解释C++性能

无法解释C++性能
EN

Stack Overflow用户
提问于 2012-04-18 04:53:19
回答 2查看 181关注 0票数 2

如果您有一个永远不变且始终为零的变量A、一个函数F、一个函数G和一个函数H,并在具有-O3优化的现代英特尔台式机处理器上调用以下代码,然后在现代版本的GCC上执行以下操作:

代码语言:javascript
复制
for(i = 0; i < a_big_number; i++)
{
if(A != 0) F();
else G();
}

执行时间为2秒。请注意,F永远不会被调用,因为A始终为0。或者,

代码语言:javascript
复制
for(i = 0; i < a_big_number; i++)
{
if(A != 0) H();
else G();
}

仅需1秒即可执行。同样,A始终为0,而H永远不会被调用。最后,

代码语言:javascript
复制
for(i = 0; i < a_big_number; i++)
{
G();
}

仅需0.5秒即可执行。

给定前两个示例中的条件语句,为什么F和H的内容很重要?既然它们从未被调用过,为什么它们做什么会有什么不同呢?考虑到Intel处理器有复杂的分支预测,难道处理器不应该知道G()总是被调用的,甚至不会在条件语句上浪费时间吗?我知道条件指令应该会浪费一些时间,但我不明白为什么它会浪费这么多时间。

EN

回答 2

Stack Overflow用户

发布于 2012-04-18 05:10:33

假设编译器理解A是一个常量,它应该将以下代码转换为:

代码语言:javascript
复制
for(i = 0; i < a_big_number; i++)
{
    if(A != 0) F();
    else G();
}

如下所示:

代码语言:javascript
复制
if(A != 0)
    for(i = 0; i < a_big_number; ++i)
        F();
else
    for(i = 0; i < a_big_number; ++i)
        G();

或者,如果一个常量看起来是一个编译时常量,则完全优化F()函数调用。

如果没有发生这种情况(例如,可能存在副作用或其他-编译器不能保证它如何优化以及优化了什么),循环将遇到来自分支错误预测的性能影响。如果A没有改变,并且被调用的函数足够小,那么CPU应该锁定循环并记住分支,这样它就不会一遍又一遍地重复同样的错误。另一方面,循环可能会被展开,这可能会带来很大的伤害,因为它不能并行化,只会破坏代码大小和CPU必须跟踪的许多事情。

但是,你如何测量执行时间对我来说是一个谜,以及你在循环中调用的函数是做什么的。例如,您可以测量进程执行换出。因此,除非您提供一个完整的工作示例,并详细解释您的测量方法,否则不可能告诉您发生了什么。

无论如何,我打赌您的时间度量是不正确的,或者您在没有显示的代码中做了一些不好的事情,或者以上所有情况。

票数 0
EN

Stack Overflow用户

发布于 2012-04-18 09:06:49

据我所知,编译器不能确定分支是否不会执行。编译器所能做的最好的事情就是预测哪个分支更有可能。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10198983

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档