首先 specCPU是收费的,好像是800$还是1000$,缴费了才有软件分发给你,关键是你要提交结果,那估计得需要购买了,因为测试报告里面有个序列号,应该是购买后给的一个号,测试的时候也要写到配置文件里,但是个人1测试或者普通项目摸底测试,都是百度或者找整机,CPU或者操作系统厂家给。
specCPU和其他性能测试工具类似,基本上都是在被测试机器现场编译测试程序,再运行测试程序得出测试结果以获得最优测试结果。
但specCPU还有个特殊的地方在于除了测试程序外,还自带了一些工具包,在编译specCPU之前,这些工具包得处于可用状态。
所以,如果是完全全新测试,整个测试过程首先是编译工具包,工具包包括好几个工具用于调用或者验证speccpu测试的,比如xz,md5sum perl tar make diff specinvoke。
编译好工具包后,specCPU的编译以及测试是通过runspec来调用和完成的。
因此,全新的specCPU测试需要进行两个部分的编译,分别是
但实际测试过程中,可能存在2种情况:
但是如果要自己编译speccpu工具包以及specCPU,根据官网说明,需要至少满足以下编译器。
Requirements SPEC CPU2006
https://www.spec.org/cpu2006/Docs/system-requirements.html#compiler
编译speccpu工具包参考如下官网地址:
Tools Build SPEC CPU2006
https://www.spec.org/cpu2006/Docs/tools-build.html编译器需求: 官网说明,C99 compiler. Most of the tools are C++ or C89, but XZ is C99.
编译过程很简单,如果在specCPU目录下tools/src下已经有源文件了,直接运行tools/src/buildtools,就可以完成编译了。如果没有源文件,直接从install_archives/cpu2006.tar.xz解压到tools/src下再编译就行。
xz -dc install_archives/cpu2006.tar.xz | tar -xf - tools/src
编译过程会提示perl测试有错,直接y忽略,编译完成后
- . ./shrc
- runspec -V
进行检查编译是否成功,可以运行runspec --test进行perl的更综合测试。
下一步是编写工具描述文件description
在tools/bin/下新建一个能记住的名字比如linux-uos-aarch64的目录,直接从tools/bin/其他目录拷贝一个description文件到tools/bin/linux-uos-aarch64/下,修改内容,符合当前工具适合的平台描述就行。
最后一步就是打包
- . ./shrc
- bin/packagetools
直接运行,会自动在specCPU根目录下生成 linux-uos-aarch64-118.tar 这样的压缩包。
将spectar linux-uos-aarch64-118.tar 拷贝到其他未编译specCPU工具的目录下,spectar xf linux-uos-aarch64-118.tar 解压到对应未知后,使用
install.sh -u linux-uos-aarch64
就安装好工具了。
在飞腾2000/4编译过程遇到的坑:
glob/glob.c:xxx: undefined reference to `__alloca'`×
在编译前面也有警告提示,到连接的时候会报找不到alloca,直接注视掉宏定义的前面和后面,让这个alloca定义上就好了。
- // #if !defined __alloca && !defined __GNU_LIBRARY__
-
- # ifdef __GNUC__
- # undef alloca
- # define alloca(n) __builtin_alloca (n)
- # else /* Not GCC. */
- # ifdef HAVE_ALLOCA_H
- # include
- # else /* Not HAVE_ALLOCA_H. */
- # ifndef _AIX
- # ifdef WINDOWS32
- # include
- # else
- extern char *alloca ();
- # endif /* WINDOWS32 */
- # endif /* Not _AIX. */
- # endif /* sparc or HAVE_ALLOCA_H. */
- # endif /* GCC. */
-
- # define __alloca alloca
-
- // #endif
报/stdio.h:474:1: error: 'gets' undeclared here (not in a function); did you mean 'fgets'?
直接给退出了。
直接编辑tar-1.25/gnu/stdio.in.h文件,注视掉#undef gets的两行。
- 142
- 143 /* It is very rare that the developer ever has full control of stdin,
- 144 so any use of gets warrants an unconditional warning. Assume it is
- 145 always declared, since it is required by C89. */
- 146 //#undef gets
- 147 //_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
- 148
直接修改tools/src/TimeDate-1.20/t/getdate.t文件第159行
my $offset = Time::Local::timegm(0,0,0,1,0,70);
修改为
my $offset = Time::Local::timegm(0,0,0,1,0,1970);
实际测试(编译好和未编译好specCPU)都是通过runspec来调用,但实际上最主要的部分在于配置文件的修改。
运行的命令可以简单的用如下格式来:
runspec -c linux-uos-aarch64
这里linux-uos-aarch64对应在config目录下linux-uos-aarch64.cfg内容,所有测试的参数以及优化参数都在这个文件里指定。
简单介绍下specCPU2006的测试情况:
测试主要是测试计算能力,所以基本上只和CPU 内存 编译器参数和优化有关,对磁盘图形等等其他的性能五官
peak compiled with aggressive optimization for each benchmark. 积极优化
base compiled with conservative optimization for each benchmark. 保守优化
运行参数 :
参数用-n 1 每个测试的运行次数,默认3 ,如果要出报告,需要是3,配置文件用iterations ,
参数用--tune=base或者--tune=all运行是否包括peak 配置文件用tune = base 不包括peak ,all 包括base peak
运行例子:
- #运行整数计算能力,int换成fp则计算浮点,换成all表示整数浮点数都运行
- runspec --config test.cfg --noreportable int
- #可以直接指定某个整数或者浮点数的测试项,这在调整编译优化参数的时候很有用。-n 1表示只运行一次,默认每个测试项会运行三次。
- runspec --config mat_dec25j.cfg -n 1 --noreportable 482.sphinx
- #只运行base,如果--tune换成all,则base peak都运行,这个在针对单个spec项调整参数做编译或者优化的时候最有用
- runspec --config mat_dec25j.cfg -n 1 --tune=base --noreportable 482.sphinx
-
-
-D 定义宏用,如果代码有ifdef可以编译的时候通过-D定义宏来开关,或者 -DNAME=Peter来定义宏的值,但不知道代码里面如果定义了,是代码定义的优先级高还是这里的搞。
-l (小写L) 是指要链接的库名,如果是-lz 表示连接libz ,如果还加了-static 则寻找libz.a静态库。
-L 表示寻找库的目录,-I (大写i) 表示寻找头文件的目录
-lz 压缩库(Z)
-lrt 实时库(real time):shm_open系列
-lm 数学库(math)
-lc 标准C库(C lib)
-dl ,是显式加载动态库的动态函数库
-ftree-parallelize-loops=8 开启多线程并行,这对某些整数和浮点数CPUspeed成绩有提高,具体的可以参考
AutoParInGCC - GCC Wiki
https://gcc.gnu.org/wiki/AutoParInGCC
462.libquantum 2.5X
410.bwaves 3.3X
436.cactusADM 4.5X
459.GemsFDTD 1.27X
481.wrf 1.25X
不过查看specCPU 2006提交的报告,基本上都是开了并行的。如果要在报告中显示并行,还需要在编译参数-ftree-parallelize-loop=8的flag描述文件中添加并行说明
- <flag name="F-ftree-parallelize-loops:8"
- class="optimization"
- parallel = "yes"
- >
- <![CDATA[
- <p>Supported 8 core parallelize</p>
- ]]>
- </flag>
如果指定了-static的优化参数,/usr/bin/ld: cannot find -lm
需要补充yum install glibc-static libgfortran-static
据说用gcc9会获得更好的成绩。
配置文件和命令行优先级关系:
配置文件内命名选项 > 命令行 > 配置文件头部选项
配置文件的主要三个组成部分:
头部选项:绝大部分选项都在头部
用户定义的命名选项 :用于提前定义编译的时候各种优化参数,在编译的时候,根据优先级合并后确定编译参数。
命名选项基本格式由四个部分组成,
benchmark[,...]=tuning[,...]=extension[,...]=machine[,...]:
对于组成部分后面全是default的,可以省略,比如:
403.gcc=base=default: 403.gcc=base:
是相同的
具体测试的时候,命名选项内包含的参数优先级按命名的详细成都来确定的,命名选项名称指定的越具体,则编译的时候使用优先级越高。
- $ cat tmp.cfg
- runlist = sjeng
- size = test
- iterations = 1
- tune = base
- output_format = text
- teeout = 1
-
- default=default=default=default:
- OPTIMIZE = -xO2 -w
-
- int=default=default=default:
- OPTIMIZE = -xO3 -w
-
- $ runspec --config=tmp | grep sjeng.c
- cc -c -o sjeng.o -DSPEC_CPU -DNDEBUG -xO3 -w sjeng.c
- $
抄个官网的例子,上面的例子重,最终在测试的时候,编译选项使用的
int=default=default=default:部分定义的-xO3 ,是因为int=default=default=default:指定的比default=default=default=default:更具体。如果还有458.sjeng=default=default=default:这样的命名选项部分,那458.sjeng=default=default=default:下面跟的参数优先级更高,如果文件中出现重复的
458.sjeng=default=default=default:那谁排后面谁的优先级更高。
上面的情况对于命名选项的第二个部分也是一样的原理。
除了用benchmark和tune来命名,还可以用自定义extension名称来指定优化选项,从而在命令行可以指定--extension=xxx来使用extension部分的命名,下面再抄一个官网例子。
- $ cat tmp.cfg
- runlist = sjeng
- size = test
- iterations = 1
- tune = base
- output_format = text
- teeout = 1
-
- default=default=default:
- LIBS = -lslowmalloc
-
- default=default=myke:
- LIBS = -lbsdmalloc
-
- default=default=yusuf:
- LIBS = -lthread -lmtmalloc
- $
- $ runspec --config=tmp --extension=myke | grep sjeng.o
- cc -c -o sjeng.o -DSPEC_CPU -DNDEBUG sjeng.c
- cc attacks.o book.o crazy.o draw.o ecache.o epd.o eval.o leval.o moves.o
- neval.o partner.o proof.o rcfile.o search.o see.o seval.o sjeng.o ttable.o
- utils.o -lbsdmalloc -o sjeng
- $
- $ runspec --config=tmp --extension=yusuf | grep sjeng.o
- cc -c -o sjeng.o -DSPEC_CPU -DNDEBUG sjeng.c
- cc attacks.o book.o crazy.o draw.o ecache.o epd.o eval.o leval.o moves.o
- neval.o partner.o proof.o rcfile.o search.o see.o seval.o sjeng.o ttable.o
- utils.o -lthread -lmtmalloc -o sjeng
- $
- $ cd $SPEC/benchspec/CPU2006/458.sjeng/exe
- $ ls -lt | head -3
- total 5888
- -rwxrwxr-x 1 alan staff 244688 May 11 16:32 sjeng_base.yusuf
- -rwxrwxr-x 1 alan staff 244628 May 11 16:31 sjeng_base.myke
可以看到这里不光编译选项使用了自定义的,生成的spec二进制文件后缀也应用上了。
如果多个命名选项部分并无冲突,那,几个部分的编译参数都会合并应用到测试编译上(当然有相同参数的,以命名选项最详细的参数为高优先级)。
如果不同的命名选项参数有冲突,优先级如下:
benchmark > suite(官网例子就是去掉测试号的benchmark,比如bzip2,虽然指定benchmark是401.bzip2) > tune > extension
MD5部分: (用于校验编译好的specCPU测试的二进制是不是和cfg的值匹配,不匹配应该要重新编译)这部分不用管,测试的时候会自动更新进去的。
要跑好specCPU其实最主要还是对cpu以及编译器的细节要熟悉,才知道调整哪些编译选项是有用的,所以一般都是找CPU厂商 提供cfg,实际自己跑一跑就是了,最多优化下内存,比如双通道,或者BIOS放开了内存的参数调整,可以细调下内存参数。
如果对gcc优化参数不了解,会出现跑不过的情况,反正我目前遇到是不加优化参数gcc测试都跑不过,借鉴别人的cfg,浮点部分有一个benchmark,base跑不过(编译通过但运行的时候直接报非0错误退出)但peak反而跑过了。很是费解,要学习的东西太多了。
以上内容是自己测着玩的笔记,后面遇到有新的东西再做补充。
跑完后报告Invalid run 状态,他会在报告里面说明是啥原因,只需要查看报告Errors部分就行。
最主要的原因就是,缺少关于编译器使用的参数有效的flags xml描述文件。
在配置文件里可以用如下参数补充:
- flagsurl0 = config/flags/Example-gcc4x-flags-revA.xml
- flagsurl1 = config/flags/Example-linux-platform-revA.xml
但是最主要的是要检查两个xml文件的内容描述是否覆盖了编译器使用的参数。因为官方的目标是,让你公开尽可能多的细节,以便让别人也能理解你的测试结果,所以,如果你使用了什么编译器参数,需要描述清楚,让别人阅读你测试报告的人也能理解。
在specCPU 2006 1.2版本里面,flags xml 被分离成两个单独的xml文件,一个描述系统平台相关,一个描述编译器参数相关。
对有些参数的描述,不是好确定是属于系统配置描述还是编译参数描述。可以放在任意文件里面。
关于描述系统相关的xml,好像可以增加一些系统相关信息,比如BIOS配置,系统sysctl参数 ulimit,内存页面等相关的说明。从测试报告看,暂时还没出现因为系统描述不完整出现invalid run的情况,所以,如果不是要向spec官网提供测试报告,可以不用管。
关于编译器的参数描述,必须要在flags xml文件里面找到对应的描述。所以需要在这个文件里面增加参数的说明。格式可以参考官网:
Flag Description Files SPEC CPU2006
http://www.spec.org/cpu2006/Docs/flag-description.html#ElementOrderxml的文件结构大致如下:

其中每个xml必须要有的部分
具体的,其实可以打开config/flags/Example-gcc4x-flags-revA.xml这个示例查看,如果我们要自己写一个描述文件,可以复制一份修改,这个文件是描述编译参数的。可以看到前面的文件名,标题,style,都是有的。
关于 标记说明,这是用来让xml里面包含html带<>的标记的比如
xxx
之类主要需要在文件增加如下flag部分格式的内容:
- <flag name="F-Wno-write-strings"
- class="optimization"
- regexp="-Wno-write-strings">
- <![CDATA[
- <p>Supported values for this flag are</p>
- ]]>
- </flag>
- <flag name="F-123"
- class="optimization"
- regexp="-fprefetch-loop-arrays">
- <![CDATA[
- <p>Supported values for this flag are</p>
- ]]>
- </flag>
用于说明编译器参数的含义。上面两段内容增加了2个参数说明,-Wno-write-strings -fprefetch-loop-arrays
关于每一段flag内容的含义,主要包含三个部分 name class regexp
name是为参数说明起名,但名字本身命名还可能推断出regexp部分的内容。这个和regexp正则表达式部分有点关系。
class 有7个类,截图如下,具体放那个class根据具体情况写了。反正绝大部分都是优化class

regexp 正则表达式,这个貌似是perl的正则表达式,如何写的规则先看官网的吧,一般参数就按实际参数原封不动放进去就好了。单对某些有特殊符号的参数还是需要正则表达式来过滤匹配的。
如果name的名字是F- xxx开头,那么可以不写regexp,他默认根据name推断参数就是-xxx,当然也可以像我第二段起名叫F-123,然后写好regexp。
比如有个参数-march=armv8-a+crc+fp+crypto ,直接把这部分放到regexp后面是不行的,=在里面不是字符是特殊含义了。最终我简单研究了下,用-march(?:=\S*) 匹配-march=开头的任意参数了。我的测试只有这个-march=开头的参数,所以无所谓,但如果有多个-march=开头的参数,那么需要单独写匹配。复杂的还是需要稍微花时间看看官网参数如何运用正则表达式。
写完后,可以使用specCPU提供的工具来检查格式和是否有重复描述。
specrxp -s -V ../config/flags/test-gcc931.xml
如果都没问题,那么可以使用这个xml来重新格式化已经跑完的结果。
rawformat --flagsurl ../config/flags/test-gcc931.xml ./CINT2006.063.ref.rsf
这样,会重新生成html或者PDF等测试报告。
XML的其余部分,用到的时候再做记录吧,目前我主要目的就是让他跑出来不要有Invalid run水印了。
配置文件中可用的变量比如CC, CPORTABILITY OPTIMIZE等等,可以参考官网:
makevars (CPU2006)
https://www.spec.org/cpu2006/Docs/makevars.html或者在speccpu的安装目录下也有相同的html页面说明,如果有不清楚某个变量是什么意义,可以查询这个文档,有比较详细的说明。
对于加在配置文件编译变量或者说可移植性参数部分的宏比如-DSPEC_CPU_LINUX ,-DSPEC_CPU_LP64这些 ,最开始我确实是不知道这些参数干嘛用的,后面查询了下,才明白,主要是用于让spec实际的测试代码具有可移植性的,因为speccpu一套代码要适应win linux aix solaris 操作系统,还要适应x86 amd64,power,arm64等各种不同类型的CPU,必须要配置对应的宏,来适应不同的硬件软件组合,实际上,这些宏都有对应的flag.xml进行说明的,可以参考官网
Index of /auto/cpu2006/flags
https://www.spec.org/auto/cpu2006/flags/这个目录下的flags说明文件。或者其实在speccpu目录下grep -r DSPEC_CPU_LINUX 这样区搜,业能搜出来针对这些宏开关的说明的。所以实际上需要我们针对具体的操作系统和CPU来确定配置什么样的宏开关让代码正常且最优运行。
比如下面:
- -DSPEC_CPU_LP64 整数部分是32位,长整型以及指针式64位。
- https://www.spec.org/auto/cpu2006/flags/400.perlbench.flags.html#b400.perlbench_DSPEC_CPU_LP64
-
- -DSPEC_CPU_LINUX 编译的代码是在Linux上执行
- https://www.spec.org/auto/cpu2006/flags/400.perlbench.flags.html#b400.perlbench_DSPEC_CPU_LINUX
可以看出,这些开关都是对CPU或者操作系统类型以及特性做说明。
对gcc的可用参数,直接参考官网就好,比如:
Option Summary (Using the GNU Compiler Collection (GCC))Option Summary (Using the GNU Compiler Collection (GCC))
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Option-Summary.html#Option-Summary关于GCC的FDO基于反馈的导向优化,需要开启的话直接在配置文件中写PASSn_CFLAGS之类的变量,speccpu运行的时候就会使用FDO来优化程序了,大概过程就是先使用插入指令的方式编译程序,然后使用speccpu提供的负载数据来跑(这些负载貌似还不允许人为去更改),然后根据跑的结果再重新编译程序,以提高被测spec程序的测试性能。具体可以参考:
Config files - SPEC CPU2006
https://www.spec.org/cpu2006/docs/config.html#sectionVI官网的说明,关于gcc的FDO优化,估计要深入研究就比较复杂了,看来所谓的调优真的是永无止境啊,对硬件特性以及编译器要很了解,并且要做大量实验才能取得比较好的效果。
这里照抄一段别人的specCPU的FDO参数:
- default=peak:
- PASS1_CFLAGS = -fprofile-generate
- PASS2_CFLAGS = -fprofile-use
- PASS1_CXXFLAGS = -fprofile-generate
- PASS2_CXXFLAGS = -fprofile-use
- PASS1_FFLAGS = -fprofile-generate
- PASS2_FFLAGS = -fprofile-use
- PASS1_LDFLAGS = -fprofile-generate
- PASS2_LDFLAGS = -fprofile-use
应该有少量提升。
gcc 官网关于优化参数的参考文档,除了profile-generate profile-use,还有什么auto-profile,有空再看吧。
其他的关于FDO,简单了解可以参考一些别人的文章看看效果,比如