PARSEC 3.0 编译报错
Lapin Gris Lv3

PARSEC 3.0(Parallel Applications Research for System Efficiency Collectio)是一个基准测试套件,用于评估多核处理器和系统的性能,也就是跑分软件。

工作中需要使用到这个软件作为基准测试软件,因为 PARSEC 从官网下载下来是不能直接运行的,所以有了下面适配 RHEL 9 操作系统的内容。
文章末尾有所有修改的 patches 文件,里面记录详细的修改地方。

安装 PARSEC 3.0

# Full PARSEC 3.0 tarball
wget http://parsec.cs.princeton.edu/download/3.0/parsec-3.0.tar.gz

tar xvf parsec-3.0.tar.gz
cd parsec-3.0

# 编译
source env.sh
parsecmgmt -a build

编译错误合集

error: ISO C++17 does not allow dynamic exception specifications

Thread.h:62:24: error: ISO C++17 does not allow dynamic exception specifications
62 | Thread(Runnable &) throw(ThreadCreationException);

在 C++17 标准中,将动态异常规范(Dynamic Exception Specification)声明为废弃(deprecated),也就是不推荐使用。在 RHEL 9 操作系统上默认的 C++ 标准是 17。所以会遇到这个编译报错,我们只需要使用老版本的 C++ 标准来编译代码可以规避这个问题。

config/gcc.bldconf

# Arguments to use
export CFLAGS=" -O3 -g -funroll-loops -fprefetch-loop-arrays -std=gnu11 ${PORTABILITY_FLAGS}"
export CXXFLAGS="-O3 -g -funroll-loops -fprefetch-loop-arrays -fpermissive -fno-exceptions -std=gnu++11 ${PORTABILITY_FLAGS}"

在 gcc.bldconf 里指明让 gcc 使用 gnu11/gnu++11 标准编译代码。

这里没有使用 c11、c++11 标准而是使用 gnu 版本实现的 C、C++ 标准。
如果使用 c11/c++11 标准,会遇到这个报错 warning: implicit declaration of function 'strdup' gcc 编译器会申明 这个宏—— “STRICT_ANSI“,代表只使用 c11、 spec 里的标准 C 库。这会导致我们经常使用的一些像 strdup 这些库函数不能使用(parsec3 用到了这些库函数)

error: looser exception specification on overriding virtual function


WorkerGroup.h:88:5: error: looser exception specification on overriding virtual function 'virtual threads::WorkerGroup::~WorkerGroup() throw (threads::CondException, threads::MutexException)'
88 | ~WorkerGroup();

这个错误意思是子类 override 父类的虚函数时候,子类的异常规范比父类更宽松(looser),也就是说子类的异常规范允许抛出更多类型的异常,这与 C++ 的异常规范要求相违背。所以,我们要让子类的异常更严格,而不是更宽容。

// WorkerGroup.h
- ~WorkerGroup();
+ ~WorkerGroup() throw();

显式指示不抛出异常即可。或者用 noexcept 也行。

multiple definition

/usr/bin/ld: encoder.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/encoder.c:65: multiple definition of `conf'; dedup.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/dedup.c:25: first defined here
/usr/bin/ld: decoder.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/decoder.c:39: multiple definition of `conf'; dedup.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/dedup.c:25: first defined here
/usr/bin/ld: decoder.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/decoder.c:42: multiple definition of `cache'; encoder.o:/root/parsec-3.0/pkgs/kernels/dedup/obj/amd64-linux.gcc/encoder.c:68: first defined here

gcc 10 后,默认使能了 -fno-common 选项,编译器检查更加严格了 https://gcc.gnu.org/gcc-10/porting_to.html。最简单的办法是,rollback(指定使用 -fcommon 编译代码即可)

mismatched comparison between std::ifstream and int

FILE_UTILITIES.h:83:49: error: no match for ‘operator!=’ (operand types are ‘std::ofstream’ {aka ‘std::basic_ofstream<char>’} and ‘int’)
83 | return std::ofstream (filename.c_str()) != 0;
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~ ~
| | |
| | int
| std::ofstream {aka std::basic_ofstream<char>}

std::ofstream 和 int 之间无法直接比较,需要强转,举个栗子,

// FILE_UTILITIES.h

- return std::ifstream (filename.c_str()) != 0;
+ return (bool)std::ifstream (filename.c_str()) != 0;

error: ‘HUGE’ undeclared

LSH_query.c:361:34: error: ‘HUGE’ undeclared (first use in this function)
361 | TOPK_INIT(topk, dist, K, HUGE);

没有定义 HUGE 宏。我们将 C 数学库里的 HUGE_VAL 定义为 HUGE即可,#define HUGE HUGE_VAL

conflicting type __mbstate_t, both provided by glibc and parsec lib

/usr/include/bits/types/__mbstate_t.h:21:3: error: conflicting types for ‘__mbstate_t’; have ‘struct <anonymous>’
21 | } __mbstate_t;

C 库和 parsec 库同时提供了 __mbstate_t 的定义,二者冲突了,将 parsec 库提供的定义重命名。

POD document had syntax errors

smime.pod around line 272: Expected text after =item, not a number
smime.pod around line 276: Expected text after =item, not a number
smime.pod around line 280: Expected text after =item, not a number
smime.pod around line 285: Expected text after =item, not a number
smime.pod around line 289: Expected text after =item, not a number
POD document had syntax errors at /usr/bin/pod2man line 69.
make: *** [Makefile:681: install_docs] Error 255

提示POD doc 有语法错误,应该是软件升级,语法变了导致的。使用下面的脚本一键修正过来就好了,

#! /bin/bash
for i in 0 1 2 3 4 5 6 7 8 9
do
echo "Replacing '=item $i' to '=item C<$i>'"
grep -rl "=item $i" * | xargs sed -i "s/=item $i/=item C<$i>/g"
done

PATCHES

1、fix-error-looser-exception-specification-on-overridi.patch
2、use-gnu11-gnu-11-std-to-build-parsec.patch
3、fix-multiple-definition-when-build-with-gcc-10-or-ab.patch
4、fix-A-mismatched-comparison-between-std-ifstream-and.patch
5、fix-HUGE-macro-undeclared-error.patch
6、fix-conflicting-type-__mbstate_t-both-provided-by-gl.patch
7、fix-POD-document-had-syntax-errors.patch