我有一个 native C++应用程序,该应用程序执行大量计算并消耗大量内存。我的目标是对其进行优化,主要是减少其运行时间。
经过几个周期的性能优化后,我尝试了从未进行过的Profile Guided Optimization。
我遵循了MSDN Profile-Guided Optimizations上描述的步骤,更改了编译(/GL
)和链接(/LTCG
)标志。添加/GENPROFILE
之后,我运行该应用程序以创建.pgc
和.pdg
文件,然后将链接器选项更改为/USEPROFILE
,并观看了报告使用了概要分析数据的其他链接器消息:
3> 0 of 0 ( 0.0%) original invalid call sites were matched.
3> 0 new call sites were added.
3> 116 of 27096 ( 0.43%) profiled functions will be compiled for speed, and the rest of the functions will be compiled for size
3> 63583 of 345025 inline instances were from dead/cold paths
3> 27096 of 27096 functions (100.0%) were optimized using profile data
3> 608324578581 of 608324578581 instructions (100.0%) were optimized using profile data
3> Finished generating code
在我评估程序的性能之前,一切看起来都是有希望的。结果对我来说绝对违反直觉
/USEPROFILE
选项进行比较时),慢4到5%。/GENPROFILE
用来创建Profile Guided Optimization数据文件的完全相同的方案时,它的运行速度也要慢4%。到底是怎么回事?
最佳答案
不要将其视为黑匣子。如果程序可以加快速度,那是因为它正在执行不需要执行的操作。
这些东西将在配置文件引导的或任何其他优化器中隐藏,并且肯定会在您的猜测器中隐藏。
他们不会对this隐藏。很多人使用它。
我试图抵制猜测的诱惑,但是我失败了。
这就是我在大型C++应用程序中看到的内容,无论它们的编写方式如何。
当人们可以使用简单的数据结构(如数组)时,他们使用带有迭代器和诸如此类的抽象容器类。时间去哪儿了?
就是这样。
他们要做的另一件事是编写“功能强大的函数和方法”。函数的编写者对此感到非常自豪,以至于它做得太多,以至于他/她希望它能被崇敬而谨慎地调用。
该函数的用户(可能是同一个人)认为:“看一下该函数有多有用!看看我可以在一行代码中完成多少工作?我使用的越多,我的工作效率就越高。”
看看这如何轻松地完成不必要的工作?
软件中还有另一件事-抽象层。
如果在多个抽象层上重复上述模式,则减速因子将成倍增加。
好消息是,如果可以找到它们,并且可以解决它们,则可以大大提高速度。坏消息是您可能会以“不是团队合作者”的身份受苦。