添加脚本使用说明

the-little-apprentice 1 month ago
parent 08ce9d96ab
commit 407be0fca1

@ -48,6 +48,11 @@ STEM="${BASE%.sy}"
INPUT_DIR="$(dirname "$(realpath "$INPUT")")"
TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
# 与 run_baseline.sh 一致的路径键:去掉 test/ 前缀和 .sy 后缀
REL="$(realpath --relative-to="$REPO_ROOT" "$INPUT" 2>/dev/null || echo "$INPUT")"
CASE_KEY="${REL#test/}"
CASE_KEY="${CASE_KEY%.sy}"
if [[ $# -ge 2 ]]; then
OUT_DIR="$2"
else
@ -162,26 +167,28 @@ GCC_ASM_LINES=0
GCC_ELAPSED_RAW="" # 秒,无 s 后缀
if [[ -f "$BASELINE_TSV_PATH" ]]; then
GCC_ELAPSED_RAW=$(awk -F'\t' -v s="$STEM" '$1==s{v=$2} END{if(v!="") print v}' \
GCC_ELAPSED_RAW=$(awk -F'\t' -v s="$CASE_KEY" '$1==s{v=$2} END{if(v!="") print v}' \
"$BASELINE_TSV_PATH" 2>/dev/null || true)
if [[ -n "$GCC_ELAPSED_RAW" ]]; then
GCC_OK=true
rpt_color "$GREEN" "baseline timing: ${GCC_ELAPSED_RAW}s"
else
rpt_color "$YELLOW" "WARNING: no baseline entry for '$STEM'"
rpt_color "$YELLOW" "WARNING: no baseline entry for '$CASE_KEY'"
rpt " Run: scripts/run_baseline.sh"
fi
# 复制汇编文件
if [[ -f "$BASELINE_DATA_DIR/$STEM.gcc.s" ]]; then
cp "$BASELINE_DATA_DIR/$STEM.gcc.s" "$GCC_ASM"
# 复制汇编文件(路径镜像结构)
local_gcc_asm="$BASELINE_DATA_DIR/${CASE_KEY}.gcc.s"
if [[ -f "$local_gcc_asm" ]]; then
cp "$local_gcc_asm" "$GCC_ASM"
GCC_ASM_LINES=$(wc -l < "$GCC_ASM")
rpt "GCC ASM: $GCC_ASM ($GCC_ASM_LINES lines)"
else
rpt_color "$YELLOW" "GCC ASM not found in baseline dir"
rpt_color "$YELLOW" "GCC ASM not found in baseline dir: $local_gcc_asm"
fi
# 复制输出文件供步骥5 diff
if [[ -f "$BASELINE_DATA_DIR/$STEM.gcc.out" ]]; then
cp "$BASELINE_DATA_DIR/$STEM.gcc.out" "$GCC_OUT"
# 复制输出文件供步骤5 diff
local_gcc_out="$BASELINE_DATA_DIR/${CASE_KEY}.gcc.out"
if [[ -f "$local_gcc_out" ]]; then
cp "$local_gcc_out" "$GCC_OUT"
rpt "GCC output: $GCC_OUT"
fi
else
@ -199,24 +206,25 @@ run_and_time() {
local label="$1"
local exe="$2"
local out_file="$3"
local time_file="$4"
local timeout_sec="${5:-60}"
local timeout_sec="${4:-60}"
local stdout_file="$out_file.raw"
local status=0
local _t0 _t1 _ns
_t0=$(date +%s%N)
set +e
if [[ -f "$STDIN_FILE" ]]; then
timeout "$timeout_sec" \
/usr/bin/time -f "%e" -o "$time_file" \
qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" \
< "$STDIN_FILE" > "$stdout_file" 2>/dev/null
else
timeout "$timeout_sec" \
/usr/bin/time -f "%e" -o "$time_file" \
qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" \
> "$stdout_file" 2>/dev/null
fi
status=$?
_t1=$(date +%s%N)
_ns=$((_t1 - _t0))
set -e
# 将 stdout + exit_code 合并为 .out与 verify_asm.sh 格式一致)
@ -229,26 +237,27 @@ run_and_time() {
} > "$out_file"
rm -f "$stdout_file"
local elapsed="timeout"
[[ $status -ne 124 ]] && elapsed="$(cat "$time_file" 2>/dev/null || echo "?")s"
local elapsed
if [[ $status -eq 124 ]]; then
rpt_color "$YELLOW" "$label: TIMEOUT (>${timeout_sec}s)"
elif [[ $status -ne 0 ]]; then
rpt_color "$YELLOW" "$label: exit $status elapsed=${elapsed}"
elapsed="timeout"
rpt_color "$YELLOW" "$label: TIMEOUT (>${timeout_sec}s)" >&2
else
rpt_color "$GREEN" "$label: OK elapsed=${elapsed}"
elapsed=$(awk "BEGIN{printf \"%.5f\", $_ns / 1000000000}")
if [[ $status -ne 0 ]]; then
rpt_color "$YELLOW" "$label: exit $status elapsed=${elapsed}s" >&2
else
rpt_color "$GREEN" "$label: OK elapsed=${elapsed}s" >&2
fi
fi
echo "$elapsed"
}
OUR_OUT="$OUT_DIR/$STEM.our.out"
OUR_TIME_FILE="$OUT_DIR/$STEM.our.time"
TIMEOUT_SEC=60
[[ "$INPUT" == *"/performance/"* || "$INPUT" == *"/h_performance/"* ]] && TIMEOUT_SEC=300
OUR_ELAPSED=$(run_and_time "our compiler" "$OUR_ELF" "$OUR_OUT" "$OUR_TIME_FILE" "$TIMEOUT_SEC")
OUR_ELAPSED=$(run_and_time "our compiler" "$OUR_ELF" "$OUR_OUT" "$TIMEOUT_SEC")
# GCC 耗时直接读取基线数据,不重新运行
GCC_ELAPSED="N/A"
@ -305,7 +314,7 @@ rpt "$(printf '%-20s %s' 'GCC time:' "$GCC_ELAPSED")"
if [[ "$GCC_ELAPSED" != "N/A" && "$GCC_ELAPSED" != "timeout" && "$OUR_ELAPSED" != "timeout" ]]; then
OUR_S="${OUR_ELAPSED%s}"
GCC_S="${GCC_ELAPSED%s}"
SPEEDUP=$(awk "BEGIN{if($OUR_S>0) printf \"%.3f\", $GCC_S/$OUR_S; else print \"inf\"}")
SPEEDUP=$(awk "BEGIN{if($OUR_S>0) printf \"%.5f\", $GCC_S/$OUR_S; else print \"inf\"}")
rpt "$(printf '%-20s %sx' 'Speedup (gcc/ours):' "$SPEEDUP")"
fi
rpt ""

@ -0,0 +1,103 @@
============================================================
脚本优化总结2026-04
============================================================
一、架构分离
────────────────────────────────────────────────────────────
· run_baseline.sh 成为唯一负责计算 GCC -O2 基线的脚本;
其余所有脚本lab3_build_test.sh、analyze_case.sh只读
TSV不再重复运行 GCC避免重复耗时。
· 基线输出目录镜像测试用例的相对路径结构,例如:
output/baseline/test_case/functional/65_color.gcc.s
output/baseline/class_test_case/h_functional/11_BST.gcc.s
TSV 键与目录结构对齐class_test_case/h_functional/11_BST
二、SysY → C 编译兼容性修复run_baseline.sh
────────────────────────────────────────────────────────────
· const int 全局数组维度问题
C 模式下 const int N=10; int a[N]; 属于 VLA非法于文件域
用 Python3 预处理将 const int NAME=EXPR; 转换为:
#define NAME ((int)(EXPR))
同时支持多声明符写法const int A=1, B=2;
· sylib 链接方式
预编译 sylib.o-x c用 -include sylib.h 注入声明;
链接命令用 -x none 在 .o 前重置语言标志,防止 ELF 被
当作 C 源文件解析stray '\177' 错误)。
· C++ 关键字冲突
部分 SysY 测试用例用 delete/new/class 作函数名;
-x c 模式下这些不是关键字,编译正常通过。
· 枚举浮点值
enum { MAX = 1e9 }; 枚举成员必须是整数常量Python3
预处理同样将其转为 #define MAX ((int)(1e9))。
三、计时精度与准确性
────────────────────────────────────────────────────────────
· 全面弃用 /usr/bin/time非零退出时会向输出文件写入
"Command exited with non-zero status N",污染时间值。
· 改用 date +%s%N 纳秒手动计时:
_t0=$(date +%s%N)
... 运行命令 ...
_t1=$(date +%s%N)
elapsed=$(awk "BEGIN{printf \"%.5f\", $((t1-t0)) / 1e9}")
· 所有时间输出统一为 5 位小数(秒),加速比同样 5 位小数。
四、分段计时verify_asm.sh + lab3_build_test.sh
────────────────────────────────────────────────────────────
· verify_asm.sh 新增 --timing-out <file> 选项,运行结束后
向文件写入:
compile_ns=<纳秒>
run_ns=<纳秒>
· lab3_build_test.sh 读取 timing 文件,将编译耗时与运行耗时
分开显示:
PASS test_case/functional/65_color [compile=0.31416s run=0.18804s]
· 加速比只使用运行时间run_ns排除编译器启动开销。
五、性能排行榜lab3_build_test.sh
────────────────────────────────────────────────────────────
· 测试结束后输出双排序表格:
Sort 1加速比升序最需优化的用例排最前
Sort 2我方用时降序绝对耗时最高的排最前
每行格式:
<用例名> <我方时间> <GCC时间> <加速比>x
六、analyze_case.sh 修复
────────────────────────────────────────────────────────────
· 基线查找键从裸 stem65_color改为完整路径键
test_case/functional/65_color与 TSV 格式对齐,
消除 "WARNING: no baseline entry" 误报。
· run_and_time 函数的 rpt_color 输出重定向到 stderr
防止 ANSI 转义码被命令替换($())捕获后传入 awk
消除 "fatal: error: invalid character '\033'" 错误。
============================================================
脚本列表
============================================================
run_baseline.sh 计算所有用例的 GCC -O2 基线,结果存入
output/baseline/gcc_timing.tsv
用法: ./scripts/run_baseline.sh [--update]
--update 清空重算全部条目
lab3_build_test.sh 构建编译器,跑全部用例,输出加速比排行榜
用法: ./scripts/lab3_build_test.sh
verify_asm.sh 验证单个用例的汇编正确性
用法: ./scripts/verify_asm.sh <input.sy> [input.in] \
[expected.out] [timeout] [--timing-out file]
analyze_case.sh 单用例深度分析IR/ASM/计时/与基线对比)
用法: ./scripts/analyze_case.sh <input.sy> [output_dir]
clean_outputs.sh 清理 output/ 目录下的分析结果
用法: ./scripts/clean_outputs.sh
============================================================
Loading…
Cancel
Save