﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客--文章分类-译文</title><link>http://www.cppblog.com/Qntal/category/21353.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 28 Mar 2018 21:04:48 GMT</lastBuildDate><pubDate>Wed, 28 Mar 2018 21:04:48 GMT</pubDate><ttl>60</ttl><item><title>剖析的艺术：使用Intel VTune Amplifier，第8部分（终章）</title><link>http://www.cppblog.com/Qntal/articles/215567.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 14:41:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215567.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215567.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215567.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215567.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center;"><span style="font-size:27.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel VTune Amplifier，第8部分（终章）</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：https://hadibrais.wordpress.com/2017/07/30/the-art-of-profiling-using-intel-vtune-amplifier-part-8-final/</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Hadi Brais </span></strong><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">著</span></strong></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">本系列的<a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a></span>，<a href="http://www.cppblog.com/Qntal/articles/215556.html">第2部分</a>和<a href="http://www.cppblog.com/Qntal/articles/215561.html">第3部分</a>提供了剖析入门及怎样配置VTune。在<a href="http://www.cppblog.com/Qntal/articles/215562.html">第4部分</a>中首次讨论优化，大大减少了printf执行次数。在<a href="http://www.cppblog.com/Qntal/articles/215564.html">第5部分</a>中第二次讨论优化，strlen被更为廉价的方式使用。在<a href="http://www.cppblog.com/Qntal/articles/215565.html">第6部分</a>中第三次讨论优化，报告进度所需要的次数被大量减少。在<a href="http://www.cppblog.com/Qntal/articles/215566.html">第7部分</a>中第4次讨论优化，函数do_pswd被内联到调用者。下面图表显示了优化后提升密码破解吞吐量的曲线情况。</p>  <p align="left" style="margin: 23.4pt 0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part8-1.png" alt="" /></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">所有4次优化都是有意义的，尽管printf优化带来了最大效果。通常情况下，推荐减少I/O，或改为异步I/O，或是在专用线程中处理I/O，图形绘制也是一样的。这里有个有趣的事情，编译器在内联do_pswd这个重要点上失效了，我们不得不手动处理它。也许我们使用配置文件引导优化（PGO），编译器很可能会自己解决它。为了保持本系列的简洁性，这里我避免深入到算法，微型框架，并行优化中去，可能会在以后的文章中讨论它们，VTune在这些方面也会发挥作用。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 22:41 <a href="http://www.cppblog.com/Qntal/articles/215567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第7部分</title><link>http://www.cppblog.com/Qntal/articles/215566.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 14:31:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215566.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215566.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215566.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215566.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215566.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size:27.0pt;font-family:"微软雅黑",sans-serif">剖析的艺术：使用Intel VTune Amplifier，第7部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:"微软雅黑",sans-serif">原文：</span>https://hadibrais.wordpress.com/2017/07/29/the-art-of-profiling-using-intel-vtune-amplifier-part-7/</p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">Hadi Brais </span></strong><strong><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">著</span></strong></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">本系列教程的前面部分都可以通过以下链接找到：<a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a></span>，<a href="http://www.cppblog.com/Qntal/articles/215556.html">第2部分</a>，<a href="http://www.cppblog.com/Qntal/articles/215561.html">第3部分</a>,<a href="http://www.cppblog.com/Qntal/articles/215562.html">第4部分</a>，<a href="http://www.cppblog.com/Qntal/articles/215564.html">第5部分</a>和<a href="http://www.cppblog.com/Qntal/articles/215565.html">第6部分</a>。</p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">在<a href="http://www.cppblog.com/Qntal/articles/215565.html">第6部分</a></span>中，执行时间被优化了14%，密码破解吞吐量变为大概150百万个密码每秒。回到<a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a>，基线吞吐量大概为3百万个密码每秒。我们已经取得了长足的进步，但还可以从VTune中获取更多帮助。</p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">在<a href="http://www.cppblog.com/Qntal/articles/215565.html">第6部分</a></span>的最后图表中，热点排行榜出现了新的热点。CalculateCRC累积超过了50%的执行时间，让我们分别从源代码和汇编代码的角度观察一下。</p>  <p align="left" style="margin: 23.4pt 0cm;">&#160; &#160;&#160;&#160;&#160;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part7-1.png" width="584" height="90" alt="" /></p>  <p align="left" style="margin: 23.4pt 0cm;">&#160; &#160;&#160;&#160;&#160;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part7-2.png" alt="" /></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">这里是高亮两条代码展开后的指令，其中第40行为热度最高代码。VTune显示的该代码行的汇编指令实现，这些信息是VTune通过带优化编译选项且开启调试信息的二进制可执行体中获取的。例如第41行就是灰色无效的，它表明总是被编译器优化的代码，尤其是编译器会将CalculateCRC内联到它的调用函数中，并省略掉它的返回语句。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; VTune</span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">显然将36.7%的执行时间归于两条高度的指令，完全是因为第二条指令。但是这条指令仅是简单的将寄存器数据累加，真的开销那么昂贵吗？</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">记住VTune是定期进行性能指标采样的。在原始性能度量和单独指令之间的关联性取决于VTune，不可避免的在VTune分析中出现错误。但是这些信息仍然是有用的，我们可以使用人为分析技术精确定位到热点。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">尽管VTune的分析是不精确的，但通常已经离真相不远了。让我们检查一下附近的指令，看看它们是不是开销很大。除了以下两条指令可能开销大之外其余都是廉价的：一个条在0x400c71，另一条是0x400c90。它们都是进行内存访问。根据内存访问模型，它们之所以可能慢的原因，一个是cache misse，一个是bandwith限制。综上所述，我们并还没有足够的信息来确定它。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">不管怎样，我们先退一步，关注整个函数<a href="https://gist.github.com/hadibrais/9d778b2f2a6e2672e0e70517c1e02c5a#file-passwordcracker-c-L36">function</a>。该函数会被执行数以10亿次，里面有个for循环。从计算机体系结构角度来说，可以充分地优化它，但题更可能是算法本身。这种情况下，通常去理解算法实现，看看能否进行优化会更好一些。不幸地是，在这世界上，即使是VTune还是其他工具也不能帮助我们对算法进行优化。看上去我们一时不知道能做什么了，所以现在您不得不进行一些手动尝试。然而在这个系列中关注的是VTune，我不会使用这种方法, 并继续追求在体系结构层面上的优化, 希望在这个层次上仍然找到一些重要的优化点。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">幸运的是，在这个示例中，大多数的指令都是廉价的。通常情况下，使用TBS剖析查找和优化这些开销昂贵的指令是非常困难的。在这种时候，通用有勘探（<a href="https://software.intel.com/en-us/node/544025">General Exploration</a>）微型框架分析或内存访问（<a href="https://software.intel.com/en-us/memory-access-analysis-lin">Memory Access</a>）微型框架分析可供使用，它们都是使用EBS，<a href="https://software.intel.com/en-us/intel-advisor-xe">Intel Advisor</a>&#160;也能够提供巨大帮助。记住EBS中的事件，VTune使用硬件性能计数器，并为所有的指令维护计数器连续性来度量性能指标。即使剖析结果不是那么的精确，基于EBS结果也趋向于更为精确，并提供更多有用的信息。我不做微型框架分析，所以暂时不管它。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; VTune</span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">的高级热点分析相比基本热点提供了多得多的信息，尤其是能够帮助你找到热点循环和函数。您可以关注到可并行化热点循环，尝试内联热点函数或使用整体程序优化（<a href="https://en.wikipedia.org/wiki/Whole_program_optimization">whole program optimization</a>）方式优化它们。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">创建一个新的分析，选择高级热点类型，保留采样间隔为默认值1毫秒。选择细节级别为&#8220;热点，调用计数，循环访问计数和堆栈&#8221;。这个细节级别会增加剖析开销，并级程序的CPU耗时带来稍微增长。运行分析，其结果会类似于下图显示的那样。</span></p>  <p align="left" style="margin: 23.4pt 0cm;">&#160; &#160;&#160;&#160;&#160;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part7-3.png" alt="" /></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; VTune</span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">展示了更为丰富的信息，既可以直接定位热点，也可以指导更深入的分析。在这里我们关注循环访问计数和调用次数的评估。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; VTune</span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">通过观测循环控制流来评估循环访问计数。VTune记录了处于CalculateCRC中大概数以10亿次的循环迭代，与在gen_pswd中数值相近，这足以证明，将努力花在这些函数中的循环并行化上是很有价值的。但在该系统中，我并不打算这么做。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">首先，调用计数看上去令人吃惊。CalulateCRC和gen_pswd的调用次数怎么可能会是零呢？好吧，CalulateCRC的调用次数之所以是零，是因为它被编译器内联了。gen_pswd没有被内联，实际上在程序中被调用了一次，但调用次数并不足以在一个采样剖析中能被抓取到。接下来有趣的函数是do_pswd。这个函数显然没被内联，它被调用了数大概数以10亿次。实际上它确实被调用了数以10亿次，但再次提及，采样剖析时并不能抓取所有调用。注意一下，一个准确的调用度量需要使用基于仪表（instrumentation-based）剖析。然而在高级热点分析中，硬件事件用于测量调用次数。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">这里稍微简单的关注一下编译器强制内联函数。在gcc中，您总是可以使用总是内联（<a href="https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Function-Attributes.html">&#160;always_inline</a>&#160;）指示符。如果使用得当，不仅是do_pswd还是CalculateCRC和CheckCRC确保它们一样得到内联。进行这个变更，编译代码，重新剖析。在我这边看到的结果是，VTune已经完全忽略掉了所有的调用计数度量，因为没有调用得到记录。密码破解程序的吞吐量变为了大概170百万每秒。</span></p>  <p align="left" style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:"微软雅黑",sans-serif">&#160;&#160;&#160;&#160;&#160;&#160; </span><span style="font-size:11.0pt; font-family:"微软雅黑",sans-serif">接下来是该系列的<a href="http://www.cppblog.com/Qntal/articles/215567.html">最后一部分</a>，我会做个总结。</span></p>   <img src ="http://www.cppblog.com/Qntal/aggbug/215566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 22:31 <a href="http://www.cppblog.com/Qntal/articles/215566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第6部分</title><link>http://www.cppblog.com/Qntal/articles/215565.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 14:10:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215565.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215565.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215565.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215565.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215565.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size: 24pt; font-family: 微软雅黑, sans-serif;">剖析的艺术：使用Intel VTune Amplifier，第6部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：https://hadibrais.wordpress.com/2017/07/27/the-art-of-profiling-using-intel-vtune-amplifier-part-6/</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Hadi Brais </span></strong><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">著</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">本系列的前面部分都可以通过以下链接找到：<a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a></span>，<a href="http://www.cppblog.com/Qntal/articles/215556.html">第2部分</a>，<a href="http://www.cppblog.com/Qntal/articles/215561.html">第3部分</a>,<a href="http://www.cppblog.com/Qntal/articles/215562.html">第4部分</a>和<a href="http://www.cppblog.com/Qntal/articles/215564.html">第5部分</a>。</p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VTune</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">报告的热点如下面所示：</span></p>  <table border="1" cellpadding="0" width="584" style="width: 438pt; border-top: none; border-right: none; border-left: none; border-bottom: 1pt solid #222222;">  <tbody><tr>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">FUNCTION</span></p>   </td>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">MODULE</span></p>   </td>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPU TIME</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">gen_pswd</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">4.302s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">do_pswd</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">1.548s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CalculateCRC</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">1.544s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">___printf_chk</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">libc.so.6</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">0.036s</span></p>   </td>  </tr> </tbody></table>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">函数gen_pswd占用了CPU耗时总和的50%以上。定位到该函数的调用堆栈，点击它的堆栈帧实体，VTune将会为您显示该函数每个语句执行的耗时情况（这是根据每个语句的采样次数进行计算的）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part6-1.png" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">第98行几乎占用了整个程序CPU耗时的49%，大概是3.6秒。注意一点，第98行代码是函数gen_pswd函数所有引用的，而不是do_pwsd函数引用的。查看一下汇编指令的CPU耗时：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part6-2.png" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VTune</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">已经标明外部CPU耗时为49%，36%以上的执行开销在指令&nbsp;<strong>mov %r12d, %edx</strong>&nbsp;。如果您的仅从字面上理解，这是毫无意义的，因为寄存器之间进行值拷贝的开销要比除法操作廉价的多。这很可能剖析采样问题，误导了您。这里更为普遍的问题是采样间隔为10毫秒，但是在这个间隔中能够执行数以100万计的指令，热点很可能出现在循环中。在这种情况下，继续剖析与分析微型框架是必要的，但是在这里我不打算这么做。取而代之，我们将尝试通过检查代码的方式确定热点。For循环中主要包括两块：调用do_pswd函数和嵌套的while循环。如果您可以优化掉任何一个，我们就有理由相信预期的性能优化是有效的。函数do_pswd做了两件事件：报告进度和检查当前候选密码。语句printf用于报告进度是之前的热点。由于总共迭代次数10亿次，printf将会每隔1万次迭代执行一次。总共迭代次数为10,0000。这里您能够做一件事件，就是尽可能的减少进度的报告频率。让我们减少它基本迭代数的总和，如这样ITER/10。另外，gen_pswd调用数以10亿次，只执行ITER/10次迭代。我们在do_pswd调用printf之前先计算好进度。剖析结果如下：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part6-3.png" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">很棒。执行时间大约改善了14%，但出现了其他有意思的热点。现在没有什么能比报告中CPU利用率已经相当于100%超过99%更有价值了。让我们看看下次还能做什么吧。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215565.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 22:10 <a href="http://www.cppblog.com/Qntal/articles/215565.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第5部分</title><link>http://www.cppblog.com/Qntal/articles/215564.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 13:55:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215564.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215564.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215564.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215564.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215564.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size:24.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel VTune Amplifier，第5部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：<a href="https://hadibrais.wordpress.com/2017/07/27/the-art-of-profiling-using-intel-vtune-amplifier-part-5/">https://hadibrais.wordpress.com/2017/07/27/the-art-of-profiling-using-intel-vtune-amplifier-part-5/</a></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Hadi Brais </span></strong><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">著</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">本系列的前面部分都可以通过以下链接找到：<a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a></span>，<a href="http://www.cppblog.com/Qntal/articles/215556.html">第2部分</a>，<a href="http://www.cppblog.com/Qntal/articles/215561.html">第3部分</a>和<a href="http://www.cppblog.com/Qntal/articles/215562.html">第4部分</a>。</p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在<a href="http://www.cppblog.com/Qntal/articles/215561.html">上一部分</a></span>中，我们对程序进行了修改和分析之后，您将可以看到以下的类似结果：</p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part5-1.png" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">平均CPU利用率为0.25，CPU耗时为2.3秒。等等，现在还不是高兴的时候。VTune之前告诉我们CPU耗时为2.7秒，运行时间为17.1秒。这意味着花费在printf函数的总共执行时间为17.1 &#8211; 2.7 = 14.4。优化之前printf被调用次数是以10百万数，现在只有数以10万次。因此, 应该只有百分之14.4 &lt; 0.2 秒的I/O开销。但从结果显示超过了7秒，很显然哪里出问题了。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">起初这令我很困惑，我怀疑是不是当采样间隔太小时，VTune使用TBS模式时触发采样导致的问题。然后我将采样间隔修改回了默认的10毫秒，并重新进行剖析：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part5-2.png" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">漂亮！这才是有意义的结果。CPU耗时为9.6秒，比运行时间稍微大一点。同样CPU利用率为0.99，已经很接近理想值了，这意味着printf函数已不在是热点。从VTune的热点排名中，这次可以很清楚的看到strlen函数像是罪魁祸首。它大概占用了CPU耗时的33%，让我们检查一下堆栈吧：</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom:7.8pt; margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">libc.so.6&nbsp;! strlen &#8211; strlen.S<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">a.out ! do_pswd + 0x3a &#8211;&nbsp;main.cpp:60<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">a.out ! gen_pswd + 0x45 &#8211;&nbsp;main.cpp:94<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">a.out ! main + 0x1d5 &#8211;&nbsp;main.cpp:233<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">libc.so.6&nbsp;! __libc_start_main + 0xef &#8211; libc-start.c:291<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">a.out ! _start + 0x28 &#8211; [unknown source file]</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">注意一下，您可能会看到一个不同的堆栈或比这里多一些，这是因为在程序代码中有多个位置对strlen进行调用 ，这也取决在进行采样的时候，当前捕捉的是哪个被编译优化内联的函数。这个堆栈告诉您的，从do_pswd方法中调用的strlen函数开销最大。不管怎么样，看一下这个函数只有一个位置调用了strlen，并且是在一个条件语句当中。从终端的输出当中，您可以看到输出只有在12倍数条件才为真。然而do_pswd会被调用数以10亿次，因此纠结strlen并没有太大的意义，这是怎么回事呢？</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">通过检查do_pswd函数，你可以看到条件里面会调用CheckCRC，这个函数转而调用CalculateCRC，它是个条件终止循环（<a href="https://gist.github.com/hadibrais/9d778b2f2a6e2672e0e70517c1e02c5a#file-passwordcracker-c-L41">&nbsp;loop termination condition</a>）调用strlen。基于循环计数，调用strlen次数少于10亿次。不幸的是，我使用的编译器在优化代码时会在循环里面的strlen调用移到外面，使所有的迭代只会调用一次（通过查看汇编代码得到的），因此实际上strlen被调用了数以10亿次。如果您的编译没有这么处理，就手动完成了。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我们又能对strlen怎么样呢？这个函数用于计算以终止字符结束的字符串个数。我们能够完全避免调用它吗？让我们来检查一下生成的密码，看上去只是一些简单的普通数字模式。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在main函数中生成了第一个密码，在gen_pswd函数中会重新生成密码。只有在&nbsp;<a href="https://gist.github.com/hadibrais/9d778b2f2a6e2672e0e70517c1e02c5a#file-passwordcracker-c-L100">!psw[d]</a>&nbsp;为真时，密码长度才会增长一个字符，这就是我们所看到的模式。这里还定义了一个全局变量用于保存密码字符串长度。当每次条件为真时，长度会增长1位。这个变量在gen_pswd起始处进行初始化。因此修改代码重新剖析一下，平均CPU利用率并未变化，因为变更并没有减少I/O的等待时间，反正现在已经接近最优了。结果只有CPU耗时减少了，变为大概7.4秒，有23%的优化，还不赖。在下一部分中，我们尝试做得更好吧。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215564.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 21:55 <a href="http://www.cppblog.com/Qntal/articles/215564.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第4部分</title><link>http://www.cppblog.com/Qntal/articles/215562.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 07:39:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215562.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215562.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215562.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215562.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size:24.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel VTune </span><span style="font-size:27.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">Amplifier</span><span style="font-size:27.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">，第4部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：<a href="https://hadibrais.wordpress.com/2017/04/07/the-art-of-profiling-using-intel-vtune-amplifier-part-4/">https://hadibrais.wordpress.com/2017/04/07/the-art-of-profiling-using-</a>intel-vtune-amplifier-part-4/</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Hadi Brais </span></strong><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">著</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在该系列的</span><span lang="EN-US" style="font-size: 11pt; font-family: 微软雅黑, sans-serif;"><a href="http://www.cppblog.com/Qntal/articles/215561.html"><span lang="EN-US"><span lang="EN-US">上<span lang="EN-US">一部分</span></span></span></a></span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">中，我已经讨论了为目标程序设置VTune的基本热点分析。这里快速过一下目标程序，您会注意到在第18行（<a href="https://gist.github.com/hadibrais/9d778b2f2a6e2672e0e70517c1e02c5a#file-passwordcracker-c-L88" target="_blank">line 88</a>）有一个非常重要的函数gen_pswd，有人可能会为觉得gen_pswd就是热点。然而在VTune的分析报告中却并非如此。确保您的CPU占用的热点在VTune显示视图如本文下图所示：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part4.png" width="584" height="393" alt="" /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">运行时间（Elapsed Time）是指程序在运行过程中并处于剖析时的时钟时间工作总和。S, E, O分区表示开始时间、结束时间、开销时间，运行时间 =</span> <span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">E &#8211; S + O</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">。通常情况下，剖析所带来的开销时间对于整个剖析程序运行时间来说是可以忽略不计的。在之后的优化代码处理中，可以使用这个运行时间作为关注的运行时间基线，但对于热点分析本身是毫无用处的。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPU</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">耗时是指所有线程执行代码的活动时间总和。并不包含线程同步请求锁和I/O操作完成的耗时（包括图形绘制）。需要额外注意的是CPU耗时包含了自旋锁处于自旋状态的耗时，这一耗时主要是用于内存请求服务和确保缓存一致性。它们之和在VTune术语中称为自旋开销时间（<a href="https://software.intel.com/en-us/node/544471" target="_blank">Spin and Overhead Time</a>）。当CPU耗时大于运行时间时，表明程序是并行化的，这就需要您进行并发或同步分析。如果CPU耗时远远小于运行时间，表明出现了太多的 I/O同步。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">当前目标是单线程的，所以等待时间 = 运行时间 &#8211; CPU耗时 = 17.181 &#8211; 2.770 = 14.411 秒。这足以说明了我们之前的假设，剖析所产生的开销是微乎其微的。同样我们也可以得出这么个结论，执行时间都花在的I/O等待上面，正如上面CPU使用直方图所显示的。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPU</span></strong><strong><span style="font-size:12.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">使用直方图（The CPU Usage Histogram）</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></strong><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif;">CPU</span><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">利用率是一个量化应用程序有多少有效运行的度量。我的CPU有8个逻辑CPU（核心），所以CPU利用率最大为8或800%。CPU利用率是通过所有软件线程的总和计算得到的结果：CPUTime(T ,i)，i是软件线程数，T是代码执行时长，它要比采样间隔大些。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">与其笼统的报告CPU利用率数值，VTune还对CPU使用率进行了以下灵活的（可手动调整）4个分类：</span></p>  <p style="margin-top:15.6pt;margin-right:21.0pt; margin-bottom:15.6pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">Idle</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">：CPU利用率低于0.5。</span></p>  <p style="margin-top:15.6pt;margin-right:21.0pt; margin-bottom:15.6pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">Poor</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">：CPU利用率大于等于0.5，且小于或等于最大利用率的50%。</span></p>  <p style="margin-top:15.6pt;margin-right:21.0pt; margin-bottom:15.6pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">OK</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">：CPU利用率小于或等于最大使用率的85%。</span></p>  <p style="margin-top:15.6pt;margin-right:21.0pt; margin-bottom:15.6pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">Ideal</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">：CPU利用率大于最大利用率的85%。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPU</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">使用率是一个离散的度量，只是对数据进行归类，相对于CPU利用率作为连续的值要来得直观一些。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPU</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">使用率直方图的x轴显示的是从0开始跨越多个逻辑核心的CPU利用率。下面彩色条显示的是与之对应的CPU使用率。垂直的两个虚线，右边显示的是最大CPU占用率（图中是目标占用率），左边显示的是平均CPU利用率（图中平均CPU使用率）。高亮选择平均CPU使用率线条告诉您，具体平均CPU利用率为0.161。对于单线程的密码破解程序来说，最佳CPU利用率是1或100%。通过该系列教程，我将一步步接近这个目标，现在它是0.161。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPU</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">使用率直方图的y轴显示的是CPU运行时间。在图中有两个条蓝色垂直条，用于显示目标程序在不同CPU利用率的占用情况。其中一条处于中间位置，表示CPU占用率在-0.5~+0.5之间。每个垂直条就表示运行时间所处CPU利用率覆盖范围。你可以从直方图看出CPU使用率基本在Idle范围。对于一个单线程来说，一个处于1中间位置的蓝条才是优秀的。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">罪魁祸首</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">当前我们找到了这些昂贵的开销来自于I/O操作，看看是不是能通过减少或消除它们。热点排名摘要面板如下：</span></p>  <table border="1" cellpadding="0" width="584" style="width: 438pt; border-top: none; border-right: none; border-left: none; border-bottom: 1pt solid #222222;">  <tbody><tr>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">FUNCTION</span></p>   </td>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">MODULE</span></p>   </td>   <td valign="bottom" style="border-width: initial; border-style: none; border-color: initial; padding: 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">CPU TIME</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">___printf_chk</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">libc.so.6</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">2.620s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">gen_pswd</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">0.074s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">strlen</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">libc.so.6</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">0.032s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">do_pswd</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">0.024s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">CalculateCRC</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">0.012s</span></p>   </td>  </tr>  <tr>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">[Others]</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker</span></p>   </td>   <td valign="bottom" style="border-right: none; border-bottom: none; border-left: none; border-top: 1pt solid #222222; padding: 4.5pt 7.5pt 4.5pt 0cm;">   <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom:   23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">0.008s</span></p>   </td>  </tr> </tbody></table>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">这个表格显示CPU耗时最高的函数。注意因为采样频率非常高（10ms），对于一些CPU耗时相近的函数，它们的顺序可能出现差异。处于排名靠前的两个函数，它们的CPU耗时非常大，在每次程序剖析中，顺序应该是不变的，其他函数可能会出现不同顺序。通过减少采样频率的方式，可以使剖析结果更稳定一些。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CPU</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">耗时显示的是自身耗时（或是排它耗时），也就是不包括它调用其他函数的耗时。第一个函数___printf_chk，看起来跟标准的printf函数相关。通过调用printf将特定字符串写到标准输出，通常是命令行窗口。这是个I/O操作，但是谁在调用它呢？我们可以在Bottom-up面板中查看有关___printf_chk的堆栈调用列表。列表如下：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">libc.so.6&nbsp;! ___printf_chk &#8211; printf_chk.c<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker&nbsp;! printf + 0x29 &#8211; stdio2.h:104<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker&nbsp;! do_pswd + 0x4 &#8211;&nbsp;main.cpp:63<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker&nbsp;! gen_pswd + 0x46 &#8211;&nbsp;main.cpp:92<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker&nbsp;! main + 0x209 &#8211;&nbsp;main.cpp:231<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">libc.so.6&nbsp;! __libc_start_main + 0xef &#8211; libc-start.c:291<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">PasswordCracker&nbsp;! _start + 0x28 &#8211; [unknown source file]</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">跟之预期的一样，__printf_chk调用printf。更清楚的看到，printf在main.cpp中第63行的do_pswd函数中也被调用了。然后通过在代码中搜索&#8221;printf&#8221;，我们可以很快的确定printf的调用位置，一个是do_pswd，更多的是print_dot。对于检测这些执行路径使用的采样间隔（10ms）可能太大了，但实际上并无大碍，我们的目的仅是找到热点，63行的printf调用看上去就是了。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">让我们修改刚才定位到调用printf代码的位置，让它在每隔10,000个密码时才调用一次。使用优化参数重新编译运行一下。破解的吞吐量变成了每秒107百万次密码破解，对于之前的3百万已经是非常大的优化了。注意重复运行多次，确保优化结果是可重现的。在这里，您可以使用VTune的比较分析功能（</span><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif"><a href="https://software.intel.com/en-us/node/596643" target="_blank">compare between two analysis results</a></span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">），在这里我就不过多赘述了。</span></p>  <p style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">现在程序能够在1秒内进行至少10百万次迭代。让我们做些更有趣的尝试，看看有没有更多的优化空间，使它能够提升到每秒10亿次迭代。增长迭代次数并不会改变吞吐量，但会增加执行时间。这会给予剖析充足的时间收集信息来了解它的行为。仍然使用基本热点，但这次使用1ms采样间隔。我将会在</span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;"><a href="http://www.cppblog.com/Qntal/articles/215564.html">下一部分</a></span><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif;">讨论结果。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 15:39 <a href="http://www.cppblog.com/Qntal/articles/215562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第3部分</title><link>http://www.cppblog.com/Qntal/articles/215561.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Fri, 23 Mar 2018 06:36:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215561.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215561.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215561.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215561.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size:24.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel VTune </span><span style="font-size:27.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">Amplifier</span><span style="font-size:27.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">，第3部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：<a href="https://hadibrais.wordpress.com/2017/03/24/the-art-of-profiling-using-intel-vtune-amplifier-part-3/">https://hadibrais.wordpress.com/2017/03/24/the-art-of-profiling-using-intel-vtune-amplifier-part-3/</a></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"><strong>Hadi Brais&nbsp;著</strong></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在本系列中的第1和第2部分中，我已经讨论了剖析的基本知识以及为VTune提供了一个介绍。现在是时候创建、配置和运行一个分析了。对于我们感觉兴趣的性能热点查找，有以下两种方式可供选择：基本热点，高级热点。前者使用的是TBS，后者是EBS。在这个系统中都会讨论它们，在此我将选择基本热点作为起点。在真实世界场景中，您也可以选择高级热点，并使用更小的采样间隔，但与此同时也会带来更为显著的开销。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在运行分析之前，首先您必需先配置分析目标和分析类型。在基本热点分析中，需要注意以下几个重要参数：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:31.5pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析模式：可以是自动、本地、混合或托管之一。如果程序的代码在可执行的二进制形式中可用, 则说它是本地的，换句话说，代码需要模拟器的为托管，如Java或.Net。该参数是为了告诉VTune在剖析什么类型的代码。在托管模式中，仅有托管代码会被剖析，如果您关心的只是这部分时，请选择它，这有助于改善剖析性能。在本地、混合模式中，所有代码都会被剖析，但仅会对相关数据进行保留和分析。在自动模式中，VTune将会自行分析输入的二进制从而选择合适的模式。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:31.5pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">分析子进程：很明显，当剖析程序分叉（forked）或创建一个新进程时，用于指定VTune是否分析该进程。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:31.5pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">时间估量（<a href="https://software.intel.com/en-us/node/609022" target="_blank">Duration time estimate</a>）：用于指定当运行目标时未处理剖析的时间。VTune使用这个估量值来减小采样间隔和减少剖析结果的大小。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:31.5pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析大小限制（<a href="https://software.intel.com/en-us/node/609021" target="_blank">Profile size limit</a>）：指定剖析结果阈值大小，单位MB。当出现VTune暂停数据收集，但目标仍运行时，会出现一个空白跨度。VTune能在这个暂停点上继续进行分析及显示收集数据。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">其他一些选项一目了然，或是非常重要但仅支持EBS，我会在该教程的后面部分再进行讨论。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">对于密码破解程序，默认的选项已经足够了。选择基本热点分析，默认的采样间隔（大概是10毫秒），开始进行分析。程序将在运行一段时间后结束，在结束时，VTune将自动处理和显示结果，下一（<a href="https://hadibrais.wordpress.com/2017/04/07/the-art-of-profiling-using-intel-vtune-amplifier-part-4/">next</a>）部分再进行详细说明。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">注意一下，由于目标会打印输出到终端，在没有输出的情况下将快上很多。VTune会对目标输出终端重定向到自己的终端。VTune自身不会输出到终端，如果目标也是如此，那么以终端方式启动就变得很重要了。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-23 14:36 <a href="http://www.cppblog.com/Qntal/articles/215561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第2部分</title><link>http://www.cppblog.com/Qntal/articles/215556.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Sun, 18 Mar 2018 13:37:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215556.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215556.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215556.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215556.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215556.html</trackback:ping><description><![CDATA[<p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center"><span style="font-size:24.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel VTune Amplifier，第2部分</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：<a href="https://hadibrais.wordpress.com/2017/03/19/the-art-of-profiling-using-intel-vtune-amplifier-part-2/">https://hadibrais.wordpress.com/2017/03/19/the-art-of-profiling-using-intel-vtune-amplifier-part-2/</a></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"><strong>Hadi Brais&nbsp;著</strong></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在</span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;"><a href="http://www.cppblog.com/Qntal/articles/215555.html">第1部分</a></span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;">中，我已经介绍了VTune、剖析流程和剖析程序。剖析流程的第1步就是构建目标程序。在构建目标程序是打开编译优化选项是非常重要的。在这部分中，我将为分析类型进行介绍。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">目的</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在做任何事之前，您必须确定剖析的目的。您想要分析的是什么？在该教程中，您要分析的是热点。热点是指计算机程序或计算机系统的某个区域，该区域是大量活动对系统其余部分具有重要意义。其中一个更为常用的定义请参考</span><a href="https://en.wikipedia.org/w/index.php?title=Hot_spot_(computer_programming)&amp;oldid=644422063" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Wikipedia</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">。通常, 感兴趣的活动是程序执行情况。在这里，一个热点将是程序的一个区域, 其中占执行时间的总和的很大一部分时间。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">查找热点不仅仅是用来剖析的唯一理由，还包括查找错误、发现并行化时机、理解线程工作或进程的相互交互、分析特定I/O设备部或系统资源利用率、。如果您想进行性能优化，却无从下手，可以参考性能提速方法（</span><a href="https://software.intel.com/en-us/node/596500" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">performance tuning methodology</span></a><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在该教程中，我将着手于查找密码破解程序的性能热点。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">VTune</span></strong><strong><span style="font-size:12.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">工程及分析项</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VTune</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">工程就是一个分析项集合。一个工程仅有两个属性：工程名及保存分析结果的目录。动手吧，创建一个工程，名称随您取（冷静一下，描述性的名称更可取）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">一个VTune分析项是一对配置与剖析结果（在目标终止时生成）。在VTune GUI中，为配置分析项提供了两个标签，分析目标和分析类型。切换到分析目标标签页，选项合适的选项，参考这里（</span><a href="https://software.intel.com/en-us/node/596517" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">here</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">分析类型</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析技术可分为3种：采样、仪表、软件事件订阅。采样的过程是，周期性中断程序或系统，并在此时抓取它的状态信息。仪表的过程是，在程序中感兴趣的位置插入称为仪表器的代码片段，这些仪表器伴随程序一起执行，并收集程序的行为信息。一般来说，仪表比采样得到更为精确的结果，但随之开销也大得多。VTune同时使用这两种技术，它使用</span><a href="https://software.intel.com/en-us/articles/pin-a-dynamic-binary-instrumentation-tool" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Pin</span></a>&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">处理仪表器，并管理在运行的目标进程。软件事件订阅的过程是，它依赖于运行时或操作系统报告系统的行为事件，剖析器能订阅某些可监听的回调事件。VTune通过仪表及跟踪技术（&nbsp;</span><a href="https://software.intel.com/en-us/node/544195" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Instrumentation and Tracing Technology (ITT) APIs</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">.</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）来支持这种方式。以下是两种采样方式：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">基于时间采样（TBS）</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">基于时间采样，通常称为软件收集或用户模式采样及跟踪收集（</span><a href="https://software.intel.com/en-us/node/596498" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">User-Mode Sampling and Tracing Collection</span></a><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">），利用时间定时器中断当前进程所有线程并抓取所需的信息。之所以称之为用户模式，是因为它在不需要内核驱动的情况下，就能进行抓取采样（与基于事件的采样相反）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我说一下它在Linux下是如何工作的。当VTune启动或关联到一个进程时，程序将调用</span><a href="https://linux.die.net/man/2/setitimer" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">setitimer(2)</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">创建ITIMER_PROF定时器并传递一个数值作为采样间隔。即使程序也会使用setitimer函数，VTune会对这些调用进行模拟，剖析器会将它们排除在外。顺便一说，Windows下的等价函数是&nbsp;<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ms644906(v=vs.85).aspx" target="_blank">SetTimer</a>。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">当一段约等于采样间隔的时间过去后，将会产生SIGPROF信号，操作系统将会选择其中一个线程来处理它。当然，VTune会为该信息注册处理器。处理器按适当的顺序执行下列操作:</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">决定是抓取一个采样，还是传递给程序处理，如果是后者，那么调用程序的处理器并返回。</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">挂起其余所有线程。</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">记录当前指令指针（IP）和每个线程的调用堆栈。</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">恢复其余所有线程。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">可编程的定时器会周期性发出信号。您可以设置VTune的采样间隔，在1到1000毫秒之间。实际上最小采样间隔要依赖于操作系统（</span><a href="https://software.intel.com/en-us/node/609035" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">OS dependent</span></a><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">.</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">一般来说，采样要做到正确是困难的。线程的创建、终止、动态库的加载和卸载都是需要跟踪的。更多内容参看这里（</span><a href="http://compsci-dev.rice.edu/research/technical-reports/TR04-437/" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">this</span></a>&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。感谢VTune，您大可不必担心这些问题。请注意, 由于它工作方式的原因，使用TBS进行整个系统剖析并不方便。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBS</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">不依赖于任何特定硬件特性，仅仅是一个定时器就能工作。所以，您可以在Intel和非Intel处理器中使用TBS。以下是使用TBS的分析类型：</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">基本热点</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">并发</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">锁与等待</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TBS</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">同时能用于任何虚拟机。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">基于事件采样（EBS）</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">基于事件采样，通常称为硬件收集或基于硬件事件采样收集（</span><a href="https://software.intel.com/en-us/node/596494" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Hardware Event-based Sampling Collection</span></a><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">），当某些事件中断发生时，Intel处理器将使用性能监视单元接收这些中断。它远比TBS强大得多，但只能用于Intel处理器。对于其他处理器，也有特定的剖析器，例如：</span><a href="https://github.com/GPUOpen-Tools/CodeXL" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">AMD CodeXL</span></a>&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">支持AMD处理器下的EBS。跟VTune一样，CodeXL在所有兼容处理器中支持TBS。每个逻辑内核 (硬件线程) 都有一个 PMU, 用于处理与该核心有关的事件。然而，多个逻辑内核也同时共享一个资源（如一个L2缓存），此时将共享一个事件集合。另外，还有个单独的PMU来处理一些非核心（L3缓存、内存控制器、QPI）的关联事件。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">事件计数器可以是可编程，也可以是固定的。在同一时刻，仅有少量的可编程计数器可用 （一般是4个）。固定计数器总是可用，但在溢出时不会被通知。更多采样的实现信息，请查阅下列文章：</span><a href="https://software.intel.com/en-us/node/609449" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">article 1</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">,&nbsp;</span><a href="https://software.intel.com/en-us/blogs/2013/05/29/how-does-intel-vtune-amplifier-xe-calculate-hardware-event-counts-from-the-hardware" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">article 2</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">,&nbsp;</span><a href="https://software.intel.com/en-us/blogs/2013/05/29/sanity-check-statistical-data-validity-of-intel-vtune-amplifier-xe-results" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">article 3</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:0cm;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">检测热点时有非常多的特定事件可用（Haswell中定义的事件名称）：</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:43.0pt;text-indent:-22.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPU_CLK_THREAD_UNHALTED.REF_XCLK</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">：可编程计数器，用于获取递增计数器时钟，引用时钟(XCLK)频率，只有在硬件线程非中止状态时可用（有些软件线程被调度到硬件线程时，线程没有执行HLT指令或MWAIT指令）。它计数的是基准周期。主频为133MHz的Westmere和低一点的100MHz的Sandy Bridge就是这类。当超线程不可用时，CPU_CLK_UNHALTED.REF_XCLK计数可用；</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:43.0pt;text-indent:-22.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPU_CLK_UNHALTED.THREAD_P</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">：可编程计数器，用于获取递增计数器，在当前时钟频率下硬件线程处于非中止状态时，换句话说就是钟周期数。注意动态频率或散热将会导致时钟周期产生变化。这些被称作核心周期相对于基准周期；</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:43.0pt;text-indent:-22.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPL_CYCLES.RING0</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">：可编程计数器，用于获取递增计数器，在当前时钟频率下硬件线程处于非中止状态时运行在Rang 0级（特权模式）时；</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:43.0pt;text-indent:-22.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">PL_CYCLES.RING123</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">：可编程计数器，用于获取递增计数器，在当前时钟频率下硬件线程处于非中止状态时运行在Rang 1，2，3级（非特权模式）时。该计数器与上个计数器可用于区分用户模式与内核模式的CPU利用率情况；</span></p>  <p style="margin-top:7.8pt;margin-right:0cm;margin-bottom: 7.8pt;margin-left:42.0pt;text-indent:-21.0pt;"><span style="font-size:11.0pt;font-family:Wingdings;">n&nbsp;</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">CPU_CLK_UNHALTED.REF_TSC</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">：固定计数器，用于获取递增的计数器，在相同频率时的时间戳计数器(TSC)。等于参考频率乘以额定比率（非加速）（等于额定频率除以10<sup>^8</sup>）。参看可编程计数器CPU_CLK_THREAD_UNHALTED.REF_XCLK。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">VTune</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">使用这些计数器进行采样。每个逻辑核心有它自己的一套可编程计数器，每个核心可中断它运行的采样线程。当使用比较小的采样间隔时，相对于TBS这会导致少量开销。然而，对这些计数器在进行编程和使用时需要内核驱动程序（伴随VTune安装）。另外，如果剖析的程序同时也使用PMU，那么该功能将失效。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">硬件性能计数器并不受限于特定的软件线程或进程，它们是系统范围的。所以如果您只对单个进程的剖析感觉兴趣，但其他潜在进程也运行于系统中，性能计数器所有描述的程序行为并不总是精确的。VTune会管理线程，不管它是否派发到核心上，使得性能计数器能够为特定进程保存独立的状态，这也就说明了为什么在剖析系统时只能使用有EBS。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我注意到了一点，在使用EBS时，VTune 不会禁用动态频率缩放，这是件好事。这才是程序被剖析时的真实行为。其他剖析器会禁用动态频率缩放或使用固定的最大频率，以方便中断计数器。也可能是VTune在处理相关事件时才会这么做。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我之前提到的分析类型使用的是TBS，其他所有类型使用EBS（</span><a href="https://software.intel.com/en-us/node/596494" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">All other analysis types use EBS</span></a><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">）。在EBS下VTune支持采样间隔在0.01~1000毫秒之间。重申一遍，TBS的最小采样间隔远远小于1毫秒。最小间隔限制主要取决于硬件本身，最大间隔限制是因为更大的间隔对剖析并不用处。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">对于EBS与TBS，在进行采样时，间隔不取决于硬件频率。要牢记的是，除了实时系统，在特定地频率下定时器的中断触发将是近似的。在一个间隔后，一次采样将不会发生，可能在之后的某个时间触发。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;text-indent:22.0pt;"><span style="font-size:11.0pt;font-family: &quot;微软雅黑&quot;,sans-serif">EBS</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">能够用于支持硬件性能计数器虚拟化技术的虚拟机。详情请参考这里（</span><a href="https://software.intel.com/en-us/node/638180" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">this</span></a>&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">采样vs.仪表</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">之前已经提到，仪表相对于采样会带来更大的开销，但与此同时也带来了更为精确的程序行为描述。如果有函数的执行时间太短（小于采样间隔），VTune将无法剖析到这些函数。出于这个原因，VTune将会尽可能的收集调用堆栈。观察下面这个例子调用路径</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">func1 -&gt; func2 -&gt; func3</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">如果func2执行时间太小，VTune可能无法抓取到这个函数的采样信息。那么剖析结果将会是如下调用路径：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">func1 -&gt; func3</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">旧版本的VTune提供一个称为剖析调用图，利用动态二进制仪表的功能精确抓取调用图。遗憾的是，出于一些原因，在新版本已经移除了，VTune目前支持源代码级仪表（</span><a href="https://software.intel.com/en-us/node/544194" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">source level instrumentation</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">如果您很想看到精确的调用图，您可以使用EBS并使用0.01毫秒，在大多数热点分析中都是有效的。通常您都不必这么做的，默认的1毫秒间隔已经是一个在剖析开销及精确度很好的平衡了。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在该系列的</span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;"><a href="http://www.cppblog.com/Qntal/articles/215561.html">下一部分</a></span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;">中，我将进行配置分析，运行分析。</span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215556.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-18 21:37 <a href="http://www.cppblog.com/Qntal/articles/215556.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>剖析的艺术：使用Intel VTune Amplifier，第1部分</title><link>http://www.cppblog.com/Qntal/articles/215555.html</link><dc:creator>slientlight</dc:creator><author>slientlight</author><pubDate>Sun, 18 Mar 2018 13:33:00 GMT</pubDate><guid>http://www.cppblog.com/Qntal/articles/215555.html</guid><wfw:comment>http://www.cppblog.com/Qntal/comments/215555.html</wfw:comment><comments>http://www.cppblog.com/Qntal/articles/215555.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/Qntal/comments/commentRss/215555.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/Qntal/services/trackbacks/215555.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-size:28.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"></span></strong></p><p align="center" style="margin-top:23.4pt;margin-right:0cm; margin-bottom:23.4pt;margin-left:0cm;text-align:center;"><strong><span style="font-size:24.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析的艺术：使用Intel&nbsp;VTune&nbsp;Amplifier，第1部分</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">原文：<a href="https://hadibrais.wordpress.com/2017/03/15/the-art-of-profiling-using-intel-vtune-amplifier-part-1/">https://hadibrais.wordpress.com/2017/03/15/the-art-of-profiling-using-intel-vtune-amplifier-part-1/</a></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"><strong>Hadi Brais&nbsp;著</strong></span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><a href="https://software.intel.com/en-us/intel-vtune-amplifier-xe" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Intel VTune Amplifier</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">是Intel处理器的最佳性能剖析及分析工具。它不仅支持所有Intel处理器，并能在Windows，Linux，Android和macos下同时工作。其中最基本的剖析功能也能用于非Intel兼容处理器（第2部分讨论）。如果你正处于非商业工作环境，获取它是免费的（</span><a href="https://software.intel.com/en-us/qualify-for-free-software" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">obtain it for free</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。除此之外，还有30天免费评估时间，要是你老板有钱的话，请购买正版吧。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intel VTune Amplifier</span><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">是提供给经验丰富的开发者及性能分析工程师使用的。因此，在这里我假设您能够自行安装它到系统中。在这个教程里，我使用的是非虚拟系统Ubuntu16.04，单颗</span><a href="http://ark.intel.com/products/75122/Intel-Core-i7-4770-Processor-8M-Cache-up-to-3_90-GHz" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Intel Core i7-4770</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">处理器。但在学习该教程时可以使用您首选的平台。同样您也可以在虚拟机中使用VTune，参考这里（</span><a href="https://software.intel.com/en-us/node/638180" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">here</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。从现在起，我将Intel VTune Amplifier简称为VTune，使用的版本是VTune 2017 Update 2，当然时下流行的版本都是可以的。</span></p>  <p style="margin: 23.4pt 0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VTune</span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">的使用方式有三种GUI mode、CLI mode、Visual Studio中。前面两个使用方式对应的二进制可执行体分别是amplxe-gui和amplxe-cl，我使用的是amplex-gui。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">坦白说，VTune的文档和教程一直以来都写得不太好。感觉它们更多的是为VTune的开发者而不是用户写的，过于简洁且含糊不清。看起来就像是Intel有意为之，使它们看上去尽可能简单, 产品看起来不太笨重或复杂, 而吓跑潜在的客户。我很难想像Intel在兜售产品时说&#8220;为专家打造&#8220;。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">反正，本教程是为那些认真的性能分析人员而编写的, 希望他们能够真正理解正在查看的数值和图表。如果您是初学者，从Intel的教程开始会更为适合。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析流程</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析是收集有关程序动态行为信息的活动。这些信息不仅用于聚合、分析，还以某些方式优化程序。不管使用的是哪款剖析器，在流程上都是一样的。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/qntal/part1.gif" border="0" alt="" /><br /></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">来源：&nbsp;</span><a href="https://software.intel.com/en-us/node/544005"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">https://software.intel.com/en-us/node/544005</span></a></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">首先，确定剖析目标程序，生成二进制可执行体。最好调用符号是可用的，可以是嵌入到二进制中，或是单独文件。剖析器使用调试信息进行单个执行体剖析或整个系统剖析。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">第2步，配置剖析器，剖析哪些内容、收集哪些信息及其他设置。在VTune术语中，称之为分析项。VTune工程就是分析项的集合。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">第3步，运行分析，这包括附加到已运行的进程或启动一个新进程来分析。剖析器会对性能带来一定的开销，小至1.1x，大到10，000x，这基于所使用的剖析技术。采样的开销最小，而仪表的开销最大。使用VTune时要根据具体情况择其一。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">第4步，VTune将解析结果，更好的展示内容，让您方便定位感兴趣的部分。这时，在VTune的帮助下，您可以进行结果分析了。您也可以进行结果比较，跟之前运行的结果相比，确定您对源代码或系统更改对程序造成了怎样的影响。您还需要决定是否还存在尚未解决的问题。如果没有，工作至此结束（很遗憾，流程图中少了这步）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">最后, 为了确信您所做变更已经解决了问题，需要重新对程序或系统进行剖析。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">这个过程一直持续到所有问题得到解决，或是您察觉不到还存在问题为止。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">所以，是什么导致了性能问题呢？这取决于程序本身是非功能性规范。应该有一些文档, 说什么是可以接受的, 通过分析, 你可以决定是否满足非功能性要求。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">剖析程序</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">有个叫Kris Kaspersky的人在十年前写了一本很棒的书：</span><a href="https://www.amazon.com/dp/1931769249/?tag=internetarchi-20" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">Code Optimization: Effective Memory Usage</span></a><span style="font-size: 11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">。尽管书中的实验和使用的软件至今已经过时了，但其中的想法和呈现的技术在现在乃至多年后依旧有用。我将在该教程中使用的吞吐量程序改编于书中清单1.17，在这里找到（</span><a href="https://gist.github.com/hadibrais/9d778b2f2a6e2672e0e70517c1e02c5a" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">here</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">稍微提醒一下，您的不必拥有这本书，或是在学习该教程后去阅读它。理由嘛，我使用的程序跟Kaspersky书中使用的程序并不是一回事。首先，书中使用的VTune版本非常笨重，VTune从那里起已经大幅变更。其次，Kaspersky在书中讨论的一些技术并不适用于今天的处理器。我所希望的是您通过使用VTune优化程序时收获有用的经验和知识。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">现在我们快速浏览一下代码，对它的想法和目的有个基本了解。该系列教程是从处理大型代码库的开发人员的角度出发而编写的, 他们对代码仅有有限的了解或全部理解。这很像现实中您的使用剖析的情景。因此, 这里假设代码太大且复杂, 也无法完全理解。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">使用您喜欢的编译器并打开优化选项。在不带任何特殊参数的情况下运行构建得到的二进制可执行程序。程序将会输出密码破解吞吐量，每秒检查的密码数。在我的系统中，大概是3百万每秒。这个度量将是该教程中使用VTune剖析器进行优化的衡量标准。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">在我们做任何事之前，先得决定目标吞吐量。换句说，我们将密码破解吞吐量提升了多少呢。在实际的非功能性规范中，这可能是商业目标，提升2百万。然而，在这个教程里，让我们充分利用VTune，尽可能的提升吞吐量吧。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">术语基线被用于平台、程序或系统性能的优化参考值。并报告相较于基线的所有优化情况。这里以3百万吞吐量作为基线。如果我们能够对程序实现吞吐量提升2百万，那么就相当于提升了33%或1.5x。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">可重现性</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">可重现性是对某一度量值进行多次测量，并每次得到相同测量结果的能力。可重现性是性能评估的基础。如果一个实验是不可重复的，其结果是不可重现的，那么就无法判断是否优化了或优化了多少。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我们必须保证基本吞吐量的可重现性。这是通过连续多次测量吞吐量并观察结果中的方差来得到的。计算机是极其的复杂，并不能像期望的那样每次都得到相同的测量结果。一些细微的变化通常是可以接受的。当然这确保程序和平台的不变性。我们称之为基于统计的性能评估。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">现在我不打算深入讨论性能评估的所有数学知识，那样就在耽搁时间了。对于一个简单的密码破解程序，我们无论如何都无须关注这些。连续运行程序15次，吞吐量结果顺序如下：</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;">&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,740,894<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">3,019,334<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,883,304<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,689,124<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">3,124,446<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,961,334<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,954,207<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,876,620<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,928,249<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">3,017,467<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">3,212,000<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,766,821<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,862,842<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,794,467<br /></span>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">2,729,612</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">我们注意到吞吐量的最小值为2,689,124，最大值为3,212,000，平均值为2,904,048。在忽略吞吐量尾数的同时，我们也不会丢失精度，因为数值已经相当大了。另外注意一下，最小值与最大值实质上相差了17%。这种不确定性是系统与硬件导致的。这是一种常见的做法, 即在执行时间速度或吞吐量方面是根据平均 (又称算术平均数) 观察到的执行时间或吞吐量来衡量的。至此，基线吞吐量定为2,904,048。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><strong><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">调试符号</span></strong></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">二进制可执行体包括了一系列指令和附加信息，操作系统使用这些信息确保常量、已初始化和未初始化静态变量能够加载到正确的空间中。对这一层进行剖析，定位其中的热点是困难的。但至少在二进制中函数名称和位置信息是需要知道的，以便在剖析结果时，用于解析函数信息，要是有指令到源代码行的映射就更好。这些信息称之为调试符号或调试信息。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">如果正在分析的程序源代码可用, 则可以启用调试符号选项来编译它。否则，就需要检查看作者或开发商是否提供了单独的调试符号。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">使用您的喜欢的编译器，打开调试符号选项，编译密码破解程序。这对于用户级的分析已经足够了。但对于内核级的分析，您还需要内核的调试符号。对于如何安装Ubuntu系统的调试符号，您可以查看这遍博客（</span><a href="https://hadibrais.wordpress.com/2017/03/13/installing-ubuntu-kernel-debugging-symbols/" target="_blank"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">this</span></a><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">）。我安装这些符号只是出于好奇。在没有内核调试符号情况下，VTune将会把所有的内核代码聚合到一个称为[vmlinux]的单独标签中，因为实际的函数名称不可用。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">如果VTune没有找到相应的调试符号及源代码，它会向您显示一个警告，您也可以手动将包含这些文件的目录添加到搜索目录中（</span><a href="https://software.intel.com/en-us/node/544098" target="_blank"><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif; color: #1982d1; border: 1pt none windowtext; padding: 0cm; text-decoration-line: none;">here</span></a><span style="font-size:11.0pt; font-family:&quot;微软雅黑&quot;,sans-serif">）。</span></p>  <p style="margin-top:23.4pt;margin-right:0cm;margin-bottom: 23.4pt;margin-left:0cm;"><span style="font-size:11.0pt;font-family:&quot;微软雅黑&quot;,sans-serif">&nbsp; &nbsp; &nbsp; &nbsp;</span><span style="font-size: 11pt; font-family: 微软雅黑, sans-serif;">在<a href="http://www.cppblog.com/Qntal/articles/215556.html">下<span style="font-size: 10.5pt;font-family:等线;">一部分</span></a></span>，我将讨论一下VTune的工程配置及分析类型，敬请期待。</p><p><span style="font-size:12.0pt;font-family:&quot;微软雅黑&quot;,sans-serif"></span></p><img src ="http://www.cppblog.com/Qntal/aggbug/215555.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/Qntal/" target="_blank">slientlight</a> 2018-03-18 21:33 <a href="http://www.cppblog.com/Qntal/articles/215555.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>