makefile update: implement the csv output
This commit is contained in:
246
Makefile
246
Makefile
@@ -248,3 +248,249 @@ clean-tests: clean-inputs clean-outputs
|
||||
clean:
|
||||
@echo "Cleaning up $(BUILD_DIR)/..."
|
||||
@rm -rf $(BUILD_DIR)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Benchmark Target (Advanced)
|
||||
# - N, M 증가 (Step)
|
||||
# - 동일 조건 반복 (Repeat)
|
||||
# - 유효성 검사 (Validator) 포함
|
||||
# - 상세 정보(Seed, Command) CSV 기록
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
BENCH_TIMESTAMP = $(shell date +%Y%m%d_%H%M%S)
|
||||
BENCH_CSV = $(LOG_DIR)/benchmark_results_$(BENCH_TIMESTAMP).csv
|
||||
BENCH_META = $(LOG_DIR)/benchmark_results_$(BENCH_TIMESTAMP).meta
|
||||
|
||||
START_N ?= 10000
|
||||
END_N ?= 50000
|
||||
STEP_N ?= 1000
|
||||
# M 계산식 (bash arithmetic expansion 문법)
|
||||
M_CALC ?= n * 4
|
||||
|
||||
# 동일 조건 반복 횟수
|
||||
REPEAT ?= 5
|
||||
|
||||
.PHONY: benchmark
|
||||
benchmark: all $(CHK_EXE) $(LOG_DIR)
|
||||
@echo "--- Starting Benchmark ---"
|
||||
@echo "Data: $(BENCH_CSV)"
|
||||
@echo "Meta: $(BENCH_META)"
|
||||
|
||||
@# 1. 메타 파일(.meta)에 실행 정보 기록
|
||||
@echo "Execution Info: Date=$(BENCH_TIMESTAMP) | Host=$(shell hostname)" > $(BENCH_META)
|
||||
@echo "Reproduce Command: make benchmark START_N=$(START_N) END_N=$(END_N) STEP_N=$(STEP_N) REPEAT=$(REPEAT) M_CALC='$(M_CALC)' SOL_A=$(SOL_A) SOL_B=$(SOL_B) gen=$(gen)" >> $(BENCH_META)
|
||||
|
||||
@# 2. CSV 파일(.csv)에는 순수 헤더만 기록 (엑셀 호환성 확보)
|
||||
@echo "N,M,Iter,Seed,$(SOL_A)_Time,$(SOL_B)_Time,Gen_Cmd,Sol_A_Cmd,Sol_B_Cmd" > $(BENCH_CSV)
|
||||
|
||||
@bash -c ' \
|
||||
export LC_ALL=C; \
|
||||
TIMEFORMAT=%R; \
|
||||
\
|
||||
for (( n=$(START_N); n<=$(END_N); n+=$(STEP_N) )); do \
|
||||
m=$$(( $(M_CALC) )); \
|
||||
\
|
||||
for (( r=1; r<=$(REPEAT); r++ )); do \
|
||||
SEED=$$(cat /dev/urandom | tr -cd "a-zA-Z0-9" | head -c 32); \
|
||||
\
|
||||
TMP_IN="$(BUILD_IN_DIR)/bench_in_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
TMP_OUT_A="$(BUILD_DIR)/bench_out_a_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
TMP_OUT_B="$(BUILD_DIR)/bench_out_b_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
\
|
||||
CMD_GEN="./$(GEN_TO_RUN) -N $$n -M $$m $$SEED"; \
|
||||
CMD_SOL_A="./$(SOL_A_EXE) < input"; \
|
||||
CMD_SOL_B="./$(SOL_B_EXE) < input"; \
|
||||
\
|
||||
printf "Run: N=%-5d M=%-5d Iter=%-2d ... " $$n $$m $$r; \
|
||||
\
|
||||
$$CMD_GEN > $$TMP_IN; \
|
||||
\
|
||||
t_a=$$( { time ./$(SOL_A_EXE) < $$TMP_IN > $$TMP_OUT_A; } 2>&1 ); \
|
||||
t_b=$$( { time ./$(SOL_B_EXE) < $$TMP_IN > $$TMP_OUT_B; } 2>&1 ); \
|
||||
\
|
||||
if ! ./$(CHK_EXE) $$TMP_IN $$TMP_OUT_A $$TMP_OUT_B > /dev/null 2>&1; then \
|
||||
printf "\n[FAIL] Checker found mismatch!\n"; \
|
||||
echo "Seed: $$SEED"; \
|
||||
echo "Check Metafile: $(BENCH_META)"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
\
|
||||
echo "$$n,$$m,$$r,$$SEED,$$t_a,$$t_b,\"$$CMD_GEN\",\"$$CMD_SOL_A\",\"$$CMD_SOL_B\"" >> $(BENCH_CSV); \
|
||||
\
|
||||
echo "OK. [A: $${t_a}s] [B: $${t_b}s]"; \
|
||||
\
|
||||
rm -f $$TMP_IN $$TMP_OUT_A $$TMP_OUT_B; \
|
||||
done; \
|
||||
done \
|
||||
'
|
||||
@echo "--- Benchmark Complete! ---"
|
||||
@echo "CSV Data: $(BENCH_CSV)"
|
||||
@echo "Metadata: $(BENCH_META)"
|
||||
|
||||
# .PHONY: benchmark
|
||||
# benchmark: all $(CHK_EXE) $(LOG_DIR)
|
||||
# @echo "--- Starting Benchmark with Checker ---"
|
||||
# @echo "Range: N=[$(START_N) .. $(END_N)], Step=$(STEP_N)"
|
||||
# @echo "Formula: M = $(M_CALC)"
|
||||
# @echo "Checker: $(CHK_EXE)"
|
||||
# @echo "Output: $(BENCH_CSV)"
|
||||
|
||||
# @echo "N,M,Iter,Seed,$(SOL_A)_Time,$(SOL_B)_Time,Gen_Cmd,Sol_A_Cmd,Sol_B_Cmd" > $(BENCH_CSV)
|
||||
|
||||
# @bash -c ' \
|
||||
# export LC_ALL=C; \
|
||||
# TIMEFORMAT=%R; \
|
||||
# \
|
||||
# for (( n=$(START_N); n<=$(END_N); n+=$(STEP_N) )); do \
|
||||
# m=$$(( $(M_CALC) )); \
|
||||
# \
|
||||
# for (( r=1; r<=$(REPEAT); r++ )); do \
|
||||
# SEED=$$(cat /dev/urandom | tr -cd "a-zA-Z0-9" | head -c 32); \
|
||||
# \
|
||||
# # 병렬 실행을 위한 임시 파일명 설정 (Input, OutA, OutB) \
|
||||
# TMP_IN="$(BUILD_IN_DIR)/bench_in_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
# TMP_OUT_A="$(BUILD_DIR)/bench_out_a_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
# TMP_OUT_B="$(BUILD_DIR)/bench_out_b_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
# \
|
||||
# CMD_GEN="./$(GEN_TO_RUN) -N $$n -M $$m $$SEED"; \
|
||||
# CMD_SOL_A="./$(SOL_A_EXE) < input"; \
|
||||
# CMD_SOL_B="./$(SOL_B_EXE) < input"; \
|
||||
# \
|
||||
# printf "Run: N=%-5d M=%-5d Iter=%-2d ... " $$n $$m $$r; \
|
||||
# \
|
||||
# # 1. Generator 실행 \
|
||||
# $$CMD_GEN > $$TMP_IN; \
|
||||
# \
|
||||
# # 2. Sol A 실행 (시간 측정 + 출력 저장) \
|
||||
# t_a=$$( { time ./$(SOL_A_EXE) < $$TMP_IN > $$TMP_OUT_A; } 2>&1 ); \
|
||||
# \
|
||||
# # 3. Sol B 실행 (시간 측정 + 출력 저장) \
|
||||
# t_b=$$( { time ./$(SOL_B_EXE) < $$TMP_IN > $$TMP_OUT_B; } 2>&1 ); \
|
||||
# \
|
||||
# # 4. Checker 실행 (비교) \
|
||||
# if ! ./$(CHK_EXE) $$TMP_IN $$TMP_OUT_A $$TMP_OUT_B > /dev/null 2>&1; then \
|
||||
# printf "\n[FAIL] Checker found mismatch!\n"; \
|
||||
# echo "Seed: $$SEED"; \
|
||||
# echo "Input saved to: $$TMP_IN"; \
|
||||
# echo "Out A saved to: $$TMP_OUT_A"; \
|
||||
# echo "Out B saved to: $$TMP_OUT_B"; \
|
||||
# exit 1; \
|
||||
# fi; \
|
||||
# \
|
||||
# # 5. 통과 시 CSV 기록 \
|
||||
# echo "$$n,$$m,$$r,$$SEED,$$t_a,$$t_b,\"$$CMD_GEN\",\"$$CMD_SOL_A\",\"$$CMD_SOL_B\"" >> $(BENCH_CSV); \
|
||||
# \
|
||||
# echo "OK. [A: $${t_a}s] [B: $${t_b}s]"; \
|
||||
# \
|
||||
# # 6. 임시 파일 삭제 \
|
||||
# rm -f $$TMP_IN $$TMP_OUT_A $$TMP_OUT_B; \
|
||||
# done; \
|
||||
# done \
|
||||
# '
|
||||
# @echo "--- Benchmark Complete! Data saved to $(BENCH_CSV) ---"
|
||||
|
||||
# .PHONY: benchmark
|
||||
# benchmark: all $(LOG_DIR)
|
||||
# @echo "--- Starting Advanced Benchmark ---"
|
||||
# @echo "Range: N=[$(START_N) .. $(END_N)], Step=$(STEP_N)"
|
||||
# @echo "Formula: M = $(M_CALC)"
|
||||
# @echo "Repeat: $(REPEAT) times per setting"
|
||||
# @echo "Output: $(BENCH_CSV)"
|
||||
|
||||
# @echo "N,M,Iter,Seed,$(SOL_A)_Time,$(SOL_B)_Time,Gen_Cmd,Sol_A_Cmd,Sol_B_Cmd" > $(BENCH_CSV)
|
||||
|
||||
# @bash -c ' \
|
||||
# export LC_ALL=C; \
|
||||
# TIMEFORMAT=%R; \
|
||||
# \
|
||||
# for (( n=$(START_N); n<=$(END_N); n+=$(STEP_N) )); do \
|
||||
# m=$$(( $(M_CALC) )); \
|
||||
# \
|
||||
# for (( r=1; r<=$(REPEAT); r++ )); do \
|
||||
# SEED=$$(cat /dev/urandom | tr -cd "a-zA-Z0-9" | head -c 32); \
|
||||
# \
|
||||
# # [변경] 파일명에 타임스탬프와 PID($$)를 포함하여 충돌 방지 \
|
||||
# TMP_IN="$(BUILD_IN_DIR)/bench_input_$(BENCH_TIMESTAMP)_$$$$.tmp"; \
|
||||
# \
|
||||
# CMD_GEN="./$(GEN_TO_RUN) -N $$n -M $$m $$SEED"; \
|
||||
# CMD_SOL_A="./$(SOL_A_EXE) < input"; \
|
||||
# CMD_SOL_B="./$(SOL_B_EXE) < input"; \
|
||||
# \
|
||||
# printf "Run: N=%-5d M=%-5d Iter=%-2d ... " $$n $$m $$r; \
|
||||
# \
|
||||
# $$CMD_GEN > $$TMP_IN; \
|
||||
# \
|
||||
# if ! ./$(VAL_EXE) < $$TMP_IN > /dev/null 2>&1; then \
|
||||
# echo " [FAIL] Validator rejected input! Seed: $$SEED"; \
|
||||
# rm -f $$TMP_IN; \
|
||||
# exit 1; \
|
||||
# fi; \
|
||||
# \
|
||||
# t_a=$$( { time ./$(SOL_A_EXE) < $$TMP_IN > /dev/null; } 2>&1 ); \
|
||||
# t_b=$$( { time ./$(SOL_B_EXE) < $$TMP_IN > /dev/null; } 2>&1 ); \
|
||||
# \
|
||||
# echo "$$n,$$m,$$r,$$SEED,$$t_a,$$t_b,\"$$CMD_GEN\",\"$$CMD_SOL_A\",\"$$CMD_SOL_B\"" >> $(BENCH_CSV); \
|
||||
# \
|
||||
# echo "OK. [A: $${t_a}s] [B: $${t_b}s]"; \
|
||||
# \
|
||||
# rm -f $$TMP_IN; \
|
||||
# done; \
|
||||
# done \
|
||||
# '
|
||||
# @echo "--- Benchmark Complete! Data saved to $(BENCH_CSV) ---"
|
||||
|
||||
# .PHONY: benchmark
|
||||
# benchmark: all $(LOG_DIR)
|
||||
# @echo "--- Starting Advanced Benchmark ---"
|
||||
# @echo "Range: N=[$(START_N) .. $(END_N)], Step=$(STEP_N)"
|
||||
# @echo "Formula: M = $(M_CALC)"
|
||||
# @echo "Repeat: $(REPEAT) times per setting"
|
||||
# @echo "Validator: $(VAL_EXE)"
|
||||
# @echo "Output: $(BENCH_CSV)"
|
||||
|
||||
# @# CSV Header 작성
|
||||
# @echo "N,M,Iter,Seed,$(SOL_A)_Time,$(SOL_B)_Time,Gen_Cmd,Sol_A_Cmd,Sol_B_Cmd" > $(BENCH_CSV)
|
||||
|
||||
# @bash -c ' \
|
||||
# export LC_ALL=C; \
|
||||
# TIMEFORMAT=%R; \
|
||||
# \
|
||||
# # 1. N 루프 \
|
||||
# for (( n=$(START_N); n<=$(END_N); n+=$(STEP_N) )); do \
|
||||
# m=$$(( $(M_CALC) )); \
|
||||
# \
|
||||
# # 2. 반복 루프 (Repeat) \
|
||||
# for (( r=1; r<=$(REPEAT); r++ )); do \
|
||||
# SEED=$$(cat /dev/urandom | tr -cd "a-zA-Z0-9" | head -c 32); \
|
||||
# TMP_IN="$(BUILD_IN_DIR)/bench_input.tmp"; \
|
||||
# \
|
||||
# # 명령어 문자열 구성 (CSV 기록용) \
|
||||
# CMD_GEN="./$(GEN_TO_RUN) -N $$n -M $$m $$SEED"; \
|
||||
# CMD_SOL_A="./$(SOL_A_EXE) < input"; \
|
||||
# CMD_SOL_B="./$(SOL_B_EXE) < input"; \
|
||||
# \
|
||||
# printf "Run: N=%-5d M=%-5d Iter=%-2d ... " $$n $$m $$r; \
|
||||
# \
|
||||
# # 3. Generator 실행 \
|
||||
# $$CMD_GEN > $$TMP_IN; \
|
||||
# \
|
||||
# # 4. Validator 실행 (실패 시 즉시 종료) \
|
||||
# if ! ./$(VAL_EXE) < $$TMP_IN > /dev/null 2>&1; then \
|
||||
# echo " [FAIL] Validator rejected input! Seed: $$SEED"; \
|
||||
# exit 1; \
|
||||
# fi; \
|
||||
# \
|
||||
# # 5. 솔루션 실행 및 시간 측정 \
|
||||
# t_a=$$( { time ./$(SOL_A_EXE) < $$TMP_IN > /dev/null; } 2>&1 ); \
|
||||
# t_b=$$( { time ./$(SOL_B_EXE) < $$TMP_IN > /dev/null; } 2>&1 ); \
|
||||
# \
|
||||
# # 6. CSV 저장 (명령어에 콤마가 포함될 수 있으므로 따옴표로 감싸는 것이 안전하나, 여기선 단순화) \
|
||||
# echo "$$n,$$m,$$r,$$SEED,$$t_a,$$t_b,\"$$CMD_GEN\",\"$$CMD_SOL_A\",\"$$CMD_SOL_B\"" >> $(BENCH_CSV); \
|
||||
# \
|
||||
# echo "OK. [A: $${t_a}s] [B: $${t_b}s]"; \
|
||||
# \
|
||||
# rm -f $$TMP_IN; \
|
||||
# done; \
|
||||
# done \
|
||||
# '
|
||||
# @echo "--- Benchmark Complete! Data saved to $(BENCH_CSV) ---"
|
||||
Reference in New Issue
Block a user