FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

SPEC2006/SPEC2017をRISC-V環境で実行するためのリポジトリを構築する (SimPoint / BBVの並列取得)

BBVは、プログラムの実行特性を分析するための情報で、SimPointでの計算に利用する。QEMUのBBVプラグインを使用してBBVデータを収集する。

BBVプラグインの設定

BBV_PLUGIN := $(QEMU_BUILD_DIR)/contrib/plugins/libbbv.so
BBV_DIR := bbv_results

BBV収集の並列実行

run_bbv_<benchmark> ターゲットでは、通常実行と同様に並列化を実装している:

# Run all benchmarks with BBV collection
run_bbv: $(RUN_BBV_TARGETS)

$(RUN_BBV_TARGETS): benchmark=$(subst run_bbv_,,$@)
$(RUN_BBV_TARGETS): run_dir=$(SPEC_ROOT)/benchspec/CPU2006/$(benchmark)/run/run_base_ref_gcc.0000
$(RUN_BBV_TARGETS): bbv_output_dir=$(BBV_DIR)/$(benchmark)
$(RUN_BBV_TARGETS): output_dir=$(RESULT_DIR)/$(benchmark)_bbv
$(RUN_BBV_TARGETS):
    @echo "=== Preparing BBV output directory for $(benchmark) ==="
    @mkdir -p $(bbv_output_dir)
    @mkdir -p $(output_dir)
    @subcmds=$$(cd $(run_dir) && $(SPECINVOKE) -n 2>&1 | grep -v "^#" | grep -v "^timer" | grep -v "^$$"); \
    num_subcmds=$$(echo "$$subcmds" | wc -l); \
    echo "=== Subcommands for $(benchmark) with BBV ($$num_subcmds commands)"; \
    bbv_dir_abs=$$(cd $(bbv_output_dir) && pwd); \
    output_dir_abs=$$(cd $(output_dir) && pwd); \
    export bbv_dir_abs output_dir_abs; \
    echo "$$subcmds" | nl -nln | \
    parallel --line-buffer --colsep '\t' -j $$num_subcmds \
    'cmd_clean=$$(echo {2} | sed "s/ [0-9]*>>* *[^ ]*//g"); \
    bbv_file="$$bbv_dir_abs/bbv_{1}.out"; \
    output_file="$$output_dir_abs/output_{1}.txt"; \
    cmd_with_bbv=$$(echo $$cmd_clean | sed "s|$(QEMU)|$(QEMU) -plugin $(BBV_PLUGIN),outfile=$$bbv_file|"); \
    echo "[$(benchmark) BBV {1}/$$num_subcmds] Starting..."; \
    (cd $(run_dir) && eval $$cmd_with_bbv > $$output_file 2>&1) && \
    echo "[$(benchmark) BBV {1}/$$num_subcmds] Completed - BBV saved to $$bbv_file" || \
    echo "[$(benchmark) BBV {1}/$$num_subcmds] Failed"'; \
    echo "=== Completed all $(benchmark) BBV collection ==="

通常実行との違いは、QEMUコマンドにBBVプラグインを追加している点:

cmd_with_bbv=$$(echo $$cmd_clean | sed "s|$(QEMU)|$(QEMU) -plugin $(BBV_PLUGIN),outfile=$$bbv_file|")

これにより、各サブコマンドごとに個別のBBVファイルが生成される:

bbv_results/
├── 400.perlbench/
│   ├── bbv_1.out.0.bb
│   ├── bbv_2.out.0.bb
│   └── bbv_3.out.0.bb
├── 401.bzip2/
│   ├── bbv_1.out.0.bb
│   └── bbv_2.out.0.bb
└── ...

SimPointの並列実行

SimPointは、BBVファイルを解析して代表的な実行ポイントを抽出するツール。各BBVファイルに対して独立に実行できるため、並列化が可能。

# Run SimPoint analysis on all benchmarks
run_simpoint: $(RUN_SIMPOINT_TARGETS)

$(RUN_SIMPOINT_TARGETS): benchmark=$(subst run_simpoint_,,$@)
$(RUN_SIMPOINT_TARGETS): bbv_output_dir=$(BBV_DIR)/$(benchmark)
$(RUN_SIMPOINT_TARGETS): simpoint_output_dir=$(SIMPOINT_DIR)/$(benchmark)
$(RUN_SIMPOINT_TARGETS):
    @echo "=== Running SimPoint analysis for $(benchmark) ==="
    @mkdir -p $(simpoint_output_dir)
    @if [ ! -d "$(bbv_output_dir)" ]; then \
        echo "Error: BBV directory $(bbv_output_dir) not found. Please run 'make run_bbv_$(benchmark)' first."; \
        exit 1; \
    fi; \
    bbv_files=$$(ls $(bbv_output_dir)/bbv_*.out.*.bb 2>/dev/null); \
    if [ -z "$$bbv_files" ]; then \
        echo "Error: No BBV files found in $(bbv_output_dir). Please run 'make run_bbv_$(benchmark)' first."; \
        exit 1; \
    fi; \
    echo "$$bbv_files" | \
    parallel --line-buffer -j $$(nproc) \
    'bbv_file={}; \
    base_name=$$(basename $$bbv_file .bb); \
    simpoint_out="$(simpoint_output_dir)/$${base_name}.simpoints"; \
    weights_out="$(simpoint_output_dir)/$${base_name}.weights"; \
    echo "[$(benchmark)] Processing $$bbv_file..."; \
    $(SIMPOINT) -loadFVFile $$bbv_file -saveSimpoints $$simpoint_out -saveSimpointWeights $$weights_out -maxK $(SIMPOINT_K) > /dev/null 2>&1; \
    if [ -f "$$simpoint_out" ]; then \
        echo "[$(benchmark)] SimPoint completed: $$simpoint_out (weights: $$weights_out)"; \
    else \
        echo "[$(benchmark)] SimPoint failed for $$bbv_file"; \
    fi'; \
    echo "=== Completed SimPoint analysis for $(benchmark) ==="

ここでは、parallel -j $$(nproc) を使用して、CPUコア数分だけ並列実行している。