跳转至

SPEC CPU 2006 性能测试

背景

最近在网上看到龙芯 3A6000 的 SPEC CPU 2006 性能评测数据,想着自己也可以在手上的一些平台上测一测,把测试的过程记录在本文。

基本概念

SPEC CPU 2006 分 int 和 fp 两种,又分不同的模式:

  1. speed:跑单进程,看看单进程多少时间能完成;不开 OpenMP,但是编译器可以自动并行化(ICC)
  2. rate:跑多进程,看看单位时间内能跑多少个任务

根据编译选项的不同,分为:

  1. base:所有测例都用同样的优化选项
  2. peak:不同测例可以用不同的优化选项

安装

首先需要获取一份 cpu2006-1.2.iso 文件,md5 可以在 官网 上查到。在 Linux 环境下,mount 这个 iso 并运行里面的 install.sh:

mount cpu2006-1.2.iso /mnt
cd /mnt
./install.sh

按照提示输入安装路径,等待安装完成,然后按照提示进入环境:

cd /usr/cpu2006
source ./shrc

配置和运行

接着,需要按照 SPEC CPU2006 Config Files 的文档编写配置文件。编辑 config/default.cfg,写一个基本的配置:

# run one iteration
iterations = 1
# skip peak
basepeak = yes
# show live output
teeout = yes

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2
CXXOPTIMIZE = -O2
FOPTIMIZE = -O2

这样就会用单线程跑一个 -O2 优化的 401.bzip2 测例:

runspec bzip2

运行几分钟后,就可以在 result 目录下看到结果,可以看到 bzip2 单项的结果。接下来,尝试运行完整的 SPECint_base2006,修改 config/default.cfg

# match spec result standard
reportable = yes
# skip peak
basepeak = yes
# show live output
teeout = yes

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2
CXXOPTIMIZE = -O2
FOPTIMIZE = -O2

再运行:

runspec int

此时会遇到编译问题,下面来进行解决。

编译错误

编译错误实际上是因为现在用的系统太新了,在新系统上编译 2006 年前的代码,必然有各种问题。

perlbench

遇到的第一个问题是 perlbench:

pp_sys.c:4489:42: error: invalid use of undefined type 'struct tm'
 4489 |                             dayname[tmbuf->tm_wday],
      |                                          ^~

这是因为没有 include time.h,阅读 perlbench 下面的 spec_config.h,可知需要给 perlbench 传单独的编译参数。修改 config/default.cfg,添加如下部分:

# fix compilation
int=default=default=default:
PORTABILITY = -DSPEC_CPU_LP64

400.perlbench=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX_X64

表示给所有测例都加上 SPEC_CPU_LP64 的定义,perlbench 还要额外定义 SPEC_CPU_LINUX_X64。这样 time.h 的问题解决了,接下来遇到了新的问题,链接的时候出现 multiple definition 错误:

Opcode.c:(.text+0x1b60): multiple definition of `ferror_unlocked'; av.o:av.c:(.text+0x2f0): first defined here
collect2: error: ld returned 1 exit status

在网上查找,发现在 SPEC 2017 FAQ 里有解决方案,虽然用的是 CPU 2006,但是也一样适用,修改 config/default.cfg

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2 -fgnu89-inline -fcommon
CXXOPTIMIZE = -O2
FOPTIMIZE = -O2

# fix compilation
int=default=default=default:
PORTABILITY = -DSPEC_CPU_LP64

400.perlbench=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX_X64

libquantum

下一个编译错误在 libquantum:

complex.c: In function 'quantum_conj':
complex.c:42:14: error: 'IMAGINARY' undeclared (first use in this function)
   42 |   return r - IMAGINARY * i;

和 perlbench 一样,需要额外的宏定义。参考 config 目录下的 Example config,直接把剩下几个都配置上:

# fix compilation
int=default=default=default:
PORTABILITY = -DSPEC_CPU_LP64

400.perlbench=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX_X64

462.libquantum=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX

483.xalancbmk=default=default=default:
CXXPORTABILITY = -DSPEC_CPU_LINUX

481.wrf=default=default=default:
CPORTABILITY = -DSPEC_CPU_CASE_FLAG -DSPEC_CPU_LINUX

omnetpp

下一个错误是 specmake 说 CC not found:

CC -c -o EtherAppCli.o -DSPEC_CPU -DNDEBUG -I. -Iomnet_include -Ilibs/envir   -O2   -DSPEC_CPU_LP64 -fgnu89-inline -fcommon       EtherAppCli.cc
specmake: CC: Command not found
specmake: *** [EtherAppCli.o] Error 127

那就在配置 config/default.cfg 里指定绝对路径:

# specify compilers
default=default=default=default:
CC = /usr/bin/gcc
CXX = /usr/bin/g++
FC = /usr/bin/gfortran

gamess

gamess 是 SPECfp 里面的测例,编译的时候报错:

aldeci.fppized.f:1674:72:

 1674 |       CALL BINOM6(X(LIFA),NACT)
      |                                                                        1
Error: Type mismatch in argument 'ifa' at (1); passed REAL(8) to INTEGER(4)

参考 Disable argument-mismatch errors for SPEC CPU2006 416.gamess for GCC >= 8,添加编译选项 -std=legacy 来解决:

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2 -fgnu89-inline -fcommon
CXXOPTIMIZE = -O2
FOPTIMIZE = -O2 -std=legacy

dealII

dealII 是 SPECfp 里面的测例,编译的时候报错:

parameter_handler.cc: In member function 'long int ParameterHandler::get_integer(const std::string&) const':
parameter_handler.cc:763:26: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
  763 |   AssertThrow ((s.c_str()!='\0') || (*endptr == '\0'),
      |                 ~~~~~~~~~^~~~~~
include/base/exceptions.h:596:15: note: in definition of macro 'AssertThrow'
  596 |         if (!(cond))                                                 \
      |               ^~~~

编译选项打开 -fpermissive 即可:

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2 -fgnu89-inline -fcommon
CXXOPTIMIZE = -O2 -fpermissive
FOPTIMIZE = -O2 -std=legacy

soplex

soplex 是 SPECfp 里面的测例,编译的时候报错:

mpsinput.cc: In member function 'bool soplex::MPSInput::readLine()':
mpsinput.cc:75:52: error: no match for 'operator==' (operand types are 'std::basic_istream<char>::__istream_type' {aka 'std::basic_istream<char>'} and 'int')
   75 |          if (m_input.getline(m_buf, sizeof(m_buf)) == 0)
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~
      |                             |                         |
      |                             |                         int
      |                             std::basic_istream<char>::__istream_type {aka std::basic_istream<char>}

解决办法:降低 C++ 标准版本:

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2 -fgnu89-inline -fcommon
CXXOPTIMIZE = -O2 -fpermissive --std=c++98
FOPTIMIZE = -O2 -std=legacy

完整配置

解决编译问题后,完整配置如下:

# match spec result standard
reportable = yes
# skip peak
basepeak = yes
# show live output
teeout = yes

# optimization flags for base
default=base=default=default:
COPTIMIZE = -O2 -fgnu89-inline -fcommon
CXXOPTIMIZE = -O2 -fpermissive --std=c++98
FOPTIMIZE = -O2 -std=legacy

# specify compilers
default=default=default=default:
CC = /usr/bin/gcc
CXX = /usr/bin/g++
FC = /usr/bin/gfortran

# fix compilation
int=default=default=default:
PORTABILITY = -DSPEC_CPU_LP64

400.perlbench=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX_X64

462.libquantum=default=default=default:
CPORTABILITY = -DSPEC_CPU_LINUX

483.xalancbmk=default=default=default:
CXXPORTABILITY = -DSPEC_CPU_LINUX

481.wrf=default=default=default:
CPORTABILITY = -DSPEC_CPU_CASE_FLAG -DSPEC_CPU_LINUX

此时再运行 runspec int 就可以正常跑了。

其他 ISA

如果想在 AArch64 上跑,那么安装的时候会发现缺少 prebuilt 的 tools 二进制,此时就要手动按照 Building the SPEC CPU2006 Tool Suite 进行编译:

cd tools/src
./buildtools

需要注意,这一步需要修改文件系统,所以如果之前是直接 mount ISO,要先复制一份,此外还要把权限改成可写(chmod -R u+w)。

运行的时候会遇到错误,可以参考 Build SPEC CPU2006 in riscv64 linux 解决,riscv64 和 aarch64 的解决方法是类似的:

  1. 替换源代码下的几个 config.guess 和 config.sub(在 expat-2.0.1/conftools,make-3.82/config,rxp-1.5.0,specinvoke,specsum/build-aux,tar-1.25/build-aux,xz-5.0.0/build-aux 目录下),解决不认识 aarch64 target triple 的问题

    wget -O config.guess 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD'
    wget -O config.sub 'https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD'
    cp config.* expat-2.0.1/conftools/
    cp config.* make-3.82/config/
    cp config.* rxp-1.5.0/
    cp config.* specinvoke/
    cp config.* specsum/build-aux/
    cp config.* tar-1.25/build-aux/
    cp config.* xz-5.0.0/build-aux/
    
  2. 修改 make-3.82/glob/glob.c,把 # if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION 改成 # if _GNU_GLOB_INTERFACE_VERSION >= GLOB_INTERFACE_VERSION,禁用 make 自带的 glob 实现,解决 alloca 和 stat 的问题

    @@ -52,7 +52,7 @@
     #define GLOB_INTERFACE_VERSION 1
     #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
     # include <gnu-versions.h>
    -# if _GNU_GLOB_INTERFACE_VERSION == GLOB_INTERFACE_VERSION
    +# if _GNU_GLOB_INTERFACE_VERSION >= GLOB_INTERFACE_VERSION
     #  define ELIDE_CODE
     # endif
     #endif
    
  3. 修改 make-3.82/make.h,在 struct rlimit stack_limit; 前面添加 extern,解决 -fno-common 的问题

    @@ -344,7 +344,7 @@
     #endif
     #ifdef SET_STACK_SIZE
     # include <sys/resource.h>
    -struct rlimit stack_limit;
    +extern struct rlimit stack_limit;
     #endif
    
     struct floc
    
  4. 修改 make-3.82/dir.c,在 dir_setup_glob 函数里添加一句 gl->gl_lstat = lstat;,解决 make: ./file.c:158: enter_file: Assertion strcache_iscached (name) failed. 的问题(参考了 [PATCH v2] make: 4.2.1 -> 4.3

    @@ -1213,6 +1213,7 @@
       gl->gl_readdir = read_dirstream;
       gl->gl_closedir = ansi_free;
       gl->gl_stat = local_stat;
    +  gl->gl_lstat = lstat;
       /* We don't bother setting gl_lstat, since glob never calls it.
          The slot is only there for compatibility with 4.4 BSD.  */
     }
    
  5. 修改 tar-1.25/gnu/stdio.in.hspecsum/gnulib/stdio.in.h,找到 _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead"); 一句,注释掉,解决 gets undefined 的问题(参考了 CentOS 下 Git 升级

    @@ -159,7 +159,7 @@
        so any use of gets warrants an unconditional warning.  Assume it is
        always declared, since it is required by C89.  */
     #undef gets
    -_GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
    +// _GL_WARN_ON_USE (gets, "gets is a security hole - use fgets instead");
    
     #if @GNULIB_FOPEN@
     # if @REPLACE_FOPEN@
    
  6. 修改 buildtools,在 perl 的 configure 命令中的 -A ldflags 附近,把 -A libs=-lm -A ccflags=-fwrapv 添加到命令中,解决找不到 math 函数的问题和 numconvert.t 测试失败的问题(参考 https://serverfault.com/a/801997/323597如何在 Hifive Unmatched 开发板上安装 SPEC CPU 2006):

    @@ -355,7 +355,7 @@
         LD_LIBRARY_PATH=`pwd`
         DYLD_LIBRARY_PATH=`pwd`
         export LD_LIBRARY_PATH DYLD_LIBRARY_PATH
    -    ./Configure -dOes -Ud_flock $PERLFLAGS -Ddosuid=undef -Dprefix=$INSTALLDIR -Dd_bincompat3=undef -A ldflags=-L${INSTALLDIR}/lib -A ccflags=-I${INSTALLDIR}/include -Ui_db -Ui_gdbm -Ui_ndbm -Ui_dbm -Uuse5005threads ; testordie "error configuring perl"
    +    ./Configure -dOes -Ud_flock $PERLFLAGS -Ddosuid=undef -Dprefix=$INSTALLDIR -Dd_bincompat3=undef -A libs=-lm -A ccflags=-fwrapv -A ldflags="-L${INSTALLDIR}/lib" -A ccflags="-I${INSTALLDIR}/include -g" -Ui_db -Ui_gdbm -Ui_ndbm -Ui_dbm -Uuse5005threads ; testordie "error configuring perl"
         $MYMAKE; testordie "error building Perl"
         ./perl installperl; testordie "error installing Perl"
         setspecperllib
    
  7. 修改 perl-5.12.3/Configure,把判断 GCC 版本的 1* 都改成 1.*,解决 miniperl Segmentation fault 的问题(参考 unmatched(riscv64) 上编译,安装和移植 SPEC CPU 2006

    @@ -4536,7 +4536,7 @@
     fi
     $rm -f try try.*
     case "$gccversion" in
    -1*) cpp=`./loc gcc-cpp $cpp $pth` ;;
    +1.*) cpp=`./loc gcc-cpp $cpp $pth` ;;
     esac
     case "$gccversion" in
     '') gccosandvers='' ;;
    @@ -5128,7 +5140,7 @@
     case "$hint" in
     default|recommended)
            case "$gccversion" in
    -       1*) dflt="$dflt -fpcc-struct-return" ;;
    +       1.*) dflt="$dflt -fpcc-struct-return" ;;
            esac
            case "$optimize:$DEBUGGING" in
            *-g*:old) dflt="$dflt -DDEBUGGING";;
    @@ -5143,7 +5155,7 @@
                    ;;
            esac
            case "$gccversion" in
    -       1*) ;;
    +       1.*) ;;
            2.[0-8]*) ;;
            ?*)     set strict-aliasing -fno-strict-aliasing
                    eval $checkccflag
    @@ -5245,7 +5257,7 @@
     *)  cppflags="$cppflags $ccflags" ;;
     esac
     case "$gccversion" in
    -1*) cppflags="$cppflags -D__GNUC__"
    +1.*) cppflags="$cppflags -D__GNUC__"
     esac
     case "$mips_type" in
     '');;
    
  8. 修改 perl-5.12.3/Configure,在 if $ok; then 后面加上如下代码,解决 magic.t 测试失败的问题(参考 如何在 Hifive Unmatched 开发板上安装 SPEC CPU 2006Tests fail with GCC 5.0 because Errno cannot obtain errno constants):

    elif echo 'Maybe "'"$cc"' -E -ftrack-macro-expansion=0" will work...'; \
           $cc -E -ftrack-macro-expansion=0 <testcpp.c >testcpp.out 2>&1; \
           $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
           echo "Yup, it does."
           x_cpp="$cc $cppflags -E -ftrack-macro-expansion=0"
           x_minus='';
    elif echo 'Maybe "'"$cc"' -E -ftrack-macro-expansion=0 -" will work...';
           $cc -E -ftrack-macro-expansion=0 - <testcpp.c >testcpp.out 2>&1; \
           $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
           echo "Yup, it does."
           x_cpp="$cc $cppflags -E -ftrack-macro-expansion=0"
           x_minus='-';
    
    @@ -4688,6 +4688,18 @@
    
     if $ok; then
            : nothing
    +elif echo 'Maybe "'"$cc"' -E -ftrack-macro-expansion=0" will work...'; \
    +       $cc -E -ftrack-macro-expansion=0 <testcpp.c >testcpp.out 2>&1; \
    +       $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
    +       echo "Yup, it does."
    +       x_cpp="$cc $cppflags -E -ftrack-macro-expansion=0"
    +       x_minus='';
    +elif echo 'Maybe "'"$cc"' -E -ftrack-macro-expansion=0 -" will work...';
    +       $cc -E -ftrack-macro-expansion=0 - <testcpp.c >testcpp.out 2>&1; \
    +       $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
    +       echo "Yup, it does."
    +       x_cpp="$cc $cppflags -E -ftrack-macro-expansion=0"
    +       x_minus='-';
     elif echo 'Maybe "'"$cc"' -E" will work...'; \
            $cc -E <testcpp.c >testcpp.out 2>&1; \
            $contains 'abc.*xyz' testcpp.out >/dev/null 2>&1 ; then
    
  9. 修改 TimeDate-1.20/t/getdate.tmy $offset = Time::Local::timegm(0,0,0,1,0,70);my $offset = Time::Local::timegm(0,0,0,1,0,1970);,解决 error running TimeDate-1.20 test suite 报错(参考 unmatched(riscv64) 上编译,安装和移植 SPEC CPU 2006):

    @@ -156,7 +156,7 @@
    !;
    
    require Time::Local;
    -my $offset = Time::Local::timegm(0,0,0,1,0,70);
    +my $offset = Time::Local::timegm(0,0,0,1,0,1970);
    
    @data = split(/\n/, $data);
    

这样就可以正常完成 ./buildtools 了,中间 perl 测试出错,按 y 忽略即可。

编译完成以后,回到复制后的 ISO 根目录进行打包,打包完正常安装即可:

source shrc
packagetools linux-aarch64
export SPEC_INSTALL_NOCHECK=1
./install.sh -d /install/path

添加 export SPEC_INSTALL_NOCHECK=1 环境变量是因为修改了源码,md5 对不上,所以要跳过校验。

实测上述步骤在 POWER8 ppc64le 和 LoongArch64 上也可以成功。

在 AArch64 或者 PPC64LE 上跑 SPEC 的时候,可能会遇到 Miscompare #7,在编译选项里加上 -fsigned-char 即可:

# fix compilation and miscompare
int=default=default=default:
PORTABILITY = -DSPEC_CPU_LP64 -fsigned-char

自己测的数据

因为 GCC 没有自动并行化,所以都是单核运行。跑一次测试要 5000+/17000+ 秒,运行时间基本和分数成反比,乘积按 400000 估算。

实测在 -Ofast 编译选项下,SPECfp 里的 gamess 和 bwaves 会失败,改成 -O3/-O2/-O1 以后 gamess 依然失败,只有不开 -O 或者 -O0 才能跑通 gamess。所以就不测 SPECfp 了,只测 SPECint。

下面贴出自己测的数据(SPECint2006,Estimated,speed,base),不保证满足 SPEC 的要求,仅供参考。

  • i9-13900K Raptor Lake(-O2): 79.6
  • i9-13900K Raptor Lake(-Ofast -fomit-frame-pointer -march=native -mtune=native): 85.3 86.8
  • i9-10980XE Cascade Lake(-O2): 43.9
  • E5-2680 v3 Haswell(-O2): 33.2
  • POWER8NVL(-O2): 26.5
  • Kunpeng 920 TaiShan V110(-O2): 23.3
  • Kunpeng 920 TaiShan V110(-Ofast -fomit-frame-pointer -march=native -mtune=native): 24.5

网上的数据

Speed(SPECint2006)

只考虑单核,不考虑 ICC 的自动多线程并行化。

Anandtech 的数据

  • i9-10900K Comet Lake: 58.76
  • R9 3950X Zen 2: 50.02
  • R7 4800U Zen 2: 37.10
  • Amazon Graviton 2 Neoverse-N1: 29.99

Anandtech 的数据

  • Apple M1: 69.40
  • R9 5950X Zen 3: 68.53
  • Apple A14: 63.34
  • i9-10900K Comet Lake: 58.58
  • Apple A13: 52.83
  • R9 3950X Zen 2: 50.10
  • R7 2700X Zen+: 39.01

Anandtech 的数据

  • EPYC 7742 Zen 2: 39.25
  • EPYC 7601 Zen 1: 31.45

Baikal 的数据:

  • Baikal-S:19
  • Kunpeng 920: 26

龙芯 3A6000 新闻

  • Loongson 3A6000: 43.1

龙芯 3A6000:

  • Loongson 3A6000: 43.1
  • Intel Core i3-10100: 42.5
  • Hygon 3250: 39
  • Kirin 990: 26.4
  • Zhaoxin KX6780A: 20.5
  • Phytium FT-D2000: 15.4
  • Pangu M900: 12.4

在龙芯 3A5000 上测试 SPEC CPU 2006:

  • Loongson 3A5000: 26.6

龙芯、海光、飞腾、兆芯同桌对比性能力求公平:

  • Intel i9-10850K: 62.5
  • AMD R5 5600G: 48.2 59.9
  • AMD R5 2600: 36.1 40.5
  • Intel i5-6500: 40.1
  • Hygon C86 3250: 30.5
  • Loongson 3A5000HV: 26.5
  • Zhaoxin KX-U6780A: 15.5
  • Phytium D2000: 15.3

Rate(SPECint_rate2006)

Kunpeng 920 官方数据

  • Kunpeng 920 64 Cores: >930

夏晶的数据

  • AMD Zen 2 64 Cores: ~1200
  • Intel Skylake 8180 v5 28 Cores: ~750
  • Cavium TX2 32 Cores: ~750
  • AMD Zen 1 7601 32 Cores: ~700
  • Qualcomm 2400 48 Cores: ~650
  • Phytium FT2000 64 Cores: ~600
  • Intel Skylake 6148 v5 20 Cores: ~550

龙芯 3A6000 新闻

  • Loongson 3A6000 4C 8T: 155

龙芯、海光、飞腾、兆芯同桌对比性能力求公平:

  • Intel i9-10850K 10C 20T: 328 349
  • AMD R5 5600G 6C 12T: 192 232 235 278
  • AMD R5 2600 6C 12T: 166 179 192 199
  • Hygon C86 3250 8C 16T: 173 197
  • Intel i5-6500 4C: 113
  • Phytium D2000 8C: 90.2
  • Zhaoxin KX-U6780A 8C: 82.9
  • Loongson 3A5000HV 4C: 81.2

评论