使用Intel编译器(5)PGO(7)PGO工具之tselect(test prioritization Tool)

来源:互联网 发布:文艺青年 大师 知乎 编辑:程序博客网 时间:2024/05/19 09:38
参考手册:

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011Update/compiler_c/index.htm


说明:本系列文章为个人笔记,如有不正确之处,请参考官方相关文档,如果错误发现,我会尽量更新修改。另外,以下内容不保证对于所有版本的编译器都正确,编译器的实现也可能有一些变化之处,具体参考官方文档。


更多说明请参考http://blog.csdn.net/gengshenghong/article/details/7034748中补充说明部分。


Summary:这里的工具是tselect,test prioritization Tool,从字面上,测试优先级工具,应该也是和测试相关的,所以测试人员可能比较容易理解,下面只是大概理解一下tselect的内容和如何使用,对于测试理论,我也不太懂。

关于测试优先级可参考:

http://blog.csdn.net/lengyue_112/article/details/375342

http://edu.21cn.com/ruankao/g_185_695002-1.htm等

(1) 测试优先级的作用

参考相关内容理解。


(2) PGO测试优先级工具tselect的使用介绍

1. 需要的文件

类似于codecov工具,tselect涉及的文件有:使用/Qprof-gen:srcpos选项编译得到的spi文件,由dyn文件合并的dpi文件。


2. tselect使用

使用:tselect -dpi_list file

其中-dpi_list是一个必须的选项,还有一些其它可选选项。

下面是tselect工具使用的典型模型:


简单的理解,第一步,使用/Qprof-gen:srcpos得到spi文件和辅助可执行文件,多次使用不同的测试数据运行辅助可执行文件,分别得到其dpi文件,将dpi文件以列表的形式放入一个文本文件中,使用tselect工具即可。


(3)实例:

以http://blog.csdn.net/gengshenghong/article/details/7053847中的差异覆盖的代码为例子(代码如下):

// File: tselect.cpp  #include <stdio.h>    void foo()  {      printf("This is foo\n");  }    void bar()  {      printf("This is bar\n");  }    void foobar()  {      printf("This is foobar\n");  }    int main(int argc, char* argv[])  {      int count = argc;      switch(count)      {          case 0:              printf("Case0\n");              break;          case 1:              printf("Case1\n");              foo();              break;          case 2:              printf("Case2\n");              bar();              break;          case 3:              printf("Case3\n");              foo();              bar();              break;          case 4:              printf("Case4\n");              foobar();              break;      }  } 

@echo OFF  rem #File: build.bat  set exeargs=arg1 arg2 arg3rem #can set env vars in command line or in this file before run this bat file.    if exist *.obj del *.obj  if exist *.exe del *.exe  if exist *.dyn del *.dyn  if exist *.lock del *.lock  if exist *.dpi del *.dpi  if exist *.spi del *.spi  if exist *.spl del *.spl    icl tselect.cpp -o tselect.exe /Od /Qprof-gen:srcpos /nologo  tselect.exe %exeargs%  profmerge
分别得到执行case1234情况下对应的dpi和spi,如下:

PGOPTI.SPI
pgopti1.dpi
pgopti2.dpi
pgopti3.dpi
pgopti4.dpi

创建文件list.txt如下:

pgopti4.dpipgopti3.dpipgopti2.dpipgopti1.dpi
然后运行:

tselect -dpi_list list.txt
输出如下:

Intel(R) C++/Fortran Compiler test prioritizer for applications running on Intel(R) 64, Version 12.1 Build 20111128Copyright (C) 1985-2011 Intel Corporation.  All rights reserved.WARNING: no SPI file name was specified, assumed .\pgopti.spi.Total number of tests   =  4Total block coverage    ~  91.67Total function coverage ~ 100.00 num  %RatCvrg  %BlkCvrg  %FncCvrg  Test Name @ Options ---  --------  --------  --------  -------------------   1    50.00     45.83     75.00   pgopti3.dpi   2    72.73     66.67    100.00   pgopti4.dpi   3    86.36     79.17    100.00   pgopti2.dpi   4   100.00     91.67    100.00   pgopti1.dpi

说明:运行tselect需要一个列表文件和对应的多个dpi文件,以及一个spi文件(默认是pgopti.spi),不需要源代码(这是和codecov不同的,codecov需要源代码,否则结果错误)。

1. 相关基本参数含义

上面的tselect的输出相关参数的含义如下:

(total number of tests)测试的总数为4,由list.txt决定,list.txt列举了多少个dpi文件,就是多少。

(total block coverage)总的块覆盖率为91.67%。

(total function coverage)总的函数覆盖率为100%。

下面的表格分别对应于列表中每一个测试的情况。

从上面的结果可以知道如下信息,运行pgopti3.dpi对应的测试覆盖了程序45.83%的基本块,占到了所有四次测试可以获得的总的块覆盖率的50%(即45.83%/91.67%=50%),另外,它对应的测试覆盖了75%的函数覆盖率(一共有foo、bar、foobar和main四个函数,case3的时候覆盖了其中的foo、bar和main三个函数,所以是75%);运行pgopti4.dpi对应的测试后,累积覆盖了程序66.67%的基本块,占到了总的四次测试可以获得的块覆盖率的72.73%(即66.67%/91.67%=72.73%),另外,它对应的测试累积覆盖了100%的函数覆盖率(case4会覆盖foobar函数,所以所有函数都被覆盖到了);其它的类似。

说明:

A、这里是有一个顺序问题,后面的测试是前面的累积的结果。另外,不太清楚这个pgopti3、4、2、1的顺序是如何确定的,跟list.txt的列举顺序没关系,无论怎么样的顺序列举,得到的tselect结果的顺序都是pgopti3、4、2、1!Why?(更新:参考下面的内容得到答案)

B、由于显示的是累积的结果,如果某一次测试对前面的测试结果的覆盖率等数据不产生变化,那么就不会显示在下面的表格中。比如list.txt如下:

pgopti4.dpipgopti3.dpipgopti2.dpipgopti1.dpipgopti4.dpipgopti3.dpipgopti2.dpipgopti1.dpi
对应的结果如下:

Total number of tests   =  8Total block coverage    ~  91.67Total function coverage ~ 100.00 num  %RatCvrg  %BlkCvrg  %FncCvrg  Test Name @ Options ---  --------  --------  --------  -------------------   1    50.00     45.83     75.00   pgopti3.dpi   2    72.73     66.67    100.00   pgopti4.dpi   3    86.36     79.17    100.00   pgopti2.dpi   4   100.00     91.67    100.00   pgopti1.dpi
测试总数为8,但是表格只有4行。

2. 估算最少测试次数
上面提到了显示的顺序和list.txt列举的顺序无关,为什么?说白了,是我没有理解到底这里的tselect工具是干嘛用的!下面来分析我对这个工具功能的理解。
PS:这个tselect的作用可能和上面说的测试中的测试优先级的概念不一定一样,个人理解。
要理解还是根据文档开始,上面举例的功能是tselect的基本功能,文档是:“Minimizing the Number of Tests”。之所以没有理解,是由于对Minimize的含义的理解,其有一个含义为“为...做最低估计”,如果知道了这层含义,那么上面的顺序问题就很容易理解了,其作用是“估算最小测试次数”,我的理解是:tselect对于多次测试的数据,根据这些数据,分析出如何进行测试(按照什么样的顺序执行这些测试),能尽快的达到最大的覆盖率,这里面就是一个“测试优先级”的问题了。比如上面的例子,很显然,pgopti3.dpi(执行case3),里面调用了foo和bar两个函数,这样就能尽快的覆盖更多函数了,而先执行pgopti4.dpi就能达到最大的函数覆盖率100%,如果先执行pgopti1.dpi或pgopti2.dpi是不会改变函数覆盖率的(当然,会改变块覆盖率)。总之,tselect给出了一个建议的优先顺序来执行这些测试,从而达到最大的覆盖率,对于某些测试的执行不会改变覆盖率的,就不会在结果中列出来了。

3. 估算最少执行时间

有了上面的理解,下面的内容就简单了。可以在list.txt的每一行测试后面加一个表示时间的数据,然后,使用-mintime选项来估算完成所有测试的最小执行时间的顺序(如果不使用-mintime选项,也可以在每行测试后写一个时间,这不是必须的,写了也没有什么影响,如果使用了-mintime选项,那么每行必须有一个时间,这个时间要符合一定的格式)。如下是list.txt的例子:

pgopti4.dpi 00:00:40:04pgopti3.dpi 00:00:30:03pgopti2.dpi 00:00:20:02pgopti1.dpi 00:00:10:01pgopti1.dpi 00:00:10:01

注意:其中dpi文件名和后面的时间之间可以有任意多个空格,但是,不能有tab(这点有点不友好)。

运行:
tselect -dpi_list list.txt -mintime

得到:

Total number of tests   =  5Total block coverage    ~  91.67Total function coverage ~ 100.00Total execution time    =     1:50:11 num  elapsedTime   %RatCvrg  %BlkCvrg  %FncCvrg  Test Name @ Options ---  -----------  --------  --------  --------  -------------------   1        10:01    36.36     33.33     50.00   pgopti1.dpi   2        30:03    59.09     54.17     75.00   pgopti2.dpi   3      1:00:06    77.27     70.83     75.00   pgopti3.dpi   4      1:40:10   100.00     91.67    100.00   pgopti4.dpi

所以,一共五次测试,其中总的执行时间只需要1:50:11就能达到最大的覆盖率,顺序就是按照时间顺序从少到多的,其中list.txt中的最后一个pgopti1.dpi(第五次测试)是不需要进行的,因为它的执行对覆盖率没有任何影响。(当然,这里故意用同一个dpi数据,所以肯定不会改变覆盖率,但是不同的dpi也可以不改变覆盖率的)。


4. 其他选项

到这里,就基本理解了tselect的作用和用法了,接下来就看看其它的选项。

-help: 显示帮助。
-dpi_list file: 唯一一个必须有的选项,指定列表文件。
-spi file: 指定spi文件。
-o file: 指定tselect输出的报告的文件,默认情况下是输出到控制台的,指定-o后,直接输出到文件,控制台不输出。
-mintime: 估算最小执行时间。
-nototal: 报告中不包含total的那些信息。
-verbose: 工具会显示运行时的更多日志信息,且报告中会显示更详细的信息。

-cutoff value: 其参数是一个值,指定tselect工具在累积块覆盖率达到预计的总的块覆盖率的value%的值的时候就终止。比如:tselect -dpi_list list.txt -cutoff 10.00,表示只要块覆盖率达到10%就终止。下面是一个列子:

tselect -dpi_list list.txt -cutoff 49

得到:

Total number of tests   =  5Total block coverage    ~  91.67Total function coverage ~ 100.00 num  %RatCvrg  %BlkCvrg  %FncCvrg  Test Name @ Options ---  --------  --------  --------  -------------------   1    50.00     45.83     75.00   pgopti3.dpi

同样的例子,使用:tselect -dpi_list list.txt -cutoff 51,得到:

Total number of tests   =  5Total block coverage    ~  91.67Total function coverage ~ 100.00 num  %RatCvrg  %BlkCvrg  %FncCvrg  Test Name @ Options ---  --------  --------  --------  -------------------   1    50.00     45.83     75.00   pgopti3.dpi   2    72.73     66.67    100.00   pgopti4.dpi


-srcbasedir dir:
-comp: