Skip to content

Commit d38e27a

Browse files
feat: Estimate_JSON schema redesign [skip-ci]
- Restructure Estimate_JSON: move benchmark_* to per-system benchmark sub-objects - Rename nodes->target_nodes, method->scaling_method - Add fom_breakdown (SECTION/OVERLAP) to Result_JSON and Estimate_JSON - Remove hardware info from result.sh (cpu_name, gpu_name, etc.) - Add numproc_node to Result_JSON parser - Add _meta (timestamp, uuid) to query_result API - Update estimate_common.sh variables and print_json - Update qws/estimate.sh and qws/run.sh for new schema - Update results_loader and estimated_results.html template - Update test data to match new schema (95 tests passing)
1 parent 1506823 commit d38e27a

File tree

12 files changed

+1183
-191
lines changed

12 files changed

+1183
-191
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"specId": "054020f6-5261-44dd-855e-8a86ce2e3f12", "workflowType": "requirements-first", "specType": "feature"}

.kiro/specs/estimate-json-schema/design.md

Lines changed: 462 additions & 0 deletions
Large diffs are not rendered by default.

.kiro/specs/estimate-json-schema/requirements.md

Lines changed: 205 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
# 実装計画: Estimate_JSON スキーマ再設計
2+
3+
## 概要
4+
5+
Result_JSON と Estimate_JSON のスキーマ再設計を、依存関係の順序に従って段階的に実装する。まず result.sh のパーサー拡張とハードウェア情報削除、次に API 拡張、estimate_common.sh の更新、qws スクリプトの対応、最後に result_server 側(ローダー・テンプレート・フィルタ)の更新を行う。
6+
7+
## タスク
8+
9+
- [x] 1. result.sh の SECTION/OVERLAP パーサー追加とハードウェア情報削除
10+
- [x] 1.1 result.sh から `case "$system"` ハードウェア情報生成ブロックを削除する
11+
- `cpu_name`, `gpu_name`, `cpu_cores`, `cpus_per_node`, `gpus_per_node` の case 文による設定を削除
12+
- `uname_info` 変数の生成と使用を削除
13+
- Result_JSON 出力から `cpu_name`, `gpu_name`, `cpu_cores`, `cpus_per_node`, `gpus_per_node`, `uname` フィールドを削除
14+
- _要件: 12.1, 12.2, 12.3, 12.4_
15+
16+
- [x] 1.2 result.sh に `numproc_node` パーサーを追加する
17+
- FOM 行から `numproc_node:値` を抽出するパース処理を追加
18+
- Result_JSON 出力に `numproc_node` フィールドを追加
19+
- _要件: 10.6, 11.6_
20+
21+
- [x] 1.3 result.sh に SECTION/OVERLAP パーサーを実装する
22+
- FOM 行の後に続く `SECTION:区間名 time:秒` 形式の行をパースする処理を追加
23+
- `OVERLAP:区間A,区間B time:秒` 形式の行をパースする処理を追加
24+
- OVERLAP 行の区間名が同一ブロック内の SECTION で未定義の場合、stderr にエラーを出力
25+
- パースした区間とオーバーラップを `fom_breakdown` オブジェクトとして Result_JSON に格納
26+
- SECTION/OVERLAP 行が存在しない FOM ブロックでは `fom_breakdown` を省略
27+
- `jq` による JSON 検証を維持
28+
- _要件: 10.1, 10.2, 10.3, 10.4, 10.5, 11.1, 11.2, 11.3, 11.4, 11.5, 11.7, 12.5_
29+
30+
- [ ]* 1.4 result.sh のパーサーのユニットテストを作成する
31+
- SECTION/OVERLAP ありの results/result ファイルで正しい fom_breakdown が生成されることを検証
32+
- SECTION/OVERLAP なしの場合に fom_breakdown が省略されることを検証
33+
- OVERLAP の区間名が未定義の場合にエラーが stderr に出力されることを検証
34+
- numproc_node のパースを検証
35+
- ハードウェア情報フィールドが出力されないことを検証
36+
- _要件: 10.1-10.6, 11.1-11.7, 12.1-12.5_
37+
38+
- [x] 2. programs/qws/run.sh に numproc_node と仮 SECTION/OVERLAP 出力を追加
39+
- [x] 2.1 qws/run.sh の各 case ブランチの FOM 行に `numproc_node:$numproc_node` を追加する
40+
- 各 system case で適切な numproc_node 値を設定(例: MPI プロセス数)
41+
- _要件: 14.4_
42+
43+
- [x] 2.2 qws/run.sh の各 case ブランチに仮の SECTION/OVERLAP 行を追加する
44+
- FOM 行の後に `SECTION:compute_kernel time:0.30` 等の固定値 SECTION 行を出力
45+
- `OVERLAP:compute_kernel,communication time:0.05` 等の固定値 OVERLAP 行を出力
46+
- _要件: 14.1, 14.2, 14.3_
47+
48+
- [x] 3. チェックポイント — result.sh と qws/run.sh の変更確認
49+
- テストがあれば実行し、全テストがパスすることを確認する。疑問があればユーザーに確認する。
50+
51+
- [x] 4. query_result API に `_meta` を追加
52+
- [x] 4.1 `result_server/routes/api.py``query_result` 関数にファイル名からの timestamp/uuid 抽出と `_meta` オブジェクト追加を実装する
53+
- ファイル名から `YYYYMMDD_HHMMSS` パターンで timestamp を抽出し `YYYY-MM-DD HH:MM:SS` 形式に変換
54+
- ファイル名から UUID を抽出
55+
- `data["_meta"] = {"timestamp": timestamp, "uuid": uid}` をレスポンスに追加
56+
- 既存のレスポンスフィールド(code, system, FOM 等)は変更しない
57+
- _要件: 5.1, 5.2, 5.3, 5.4_
58+
59+
- [ ]* 4.2 `result_server/tests/test_api_routes.py``_meta` のテストを追加する
60+
- query_result レスポンスに `_meta.timestamp``_meta.uuid` が含まれることを検証
61+
- ファイル名に timestamp/uuid がない場合の動作を検証
62+
- _要件: 5.1, 5.2, 5.3_
63+
64+
- [x] 5. estimate_common.sh の更新(変数リネーム・新変数・関数拡張)
65+
- [x] 5.1 estimate_common.sh のグローバル変数を更新する
66+
- `est_benchmark_system`, `est_benchmark_fom`, `est_benchmark_nodes` を廃止
67+
- `est_current_nodes``est_current_target_nodes``est_current_method``est_current_scaling_method` にリネーム
68+
- `est_future_nodes``est_future_target_nodes``est_future_method``est_future_scaling_method` にリネーム
69+
- current_system 用ベンチマーク変数を追加: `est_current_bench_system`, `est_current_bench_fom`, `est_current_bench_nodes`, `est_current_bench_numproc_node`, `est_current_bench_timestamp`, `est_current_bench_uuid`
70+
- future_system 用ベンチマーク変数を追加: `est_future_bench_system`, `est_future_bench_fom`, `est_future_bench_nodes`, `est_future_bench_numproc_node`, `est_future_bench_timestamp`, `est_future_bench_uuid`
71+
- fom_breakdown 変数を追加: `est_current_fom_breakdown`, `est_future_fom_breakdown`
72+
- _要件: 2.1, 2.2, 2.3, 2.4, 2.5_
73+
74+
- [x] 5.2 estimate_common.sh の `read_values` 関数を拡張する
75+
- `numproc_node` フィールドを読み取り `est_numproc_node` に格納
76+
- `timestamp` フィールドを読み取り `est_timestamp` に格納(存在しない場合は空文字列)
77+
- `uuid` フィールドを読み取り `est_uuid` に格納(存在しない場合は空文字列)
78+
- _要件: 3.1, 3.2, 3.3_
79+
80+
- [x] 5.3 estimate_common.sh の `fetch_current_fom` 関数を拡張する
81+
- API レスポンスから `node_count` を読み取り `est_current_bench_nodes` に格納
82+
- API レスポンスから `numproc_node` を読み取り `est_current_bench_numproc_node` に格納
83+
- API レスポンスから `_meta.timestamp` を読み取り `est_current_bench_timestamp` に格納
84+
- API レスポンスから `_meta.uuid` を読み取り `est_current_bench_uuid` に格納
85+
- `est_current_bench_system` に検索対象のシステム名を格納
86+
- `est_current_bench_fom` に取得した FOM 値を格納
87+
- _要件: 4.1, 4.2, 4.3, 4.4, 4.5, 4.6_
88+
89+
- [x] 5.4 estimate_common.sh の `print_json` 関数を新スキーマに更新する
90+
- トップレベルの `benchmark_system`, `benchmark_fom`, `benchmark_nodes` を廃止
91+
- `current_system``future_system` にそれぞれ `benchmark` サブオブジェクトを出力
92+
- `nodes``target_nodes``method``scaling_method` にリネーム
93+
- `fom_breakdown` が設定されている場合のみ条件付きで出力
94+
- _要件: 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.6, 13.5, 13.6_
95+
96+
- [x] 6. programs/qws/estimate.sh を新スキーマに対応させる
97+
- [x] 6.1 qws/estimate.sh の変数代入を新スキーマに移行する
98+
- `est_benchmark_system`, `est_benchmark_fom`, `est_benchmark_nodes` への代入を廃止
99+
- future_system 用ベンチマーク変数(`est_future_bench_system`, `est_future_bench_fom`, `est_future_bench_nodes`, `est_future_bench_numproc_node`, `est_future_bench_timestamp`, `est_future_bench_uuid`)を設定
100+
- `est_current_nodes``est_current_target_nodes``est_current_method``est_current_scaling_method` に変更
101+
- `est_future_nodes``est_future_target_nodes``est_future_method``est_future_scaling_method` に変更
102+
- `est_current_fom_breakdown``est_future_fom_breakdown` を設定(fom_breakdown のパススルー)
103+
- _要件: 6.1, 6.2, 6.3, 6.4, 13.1, 13.2_
104+
105+
- [x] 7. チェックポイント — シェルスクリプト変更の確認
106+
- 全テストがパスすることを確認する。疑問があればユーザーに確認する。
107+
108+
- [x] 8. results_loader の新スキーマ対応
109+
- [x] 8.1 `result_server/utils/results_loader.py``ESTIMATED_FIELD_MAP``_matches_filters` を更新する
110+
- `ESTIMATED_FIELD_MAP``system` キーを新スキーマのフィールドパスに更新
111+
- `_matches_filters` でネストされたフィールドパス(`current_system.system`)をサポート
112+
- `code``exp` のフィルタリングは引き続きトップレベルフィールドで行う
113+
- _要件: 9.1, 9.2, 9.3_
114+
115+
- [x] 8.2 `result_server/utils/results_loader.py``load_estimated_results_table` を新スキーマに対応させる
116+
- `current_system.benchmark` からベンチマーク元情報(system, fom, nodes)を読み取る
117+
- `current_system.target_nodes`, `current_system.scaling_method` を読み取る
118+
- `future_system.benchmark`, `future_system.target_nodes`, `future_system.scaling_method` を同様に読み取る
119+
- 行データに `systemA_target_nodes`, `systemA_scaling_method`, `systemA_bench_system`, `systemA_bench_fom`, `systemA_bench_nodes` を追加
120+
- 行データに `systemB_target_nodes`, `systemB_scaling_method`, `systemB_bench_system`, `systemB_bench_fom`, `systemB_bench_nodes` を追加
121+
- 旧スキーマの `benchmark_system`, `benchmark_fom`, `benchmark_nodes` 行データを廃止
122+
- _要件: 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.8_
123+
124+
- [ ]* 8.3 `result_server/tests/test_results_loader.py` に新スキーマのテストを追加する
125+
- 新スキーマの Estimate_JSON を読み込み、行データに正しいフィールドが含まれることを検証
126+
- `_matches_filters` がネストされたフィールドパスで正しくフィルタリングすることを検証
127+
- _要件: 7.1-7.8, 9.1-9.3_
128+
129+
- [x] 9. estimated_results.html テンプレートの更新
130+
- [x] 9.1 `result_server/templates/estimated_results.html` のテーブルヘッダーとボディを新スキーマに対応させる
131+
- 旧スキーマのトップレベル Benchmark カラム(Benchmark System, Benchmark FOM, Benchmark Nodes)を廃止
132+
- System A グループに Target Nodes, Scaling Method, Bench System, Bench FOM, Bench Nodes カラムを追加
133+
- System B グループに Target Nodes, Scaling Method, Bench System, Bench FOM, Bench Nodes カラムを追加
134+
- 2段ヘッダー構成(System A / System B のグループヘッダーと個別カラムヘッダー)を実装
135+
- テーブルボディの変数参照を新しい行データフィールドに更新
136+
- _要件: 8.1, 8.2, 8.3, 8.4, 8.5, 8.6_
137+
138+
- [x] 10. チェックポイント — result_server 側の変更確認
139+
- 全テストがパスすることを確認する。疑問があればユーザーに確認する。
140+
141+
## 備考
142+
143+
- `*` マーク付きのタスクはオプションであり、MVP では省略可能
144+
- 各タスクは特定の要件を参照しており、トレーサビリティを確保している
145+
- チェックポイントで段階的に検証を行い、問題を早期に発見する
146+
- プロパティテストは Result_JSON / Estimate_JSON のスキーマ検証に有効だが、シェルスクリプト中心の実装のため、Python テスト側で検証する
147+
- シェルスクリプトは LF 改行コードを使用すること
148+
- `set -euo pipefail` 環境では curl 失敗時に `set +e` / `set -e` でラップすること

programs/qws/estimate.sh

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,31 @@ source scripts/estimate_common.sh
1313
# --- Read benchmark result ---
1414
read_values "$1"
1515

16-
# --- Benchmark values (pass through from the benchmark run) ---
17-
est_benchmark_system="$est_system"
18-
est_benchmark_fom="$est_fom"
19-
est_benchmark_nodes="$est_node_count"
16+
# --- Future system benchmark: pass through from the benchmark run ---
17+
est_future_bench_system="$est_system"
18+
est_future_bench_fom="$est_fom"
19+
est_future_bench_nodes="$est_node_count"
20+
est_future_bench_numproc_node="$est_numproc_node"
21+
est_future_bench_timestamp="$est_timestamp"
22+
est_future_bench_uuid="$est_uuid"
2023

2124
# --- Current system: Fugaku — fetch real FOM from result_server ---
2225
est_current_system="Fugaku"
2326
CURRENT_EXP="" # Set specific Exp here if needed (e.g. "default")
2427
fetch_current_fom "$est_code" "$CURRENT_EXP"
25-
est_current_nodes="$est_node_count"
26-
est_current_method="measured"
28+
# fetch_current_fom sets est_current_bench_* variables automatically
29+
est_current_target_nodes="$est_node_count"
30+
est_current_scaling_method="measured"
2731

28-
# Future system: FugakuNEXT — FOM scaled by 2x (dummy)
32+
# --- Future system: FugakuNEXT — FOM scaled by 2x (dummy) ---
2933
est_future_system="FugakuNEXT"
3034
est_future_fom=$(awk -v fom="$est_fom" 'BEGIN {printf "%.3f", fom * 2}')
31-
est_future_nodes="$est_node_count"
32-
est_future_method="scale-mock"
35+
est_future_target_nodes="$est_node_count"
36+
est_future_scaling_method="scale-mock"
37+
38+
# --- fom_breakdown (pass through from benchmark result if available) ---
39+
est_current_fom_breakdown="" # Fugaku benchmark may not have fom_breakdown
40+
est_future_fom_breakdown=$(jq -c '.fom_breakdown // empty' "$1")
3341

3442
# --- Output ---
3543
mkdir -p results

programs/qws/run.sh

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,28 @@ case "$system" in
5656
mpiexec -n 1 ./main 32 6 4 3 1 1 1 1 -1 -1 6 50 > CASE0
5757
./check.sh output.${PJM_JOBID}/0/1/stdout.1.0 data/CASE0
5858
FOM=$(grep etime output.${PJM_JOBID}/0/1/stdout.1.0 | awk 'NR==2{printf("%5.3f\n",$5)}')
59-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes >> ../results/result
59+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes numproc_node:1 >> ../results/result
60+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
61+
echo "SECTION:communication time:0.20" >> ../results/result
62+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
6063
# CASE1
6164
mpiexec -n 2 ./main 32 6 4 3 1 1 1 2 -1 -1 6 50 > CASE1
6265
./check.sh output.${PJM_JOBID}/0/2/stdout.2.0 data/CASE1
6366
FOM=$(grep etime output.${PJM_JOBID}/0/2/stdout.2.0 | awk 'NR==2{printf("%5.3f\n",$5)}')
64-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE1 node_count:$nodes >> ../results/result
67+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE1 node_count:$nodes numproc_node:2 >> ../results/result
68+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
69+
echo "SECTION:communication time:0.20" >> ../results/result
70+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
6571
;;
6672
2)
6773
# CASE7
6874
mpiexec -n 8 ./main 32 6 4 3 1 2 2 2 -1 -1 6 50 > CASE7
6975
./check.sh output.${PJM_JOBID}/0/1/stdout.1.0 data/CASE7
7076
FOM=$(grep etime output.${PJM_JOBID}/0/1/stdout.1.0 | awk 'NR==2{printf("%5.3f\n",$5)}')
71-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE7 node_count:$nodes >> ../results/result
77+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE7 node_count:$nodes numproc_node:4 >> ../results/result
78+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
79+
echo "SECTION:communication time:0.20" >> ../results/result
80+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
7281
;;
7382
*)
7483
echo "Unknown Running system: $system"
@@ -81,7 +90,10 @@ case "$system" in
8190
./main 32 6 4 3 1 1 1 1 -1 -1 6 50 > CASE0
8291
./check.sh CASE0 data/CASE0
8392
FOM=$(grep etime CASE0 | awk 'NR==2{printf("%5.3f\n",$5)}')
84-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes >> ../results/result
93+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes numproc_node:1 >> ../results/result
94+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
95+
echo "SECTION:communication time:0.20" >> ../results/result
96+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
8597

8698
# (以下のpadata0.tgzはdummyです。)
8799
mkdir -p pa
@@ -97,7 +109,10 @@ case "$system" in
97109
mpirun -n 1 --bind-to core --map-by ppr:1:node:PE=72 ./main 32 6 4 3 1 1 1 1 -1 -1 6 50 > CASE0
98110
./check.sh CASE0 data/CASE0
99111
FOM=$(grep etime CASE0 | awk 'NR==2{printf("%5.3f\n",$5)}')
100-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes >> ../results/result
112+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes numproc_node:1 >> ../results/result
113+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
114+
echo "SECTION:communication time:0.20" >> ../results/result
115+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
101116
#echo FOM:11.22 FOM_version:dummy_qc-gh200 Exp:confidential_null node_count:$nodes >> ../results/result
102117
# with confidential key
103118
#echo FOM:11.22 FOM_version:dummy_qc-gh200 Exp:confidential_TeamA node_count:$nodes confidential:TeamA>> ../results/result
@@ -112,7 +127,10 @@ case "$system" in
112127
mpirun -n 1 --bind-to core --map-by ppr:1:node:PE=96 ./main 32 6 4 3 1 1 1 1 -1 -1 6 50 > CASE0
113128
./check.sh CASE0 data/CASE0
114129
FOM=$(grep etime CASE0 | awk 'NR==2{printf("%5.3f\n",$5)}')
115-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes >> ../results/result
130+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes numproc_node:1 >> ../results/result
131+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
132+
echo "SECTION:communication time:0.20" >> ../results/result
133+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
116134
;;
117135
MiyabiG|MiyabiC)
118136
echo "Executing MiyabiG/MiyabiC benchmark..." >> "$DEBUG_LOG"
@@ -124,7 +142,10 @@ case "$system" in
124142
echo "check.sh completed with exit code: $?" >> "$DEBUG_LOG"
125143
FOM=$(grep etime CASE0 | awk 'NR==2{printf("%5.3f\n",$5)}')
126144
echo "Extracted FOM: $FOM" >> "$DEBUG_LOG"
127-
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes >> ../results/result
145+
echo FOM:$FOM FOM_version:DDSolverJacobi Exp:CASE0 node_count:$nodes numproc_node:1 >> ../results/result
146+
echo "SECTION:compute_kernel time:0.30" >> ../results/result
147+
echo "SECTION:communication time:0.20" >> ../results/result
148+
echo "OVERLAP:compute_kernel,communication time:0.05" >> ../results/result
128149
echo "Result written to ../results/result" >> "$DEBUG_LOG"
129150
;;
130151
*)

result_server/routes/api.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from flask import Blueprint, request, abort, current_app, jsonify
1616
import os
1717
import json
18+
import re
1819
import uuid
1920
import shutil
2021
from datetime import datetime
@@ -192,6 +193,23 @@ def query_result():
192193
if exp is not None and data.get("Exp") != exp:
193194
continue
194195

196+
# Add _meta with timestamp and uuid extracted from filename
197+
ts_match = re.search(r"\d{8}_\d{6}", json_file)
198+
meta_timestamp = None
199+
if ts_match:
200+
try:
201+
ts = datetime.strptime(ts_match.group(), "%Y%m%d_%H%M%S")
202+
meta_timestamp = ts.strftime("%Y-%m-%d %H:%M:%S")
203+
except Exception:
204+
pass
205+
206+
uuid_match = re.search(
207+
r"[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}",
208+
json_file, re.IGNORECASE,
209+
)
210+
meta_uuid = uuid_match.group(0) if uuid_match else None
211+
212+
data["_meta"] = {"timestamp": meta_timestamp, "uuid": meta_uuid}
195213
return jsonify(data), 200
196214

197215
abort(404, description=f"No result found for system={system}, code={code}, exp={exp}")

0 commit comments

Comments
 (0)