VS 2015 新功能: 扩展的PGO 选项

[原文发表地址https://blogs.msdn.com/b/vcblog/archive/2015/09/10/new-in-vs-2015-expanded-pgo-options.aspx

[原文发表时间] 2015年9月10号 8:24 AM

我们在以前的博客中已经介绍过配置优化。得到的最强烈的反馈之一是生成检测二进制文件太慢了-很难训练某些应用程序的类,例如游戏。

VS 2015中我们已经努力在解决了这个问题。—从二进制检测文件的代码生成和关联的 PGO 运行,来提高运行时性能和最小化系统的开销,有许多的背后的场景变化。我们已经看到在某些情况下增加了 30%。每个人都免费获取这功能 — 你不需要做什么,就可以在VS 2015 中使用PGO。但今天我想谈一谈有一些优化功能没有默认被打开的原因,以及他们相关的命令行选项。

回顾一下,在VS 2013使用PGO,你需要将/ LTCG:PGI发送给链接器,来产生检测的二进制文件,然后将/ LTCG:PGU发送给链接器,来产生PGO优化的二进制文件。

在VS 2015,PGO特定选项已被集中成一个顶层开关加到LINK.EXE,有几个自己的子开关。从link/?

/GENPROFILE[:{COUNTER32 |COUNTER64 |EXACT |MEMMAX=# |MEMMIN=# |NOEXACT |NOPATH |NOTRACKEH| PATH| PGD=filename| TRACKEH}]

有必要设定它为一个顶层开关,以便给它子开关。 GENPROFILE的第一条规则:所有的默认行为和VS 2013是一样的,传递/ GENPROFILE,无子开关, 和/ LTCG:PGI在VS 2013是完全一样的-VS2015同样如此,因此:从兼容性角度考虑我们还是接受旧的开关。

COUNTER32 vs. COUNTER64:COUNTER64是默认的 – 用一个64位的值表示探针的计数,COUNTER32使用32位的值。这显然很重要,如果任何一个探针值接近或超过2 ^ 32 - 但实际证明是,几乎没有探针会那样。一个64位的增量开销与32位相比似乎不算太多,但要记住有许多探针在检测版本中,几乎每两个基本模块一个探针,因此代码段大小和性能的开销都增加到了X86。

那么,你如何知道什么时候可以安全使用counter32?那么,我们在pgomgr / summary 增加了一些有用的输出。

C:\temp>pgomgr foo.pgd /summary

Microsoft (R) Profile Guided Optimization Manager 14.00.23022.0

Copyright (C) Microsoft Corporation. All rights reserved.

PGD File: foo.pgd

03/05/2014 00:20:07Module Count: 1 Function Count: 11362 Arc Count: 12256 Value Count: 377

Phase Name:

Max Probe Counter: 0x0000000000DE0467 (0.34%)

Consider /GENPROFILE:COUNTER32 for increased training performance.

这个告诉我们在此训练场景中最大的探针计数值是DE0467,COUNTER32的最大探头计数器的值是DE0467(1400万),这是32位计数器空间(40亿)的0.34%。它甚至还没有接近。在此基础上,推荐使用COUNTER32你可以看到输出。

大多数训练场景,用counter32就足够了 - 事实上,我在内部还没有见过counter32不够用。但是,你能想象32位计数器溢出的后果是非常糟糕的,而且现有的外部客户很可能需要一个64位计数器来训练场景 – 所以默认的是counter64。

EXACT vs. NOEXACT: NOEXACT是默认的。这是已被弃用开关/ POGOSAFEMODE的重命名版本。EXACT的方法是为探针使用线程安全互锁递增,当NOEXACT被打开时,我们并不这么做。如果你有大量多线程程序,EXACT是一个好的选择,然而你的训练质量也因此受到伤害。出于兼容性方面的考虑, / POGOSAFEMODE仍然可以使用。

MEMMAX =#和MEMMIN =#: 这些值用于在内存中为训练数据指定以最大和最小字节的预留空间。在内部PGO采用启发来估计所需的内存量,并预留空间。因为它不可能稍后扩大空间(预留的空间需要是连续和稳定的),这个初始化预留非常有侵略性的。在某些情况下,特别是当多个二进制检测文件存在于同一个进程,这可能会导致地址空间不够,并最终因为内存不足而崩溃。

MEMMAX和MEMMIN提供了一种方式来指定PGO内部使用所需内存的上限和下限。但PGO仍然会重新估计,但会尊重MEMMAX和MEMMIN值的合适性。

所以,你怎么知道这里用什么值?我们也增加了一些有用的说明,但这次是在使用合并时候:

C:\temp>pgomgr /merge foo.pgd

Microsoft (R) Profile Guided Optimization Manager 14.00.23022.0

Copyright (C) Microsoft Corporation. All rights reserved.

Merging foo!1.pgc

foo!1.pgc: Used 14.7% (3608 / 24576) of total space reserved. 0.0% of the counts were dropped due to overflow.

在这个小例子,内存预留大小为24576字节,其中真正需要的仅3608字节。指定一个较低的MAXMEM规模生产的仪器二进制时,如果PGC文件包含这些值,你是安全的。另一方面还要估计,如果可用空间被填满的话会丢失多少数据。如果这个值不是0%,则可能需要指定一个较高的MEMMIN大小。

我猜想没有多少人曾经需要这个选项,但如果你在训练中发现自己陷入内存问题,就需要查看这个东西了。它被增加是由于存在内存问题时,唯一的选择就是要将多个二进制文件分成多个独立的单元训练,但它需要消耗更多的人力资源。

PATH与NOPATH: PATH是默认。路径配置是当PGO为每个唯一函数路径保留一组独立的计数器,考虑到更好的内联决策和在内联决策以后更精确的配置文件数据。这会引导来优化整体的代码生成。

那么,为什么你曾经关闭此功能? 那是因为这里的内存开销高:假如在你的程序中所有不同的路径去调用一个给定的函数。用路径配置,我们给每个函数分配一组独立的计数器!用NOPATH,我们只留一个。除了存储成本,当在每个函数的开端寻找正确的计数器时还有运行时成本。

如果你的内存使用量是如此之高,生成二进制检测文件的运行性能的是如此糟糕,致使你考虑不使用PGO,请尝试NOPATH。

我们真的很喜欢路径配置和有意义的测量获得优于非路径分析,所以我们不愿意将其默认为关闭。但是,我们希望人们使用PGO,然而非路径分析相对于LTCG也有很显著的优势。因此,它在这里作为最后采取手段。

TRACKEH与NOTRACKEH:TRACKEH是默认的。基本意思是说每个调用点有两个计数器,一前一后 –来保持准确的计数,当该调用抛出一个异常和控制流运行在其他地方。如果你的二进制文件生成通常不使用EH或在您正在运行的训练场景不使用EH,你可以安全地关闭这个功能省去这些探针调用,以获取更小的代码段和速度。这在默认情况下不是打开的,因为在EH与此选项同时打开时训练精度将受到损害。

PGD​​ = path:类似于/EXACT,这是那个老的/PGD开关从顶层开关降到为一个分支开关/ GENPROFILE。因为兼容性的问题/PGD仍被接受。

因此,关于/ GENPROFILE。您可能会注意到另一个看起来非常相似,/ FASTGENPROFILE开关:

/FASTGENPROFILE[:{COUNTER32 |COUNTER64 |EXACT |MEMMAX=# |MEMMIN=# |NOEXACT |NOPATH |NOTRACKEH |PATH |PGD=filename |TRACKEH}]

事实上,它是完全一样:唯一的区别是默认值。 GENPROFILE默认为计数器COUNTER64, NOEXACT, PATH, TRACKEH(和VS 2013一样),然而FASTGENPROFILE默认为COUNTER32, NOEXACT, NOPATH, 和NOTRACKEH。

对于使用配置文件,我们有一个新的/ USEPROFILE开关:

/ USEPROFILE [:PGD =filename]

这相当于在VS 2013中的/ LTCG:PGU(如你所期望,因兼容性/ LTCG:PGU仍被接受的)。这里的PGD选项是和/ GENPROFILE一样的,也就是在VS 2013里的 老开关/ PGD。

如果您目前或计划从IDE使用PGO:我们目前还没有更新了我们的属性页来接受这些新的配置文件优化开关,他们仍然指向那些在VS2013里的开关。这些属性页的变化将出现在VS 2015更新版本上。现在,请使用链接器命令行属性。

大体情况就是这样。在VS 2015,我们清理了PGO开关的混合,为控制代码生成和训练精确的检测PGD提供了一组选项。有很多并没有影响训练质量的场景以外改进也被实现了。所以在VS 2015试一试PGO,我们非常乐意得到您的反馈!