Embench
EMBench
快速开始
==注意:该教程的前置条件为安装riscv32-gnu工具链,python3.6+环境,qemu-riscv32环境。==
第一步:
git clone https://github.com/embench/embench-iot.git && cd embench-iot
第二步:
# -lm用于加载数学库,请确保riscv32-gnu工具链在系统PATH中
# 速度基准(使用gcc与imc扩展)
rm -rf bd/ && ./build_all.py \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc riscv32-unknown-elf-gcc \
--cflags="-c -O2 -ffunction-sections -march=rv32imc -mabi=ilp32" \
--ldflags="-Wl,-gc-sections" \
--user-libs="-lm"
# 代码大小基准(使用clang与imc扩展)
rm -rf bd/ && ./build_all.py \
--verbose \
--timeout 30 \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc /home/yangz/llvm/build/bin/clang \
--cflags="--target=riscv32 -static -c -Os -ffunction-sections -march=rv32imc -mabi=ilp32" \
--ld /home/yangz/llvm/build/bin/ld.lld \
--ldflags="-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib" \
--user-libs="/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib/crt0.o"
# 代码大小基准(使用clang与imfdc扩展)
rm -rf bd/ && ./build_all.py \
--verbose \
--timeout 60 \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc /home/yangz/llvm/build/bin/clang \
--cflags="--target=riscv32 -static -c -Os -ffunction-sections -march=rv32imfdc -mabi=ilp32d" \
--ld /home/yangz/llvm/build/bin/ld.lld \
--ldflags="-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/data/liuf/bisheng17/llvm-project/build/lib/clang-runtimes/riscv32/lib" \
--user-libs="/data/liuf/24bm/riscv32/lib/crt0.o"
# 交叉gcc+lld
rm -rf bd/ && ./build_all.py \
--timeout 20 \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc riscv32-unknown-elf-gcc \
--cflags="-c -Os -ffunction-sections -march=rv32imc -mabi=ilp32" \
--ld /home/yangz/llvm/build/bin/ld.lld \
--ldflags="-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib -L/data/riscv32/riscv32-unknown-elf/lib" \
--user-libs="/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib/crt0.o"
# 代码大小基准(使用gcc)
rm -rf bd/ && ./build_all.py \
--verbose \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc riscv32-unknown-elf-gcc \
--cflags="-c -Os -ffunction-sections -march=rv32imc -mabi=ilp32" \
--ldflags="-O2 -Wl,-gc-sections" \
--user-libs="-lm"
# 代码大小基准(使用gcc与imfdc扩展)
rm -rf bd/ && ./build_all.py \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc /opt/riscv/bin/riscv32-unknown-elf-gcc \
--cflags="-c -Os -ffunction-sections -march=rv32imfdc -mabi=ilp32d" \
--ldflags="-L/opt/riscv/riscv32-unknown-elf/lib -Wl,-gc-sections" \
--user-libs="-lm -lc -lgcc"
########## 最新环境
rm -rf bd/ && ./build_all.py \
--verbose \
--timeout 60 \
--arch riscv32 \
--chip generic \
--board ri5cyverilator \
--cc /data/yangz/bs17/build/bin/clang \
--cflags="--target=riscv32 -static -c -Os -ffunction-sections -march=rv32imfdc -mabi=ilp32d" \
--ld /data/yangz/bs17/build/bin/ld.lld \
--ldflags="-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib" \
--user-libs="/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib/crt0.o"
第三步:测试CodeSize:
# 默认:查看基于基准的优化分数(text段)
./benchmark_size.py
# 可选:查看绝对文件体积大小
./benchmark_size.py \
--format=elf \
--absolute \
--metric text rodata data bss
# 可选:查看相对文件体积分数
./benchmark_size.py \
--format=elf \
--relative \
--metric text rodata data bss
# 可选:以JSON形式输出各段大小信息
./benchmark_size.py \
--format=elf \
--metric text rodata data bss \
--baseline-output
第四步:测试运行时间(需要搭建虚拟环境)
# 搭建环境
cd /data
wget http://plct.zdlgv5.com/riscv32_extlib.tar.gz
tar -xzvf riscv32_extlib.tar.gz
export PATH=$PATH:./riscv32/bin
riscv32-unknown-linux-gnu-gcc -v
DIR=/data/yangz
mkdir -p $DIR/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > $DIR/bin/repo
chmod a+x $DIR/bin/repo
echo 'export PATH=$DIR/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
echo 'export PATH=$DIR/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
cd $DIR
mkdir riscv-yocto && cd riscv-yocto
repo init -u git://github.com/riscv/meta-riscv -b master -m tools/manifests/riscv-yocto.xml
repo sync
repo start work --all
# 默认:查看基于基准的运行分数
./benchmark_speed.py
# 可选:查看绝对运行时间
介绍
Embench 是一个为嵌入式系统设计的开源基准测试套件,旨在衡量嵌入式处理器的性能。与传统的基准测试(如 SPEC 或 CoreMark)不同,Embench 更加关注实际的嵌入式应用场景,提供了一组基于现实世界应用的测试,反映嵌入式处理器在实际应用中的表现。Embench 的开发初衷是为没有操作系统支持的裸机系统提供衡量标准,它被设计为硬件无关、可扩展且能够生成符合嵌入式系统特性的结果。
Embench 的主要特点:
- 现实世界的工作负载: Embench 包含多个基于真实应用的基准测试,而不仅仅是合成的测试负载。这使得其更适合评估嵌入式处理器在实际应用中的表现。测试范围涵盖了常见的嵌入式任务,如压缩、图像处理、加密、数学运算等。
- 针对嵌入式系统优化: Embench 专门为资源受限的嵌入式系统设计,考虑了内存、功耗等关键因素。它适合运行在不依赖操作系统的处理器上,并且不会产生过度的代码膨胀或不必要的性能开销。
- 硬件无关: Embench 可以在任何支持 C 编译器的处理器架构上运行。它对硬件没有特别的要求,提供了跨平台的性能比较能力。典型的目标处理器包括 RISC-V、ARM、MIPS 等。
- 可测量性能的多维指标: 除了传统的运行时间,Embench 还评估了代码大小(内存占用)、性能功耗(电量消耗),并为处理器性能提供多个角度的分析。这些指标对嵌入式应用至关重要。
- 开源且可扩展: Embench 是一个开源项目,开发者可以根据需要添加新的测试集成,或者修改现有测试。它灵活可定制,能够满足不同的评估需求。
环境
- Python3.6+
- pyelftools(pip安装)
配置
- RISC-V:直接使用默认的开发板和芯片信息即可。详情参考:https://github.com/embench/embench-iot/blob/master/doc/README.md
- ARM:【等待大家补充】
- 构建参数(build_all.py):请使用./build_all.py –help
坑
bd要及时删除,多重定义问题,lm库问题
附录A:CodeSize运行脚本
%%注意::需要自己配路径和库,版本:Python3.8%%
import os
import re
import subprocess
import csv
# 定义测试参数,按照表头的顺序排列
COMPILER_OPTIONS = [
"gcc O0 rv32imc",
"gcc O1 rv32imc",
"gcc O2 rv32imc",
"gcc O3 rv32imc",
"gcc Os rv32imc",
"llvm O0 rv32imc",
"llvm O1 rv32imc",
"llvm O2 rv32imc",
"llvm O3 rv32imc",
"llvm Os rv32imc",
"gcc O0 rv32imfdc",
"gcc O1 rv32imfdc",
"gcc O2 rv32imfdc",
"gcc O3 rv32imfdc",
"gcc Os rv32imfdc",
"llvm O0 rv32imfdc",
"llvm O1 rv32imfdc",
"llvm O2 rv32imfdc",
"llvm O3 rv32imfdc",
"llvm Os rv32imfdc"
]
# 编译器路径
GCC_CC_IMC = "riscv32-unknown-elf-gcc"
GCC_CC_IMFDC = "/opt/riscv/bin/riscv32-unknown-elf-gcc"
LLVM_CC = "/data/yangz/bs17/build/bin/clang"
LLVM_LD = "/data/yangz/bs17/build/bin/ld.lld"
# 其他编译参数
GCC_CFLAGS_BASE = "-c -ffunction-sections"
LLVM_CFLAGS_BASE = "--target=riscv32 -static -c -ffunction-sections"
# 结果文件
OUTPUT_CSV_TEXT = "benchmark_results_text.csv"
OUTPUT_CSV_ALL = "benchmark_results_all.csv"
# benchmark_size.py 脚本路径
SIZE_SCRIPT = "./benchmark_size.py"
# 初始化 CSV 文件,写入表头
headers = ["Benchmark"] + [f"{opt}" for opt in COMPILER_OPTIONS]
with open(OUTPUT_CSV_TEXT, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
with open(OUTPUT_CSV_ALL, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
# 初始化 benchmark 列表
benchmarks = [
"aha-mont64", "crc32", "cubic", "edn", "huffbench", "matmult-int", "minver",
"md5sum", "nbody", "nettle-aes", "nettle-sha256", "nsichneu", "picojpeg",
"primecount", "qrduino", "sglib-combined", "slre", "st", "tarfind",
"statemate", "ud", "wikisort"
]
# 初始化 CSV 文件中基准测试名称行
def init_benchmark_rows(file_path):
with open(file_path, 'a', newline='') as csvfile:
writer = csv.writer(csvfile)
for benchmark in benchmarks:
writer.writerow([benchmark] + [""] * (len(COMPILER_OPTIONS)))
# 添加几何统计行
writer.writerow(["Geometric mean"] + [""] * (len(COMPILER_OPTIONS)))
writer.writerow(["Geometric SD"] + [""] * (len(COMPILER_OPTIONS)))
writer.writerow(["Geometric range"] + [""] * (len(COMPILER_OPTIONS)))
init_benchmark_rows(OUTPUT_CSV_TEXT)
init_benchmark_rows(OUTPUT_CSV_ALL)
# 保存结果到 CSV 文件的相应列
def save_result(benchmark, size, column_name, csv_file):
with open(csv_file, 'r') as file:
rows = list(csv.reader(file))
for row in rows:
if row[0] == benchmark:
row[column_name] = size
with open(csv_file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerows(rows)
# 运行基准测试并保存数据
def run_benchmark(compiler, opt_level, arch, metrics, output_csv, column_index):
# 构建编译器、编译标志和链接标志等
if compiler == "gcc":
if arch == "rv32imc":
cc = GCC_CC_IMC
cflags = f"{GCC_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32"
ldflags = "-Wl,-gc-sections"
user_libs = "-lm"
elif arch == "rv32imfdc":
cc = GCC_CC_IMFDC
cflags = f"{GCC_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32d"
ldflags = "-L/opt/riscv/riscv32-unknown-elf/lib -Wl,-gc-sections"
user_libs = "-lm -lc -lgcc"
elif compiler == "llvm":
cc = LLVM_CC
ld = LLVM_LD
if arch == "rv32imc":
cflags = f"{LLVM_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32"
ldflags = "-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib"
user_libs = "/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib/crt0.o"
elif arch == "rv32imfdc":
cflags = f"{LLVM_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32d"
ldflags = "-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib"
user_libs = "/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib/crt0.o"
# 打印当前的测试配置
print("-----------------------------------")
print(f"Running configuration:\nCompiler = {compiler}\nOptimization Level = {opt_level}\nArchitecture Extension = {arch}")
print(f"CC = {cc}\nCFLAGS = {cflags}\nLDFLAGS = {ldflags}\nUSER_LIBS = {user_libs}\nMetrics = {metrics}")
print("-----------------------------------")
# 清理之前的构建目录
os.system("rm -rf bd/")
# 构建命令
if compiler == "gcc":
cmd = f"./build_all.py --timeout=60 --arch=riscv32 --chip=generic --board=ri5cyverilator --cc=\"{cc}\" --cflags=\"{cflags}\" --ldflags=\"{ldflags}\" --user-libs=\"{user_libs}\""
else:
cmd = f"./build_all.py --timeout=60 --arch=riscv32 --chip=generic --board=ri5cyverilator --cc=\"{cc}\" --ld=\"{ld}\" --cflags=\"{cflags}\" --ldflags=\"{ldflags}\" --user-libs=\"{user_libs}\""
print(f"\nRunning command:\n{cmd}\n")
subprocess.run(cmd, shell=True)
# 提取指标
print(f"Running benchmark_size.py with metrics: {metrics}...")
try:
size_output = subprocess.check_output(f"python3 {SIZE_SCRIPT} --format=elf --absolute --metric {metrics}", shell=True, text=True)
except subprocess.CalledProcessError:
print(f"Error: benchmark_size.py failed for {compiler} {opt_level} {arch}")
return
# 打印输出,调试用
print(f"SIZE_OUTPUT: {size_output}")
# 提取基准测试的大小信息,并保存到 CSV
for line in size_output.splitlines():
if any(b in line for b in benchmarks):
parts = line.split()
benchmark = parts[0]
size = parts[1].replace(',', '') # 去掉逗号
save_result(benchmark, size, column_index, output_csv)
print(f"Saved result: {benchmark},{compiler} {opt_level} {arch} = {size}")
# 使用正则表达式提取几何统计信息
geometric_mean = re.search(r"Geometric mean\s+([0-9.,]+)", size_output)
geometric_sd = re.search(r"Geometric SD\s+([0-9.,]+)", size_output)
geometric_range = re.search(r"Geometric range\s+([0-9.,]+)", size_output)
# 检查正则表达式匹配结果并保存数据
if geometric_mean:
save_result("Geometric mean", geometric_mean.group(1).replace(',', ''), column_index, output_csv)
else:
print(f"Warning: Geometric mean not found or incorrect format for {compiler} {opt_level} {arch}")
if geometric_sd:
save_result("Geometric SD", geometric_sd.group(1).replace(',', ''), column_index, output_csv)
else:
print(f"Warning: Geometric SD not found or incorrect format for {compiler} {opt_level} {arch}")
if geometric_range:
save_result("Geometric range", geometric_range.group(1).replace(',', ''), column_index, output_csv)
else:
print(f"Warning: Geometric range not found or incorrect format for {compiler} {opt_level} {arch}")
# 循环测试所有组合
for index, option in enumerate(COMPILER_OPTIONS):
compiler, opt, arch = option.split()
# 运行 text 指标的测试,并立即保存结果
run_benchmark(compiler, opt, arch, "text", OUTPUT_CSV_TEXT, index + 1)
# 运行 text rodata data bss 指标的测试,并立即保存结果
run_benchmark(compiler, opt, arch, "text rodata data bss", OUTPUT_CSV_ALL, index + 1)
print(f"All benchmarks completed. Results saved to {OUTPUT_CSV_TEXT} and {OUTPUT_CSV_ALL}.")
运行时间为3分25秒左右
附录B:运行时间脚本
import os
import re
import subprocess
import csv
# 定义测试参数,按照表头的顺序排列
COMPILER_OPTIONS = [
"gcc O0 rv32imc",
"gcc O1 rv32imc",
"gcc O2 rv32imc",
"gcc O3 rv32imc",
"gcc Os rv32imc",
"llvm O0 rv32imc",
"llvm O1 rv32imc",
"llvm O2 rv32imc",
"llvm O3 rv32imc",
"llvm Os rv32imc",
"gcc O0 rv32imfdc",
"gcc O1 rv32imfdc",
"gcc O2 rv32imfdc",
"gcc O3 rv32imfdc",
"gcc Os rv32imfdc",
"llvm O0 rv32imfdc",
"llvm O1 rv32imfdc",
"llvm O2 rv32imfdc",
"llvm O3 rv32imfdc",
"llvm Os rv32imfdc"
]
# 编译器路径
GCC_CC_IMC = "riscv32-unknown-elf-gcc"
GCC_CC_IMFDC = "/opt/riscv/bin/riscv32-unknown-elf-gcc"
LLVM_CC = "/data/yangz/bs17/build/bin/clang"
LLVM_LD = "/data/yangz/bs17/build/bin/ld.lld"
# 其他编译参数
GCC_CFLAGS_BASE = "-c -ffunction-sections"
LLVM_CFLAGS_BASE = "--target=riscv32 -static -c -ffunction-sections"
# 结果文件
OUTPUT_CSV_TIME = "perf_results_time.csv"
OUTPUT_CSV_INSTRUCTIONS = "perf_results_instructions.csv"
OUTPUT_CSV_CYCLES = "perf_results_cycles.csv"
# 初始化 CSV 文件,写入表头
headers = ["Benchmark"] + [f"{opt}" for opt in COMPILER_OPTIONS]
with open(OUTPUT_CSV_TIME, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
with open(OUTPUT_CSV_INSTRUCTIONS, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
with open(OUTPUT_CSV_CYCLES, 'w', newline='') as csvfile:
writer = csv.writer(csvfile)
writer.writerow(headers)
# 初始化 benchmark 列表
EXECUTION_ORDER = [
"aha-mont64", "crc32", "cubic", "edn", "huffbench", "matmult-int", "minver",
"md5sum", "nbody", "nettle-aes", "nettle-sha256", "nsichneu", "picojpeg",
"primecount", "qrduino", "sglib-combined", "slre", "st", "tarfind",
"statemate", "ud", "wikisort"
]
# 初始化 CSV 文件中基准测试名称行
def init_benchmark_rows(file_path):
with open(file_path, 'a', newline='') as csvfile:
writer = csv.writer(csvfile)
for benchmark in EXECUTION_ORDER:
writer.writerow([benchmark] + [""] * (len(COMPILER_OPTIONS)))
# 添加几何统计行
writer.writerow(["Geometric mean"] + [""] * (len(COMPILER_OPTIONS)))
writer.writerow(["Geometric SD"] + [""] * (len(COMPILER_OPTIONS)))
writer.writerow(["Geometric range"] + [""] * (len(COMPILER_OPTIONS)))
init_benchmark_rows(OUTPUT_CSV_TIME)
init_benchmark_rows(OUTPUT_CSV_INSTRUCTIONS)
init_benchmark_rows(OUTPUT_CSV_CYCLES)
# 保存结果到 CSV 文件的相应列
def save_result(benchmark, value, column_index, csv_file):
try:
with open(csv_file, 'r') as file:
rows = list(csv.reader(file))
# 调试输出:保存之前的内容
print(f"Current rows in {csv_file} before saving result:")
for row in rows:
print(row)
# 更新相应行的数据
for row in rows:
if row[0] == benchmark:
row[column_index] = value
break
else:
print(f"Benchmark {benchmark} not found in {csv_file}")
# 写回文件
with open(csv_file, 'w', newline='') as file:
writer = csv.writer(file)
writer.writerows(rows)
# 调试输出:保存之后的内容
print(f"Saved result {value} for {benchmark} in column {column_index} of {csv_file}")
print(f"Current rows in {csv_file} after saving result:")
with open(csv_file, 'r') as file:
for row in csv.reader(file):
print(row)
except Exception as e:
print(f"Error saving result to {csv_file}: {e}")
# 运行基准测试并保存数据
def run_benchmark(compiler, opt_level, arch, column_index):
# 构建编译器、编译标志和链接标志等
if compiler == "gcc":
if arch == "rv32imc":
cc = GCC_CC_IMC
cflags = f"{GCC_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32"
ldflags = "-Wl,-gc-sections"
user_libs = "-lm"
elif arch == "rv32imfdc":
cc = GCC_CC_IMFDC
cflags = f"{GCC_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32d"
ldflags = "-L/opt/riscv/riscv32-unknown-elf/lib -Wl,-gc-sections"
user_libs = "-lm -lc -lgcc"
elif compiler == "llvm":
cc = LLVM_CC
ld = LLVM_LD
if arch == "rv32imc":
cflags = f"{LLVM_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32"
ldflags = "-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib"
user_libs = "/home/yangz/llvm/build/lib/clang-runtimes/riscv32/lib/crt0.o"
elif arch == "rv32imfdc":
cflags = f"{LLVM_CFLAGS_BASE} -{opt_level} -march={arch} -mabi=ilp32d"
ldflags = "-O2 -gc-sections -Bstatic -lc -lm -lclang_rt.builtins-riscv32 -L/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib"
user_libs = "/data/yangz/bs17/build/lib/clang-runtimes/riscv32/lib/crt0.o"
# 打印当前的测试配置
print("-----------------------------------")
print(f"Running configuration:\nCompiler = {compiler}\nOptimization Level = {opt_level}\nArchitecture Extension = {arch}")
print(f"CC = {cc}\nCFLAGS = {cflags}\nLDFLAGS = {ldflags}\nUSER_LIBS = {user_libs}")
print("-----------------------------------")
# 清理之前的构建目录
os.system("rm -rf bd/")
# 构建命令
if compiler == "gcc":
cmd = f"./build_all.py --timeout=60 --arch=riscv32 --chip=generic --board=ri5cyverilator --cc=\"{cc}\" --cflags=\"{cflags}\" --ldflags=\"{ldflags}\" --user-libs=\"{user_libs}\""
else:
cmd = f"./build_all.py --timeout=60 --arch=riscv32 --chip=generic --board=ri5cyverilator --cc=\"{cc}\" --ld=\"{ld}\" --cflags=\"{cflags}\" --ldflags=\"{ldflags}\" --user-libs=\"{user_libs}\""
print(f"\nRunning command:\n{cmd}\n")
subprocess.run(cmd, shell=True)
# 查找所有可执行文件,并运行性能测试
for benchmark in EXECUTION_ORDER:
exe_file = f"./bd/src/{benchmark}/{benchmark}"
if os.path.isfile(exe_file):
print(f"Running perf on {exe_file} ...")
try:
# 使用 perf 收集性能数据
perf_output = subprocess.check_output(
f"perf stat -e instructions,cpu-cycles qemu-riscv32 -B 0x10000000 -d in_asm,cpu,int,exec -D ch.txt {exe_file}",
shell=True,
text=True,
stderr=subprocess.STDOUT
)
print(f"PERF_OUTPUT:\n{perf_output}")
# 打印每一行,单独测试每行是否匹配
for line in perf_output.splitlines():
print(f"Line: '{line}'")
# 使用正则表达式提取指令数、周期数、运行时间
instructions_match = re.search(r"^\s*([\d,]+)\s+instructions", perf_output, re.MULTILINE)
cycles_match = re.search(r"^\s*([\d,]+)\s+cpu-cycles", perf_output, re.MULTILINE)
time_elapsed_match = re.search(r"^\s*([\d.]+)\s+seconds time elapsed", perf_output, re.MULTILINE)
# 调试:打印匹配状态
if instructions_match:
print(f"Instructions match found: {instructions_match.group(0)}")
else:
print(f"No instructions match found in:\n{perf_output}")
if cycles_match:
print(f"Cycles match found: {cycles_match.group(0)}")
else:
print(f"No cycles match found in:\n{perf_output}")
if time_elapsed_match:
print(f"Time elapsed match found: {time_elapsed_match.group(0)}")
else:
print(f"No time elapsed match found in:\n{perf_output}")
# 捕捉并去除逗号
instructions = instructions_match.group(1).replace(',', '') if instructions_match else ""
cycles = cycles_match.group(1).replace(',', '') if cycles_match else ""
time_elapsed = time_elapsed_match.group(1) if time_elapsed_match else ""
# 打印捕获的结果,调试用
print(f"Captured values - Time: {time_elapsed}, Instructions: {instructions}, Cycles: {cycles}")
# 保存结果到相应的 CSV 文件
save_result(benchmark, time_elapsed, column_index, OUTPUT_CSV_TIME)
save_result(benchmark, instructions, column_index, OUTPUT_CSV_INSTRUCTIONS)
save_result(benchmark, cycles, column_index, OUTPUT_CSV_CYCLES)
print(f"Saved results for {benchmark}: Time = {time_elapsed}, Instructions = {instructions}, Cycles = {cycles}")
except subprocess.CalledProcessError:
print(f"Error: Failed to collect perf data for {benchmark}")
else:
print(f"Executable not found: {exe_file}")
# 循环测试所有组合
for index, option in enumerate(COMPILER_OPTIONS):
print(f"Running benchmark for: {option} with column index {index + 1}")
compiler, opt, arch = option.split()
# 运行基准测试,并立即保存结果
run_benchmark(compiler, opt, arch, index + 1)
print(f"All benchmarks completed. Results saved to {OUTPUT_CSV_TIME}, {OUTPUT_CSV_INSTRUCTIONS}, and {OUTPUT_CSV_CYCLES}.")
运行时间约为12分钟
评论