我有两个功能void f(int x){...}
和void g(int x){f(x);}
。我知道99%的时间g()
收到3或5。在f()
中,x
从不改变,并监督许多循环和条件分支。以下内容会比我的原始代码快吗?
void g(int x)
{
if(x == 3) f(3);
else if(x == 5) f(5);
else f(x);
}
编译器(g++ -Ofast
)与f(3)
分别编译f(5)
和f(x)
类似于编译两个模板参数吗?我应该怎么做才能让编译器更轻松地认识到优化机会?声明void f(const int &x){...}
有帮助还是必要?
答案 0 :(得分:1)
此类问题的答案最终会引起误解,因为它们不仅取决于您使用的确切环境,还取决于您的项目将与之链接的其他代码(如果使用链接时间优化)。此外,编译器可以生成多个版本-更为“最优”,然后“最优性”取决于谁在呼叫g()
。如果g()
是constexpr-这样做,编译器可以使用该事实指导优化。
无论如何:您需要查看编译器的输出;与代码一起编译到您的项目中。只有这样你才能知道。作为序幕,您应该前往https://godbolt.org的Compiler Explorer,并在一个隔离的环境中亲眼看看。
答案 1 :(得分:1)
如果这是对性能至关重要的函数,并且99%的时间f(3)或f(5)被调用,并且您尝试进行优化,则应该测量此类调用的差值。如果f()是内联函数,则优化器也许可以更好地使用常量而不是变量,以便在编译时评估其某些功能(例如常量折叠,强度降低等)。 Godbolt.org查看程序集,看看是否有任何明显的改进。即使没有内联,LTO也可能会有所帮助,尽管不同的人对此表示不同程度的成功。
如果您没有看到太多改进,但认为可能事先了解x,则还可以考虑编写不同的专用版本的f(),例如针对这些情况进行了优化的f3()和f5()。 (尽管您最终可能还会遇到一条更大的指令,并遇到icache问题。这全都取决于您尝试进行的操作,看看收益(和损失)在哪里。最重要的是衡量。将代码复杂化对于没有收获(或更糟的是,以优化的名义减慢它的速度。)