Skip to content

1st: feat(reportgen): populate v3.0 final results tables (all 8 tables)#826

Draft
FileSystemGuy wants to merge 14 commits into
mainfrom
reportgen-v3-final-results-tables
Draft

1st: feat(reportgen): populate v3.0 final results tables (all 8 tables)#826
FileSystemGuy wants to merge 14 commits into
mainfrom
reportgen-v3-final-results-tables

Conversation

@FileSystemGuy

Copy link
Copy Markdown
Contributor

Summary

Makes mlpstorage reports reportgen emit a data value for every column of the v3.0 user-visible final results tables (all 8 tables). This is the reportgen half of #823 — the tool computed most metrics already but never surfaced the columns the tables need.

Built as one shared foundation + four per-workload metric slices, each landed RED→GREEN (TDD):

  • Task F — System-Under-Test foundation (all 8 tables). New 12-column sut_* group: reads system-description.yaml per row (solution.submission_name, total_rack_units), emits the 4 auto-filled SUT cells + 6 blank-but-present manual placeholders, and resolves the Code/Logs hyperlinks from the run's code-image pointer. Hyperlinks render as <a href> in CSV and {text, href} in JSON.
  • Slice-VDB. New benchmarks/vdb_summary.py (pure build_/write_vdb_summary); the VDB producer now writes a canonical summary.json, and reportgen backfills legacy packages in memory (never mutates a submission package). Emits Read B/W (GiB/s), # Client Nodes, Vector Count/Dimension, Index Type, Recall (%), Queries/s, Query Latency; Storage IOPs present-but-blank (not measured).
  • Slice-KVCache. Adds # Client Nodes from summary['host_count']; the per-option B/W / P95-latency / throughput columns already flow verbatim.
  • Slice-Training. Adds # Client Nodes, # Simulated Accelerators, and Read B/W (GiB/s).
  • Slice-Checkpointing. Adds Checkpoint Mode, # Client Nodes, DP Instances, and Write/Read B/W (GiB/s) + Write/Read Duration (s).

Units (all binary GiB/s, verified against DLIO / benchmark source)

  • VDB Read B/W: bytes/s ÷ 1024³. Recall ×100. Query-latency display = p99.
  • KVCache B/W: already GiB/s — kv_cache/cache.py computes (bytes / 1024³) / duration despite the _gbps field name; no conversion.
  • Training Read B/W: DLIO's train_io_mean_MB_per_second is really MiB/s (statscounter.py computes samples/s × record_size / 1024 / 1024 and logs it "MiB/second"), so GiB/s = value ÷ 1024.
  • Checkpointing B/W: DLIO's *_io_mean_GB_per_second is already GiB/s binary (checkpoint size in GiB ÷ seconds, logged "GiB/second"); no conversion.

Notes for reviewers

  • No submission-package mutation. Metric/param/SUT reads only; VDB legacy backfill is in-memory. Output is written solely to reportgen's own results.{csv,json}.
  • Blank-but-present is used wherever a value is genuinely absent (e.g. a run missing a scalar), rather than dropping the column.
  • Two fixture-vs-reality discrepancies surfaced (not introduced here) that are worth a follow-up: the training and checkpointing test fixtures use synthetic metric keys that real DLIO never emits (train_io_throughput_MB_per_second as a list; checkpoint_read/write_throughput_GB_per_second as lists with no durations). Real DLIO emits scalar train_io_mean_MB_per_second and save/load_checkpoint_io_mean_GB_per_second + _duration_mean_seconds. This PR sources the new final-table columns from the real DLIO keys (read straight from summary.json, since the metadata-complete parse path filters scalars out); the pre-existing checkpoint_mean_of_* columns built on the fabricated keys are left untouched. A separate cleanup could correct those fixtures and the existing training/checkpointing aggregation.
  • Still open (intentionally deferred): the Logs hyperlink points at the code-image dir as a known placeholder pending a future logs-target change.

Testing

All four CI suites pass locally (run separately per the conftest layout):

Suite Result
tests/ 2966 passed, 1 skipped, 13 deselected
mlpstorage_py/tests 890 passed
vdb_benchmark/tests 228 passed
kv_cache_benchmark/tests 238 passed, 2 deselected

Every slice adds RED tests first, then the implementation. Draft while the reviewer weighs in on the fixture-cleanup follow-up and the Logs placeholder.

…F-a)

Assert reportgen emits the shared System-Under-Test block for each
workload row, sourced from system-description.yaml: sut_organization,
sut_name/sut_description as hyperlinks (HTML anchor in CSV, {text,href}
in JSON), sut_rus from total_rack_units, and blank manual-fill
placeholders. Guards the D-10 6-col prefix / D-12 trailing-issues
invariants. Fails until F-a is implemented.
reportgen now emits the v3.0 results-table SUT columns for every workload
row, sourced from the row's system-description.yaml:

- sut_organization (path), sut_rus (total_rack_units)
- sut_name / sut_description as Hyperlink cells -> the system-description
  .yaml / .pdf (repo-root-relative href, Option A)
- sut_public_id / sut_type / sut_access_protocol / sut_availability /
  sut_integrated_client_storage / sut_usable_capacity_tib as
  present-but-blank placeholders (submitter fills manually)

New Hyperlink value type renders as an HTML anchor in results.csv (via
__str__) and a {text,href} object in results.json (via MLPSJsonEncoder;
write_json_file now passes cls=MLPSJsonEncoder). The sut_* group is
ordered right after the D-10 6-col prefix and before metric groups, so
the prefix stays first and 'issues' stays last.

Green: new test_reportgen_sut_block.py + all 4 CI suites pass.
Assert reportgen resolves each run's .mlps-code-image pointer to
code-<hash8> and emits sut_code/sut_logs anchors -> closed/<org>/code-<hash8>/
(Logs a placeholder to the same dir). Missing pointer -> blank, no crash.
Adds sut_code / sut_logs to the SUT block. Each is resolved from the
run leaf's .mlps-code-image pointer via the canonical code_image helpers
(_read_pointer D-61, _pool_dir_name D-62) to a repo-root-relative anchor
-> <category>/<orgname>/code-<hash8>/. Logs is a placeholder pointing at
the same code-image dir for now (future change retargets it). Absent or
malformed pointer -> blank cell, no crash.

Green: 4 CI suites (2942/890/228/238) + test_reportgen_sut_block.py.
…lock (Slice-VDB-a)

vdb_summary module (build/write_vdb_summary): locate native query-phase
statistics.json (single-node root + MPI vectordb/<phase> subdirs), coerce
dict recall to scalar mean_recall, ignore the load phase. Module absent →
import error (RED).

VectorDBBenchmark.metadata['parameters'] must carry the reportgen VDB
identity keys (engine/index_type/num_vectors/dimension); combined_params
was never set so the block is {} → engine None (RED).
…Slice-VDB-a)

Add mlpstorage_py/benchmarks/vdb_summary.py with pure build_vdb_summary /
write_vdb_summary: locate the native query-phase statistics.json
(single-node run root + MPI vectordb/<phase> subdirs), copy it whole,
coerce dict recall to scalar mean_recall; the load phase is excluded.
Directory-in, dict/path-out so reportgen can call it without constructing
a VectorDBBenchmark.

VectorDBBenchmark now sets self.combined_params (engine/index_type/
num_vectors/dimension) so base.get_metadata surfaces them in
metadata['parameters'] — the VDB final-table identity columns reportgen
reads. execute_run best-effort writes summary.json at the run root after a
query run (skipped on --what-if; never fatal).

GREEN for Slice-VDB-a.
reportgen _aggregate_vdb must gain: Read B/W (disk_io.total_bytes_read_per_sec
÷1024³ GiB/s), # Client Nodes (disk_io.host_count), Storage IOPs
(present-but-blank, unmeasured), recall as percentage (×100, incl. dict→scalar
coercion), in-memory legacy backfill from native statistics.json WITHOUT
writing into the package, and identity columns (engine/index_type/num_vectors/
dimension) falling back to persisted metadata['args'] when parameters is empty
(parameters win when present).

BenchmarkRun.run_args must surface metadata['args'] (empty dict when absent).
Existing TestVdbPassThrough recall assertions updated to the percentage form.

10 failing.
…ice-VDB-b)

BenchmarkRunData gains run_args (persisted metadata['args'] snapshot),
populated at all three extractor sites; BenchmarkRun.run_args exposes it.

report_generator._aggregate_vdb now emits the v3.0 VDB final-table columns:
- vdb_read_bw_gibps  (disk_io.total_bytes_read_per_sec ÷ 1024**3, GiB/s)
- vdb_num_client_nodes  (disk_io.host_count)
- vdb_storage_iops  (present-but-blank; not measured)
- vdb_recall  as a percentage (×100), with dict→scalar mean_recall coercion
  on both the summary.json and recall_stats.json paths
- vdb_num_vectors / vdb_dimension / vdb_engine / vdb_index_type via
  parameters-first, persisted-args-fallback (blank only when truly absent)

New _load_vdb_summary backfills legacy packages IN MEMORY via
vdb_summary.build_vdb_summary when summary.json is absent — never writing
into the submission package.

GREEN for Slice-VDB-b.
…VCache)

The v3.0 kvcache final table carries a shared '# Client Nodes' column.
Its source is the top-level host_count field kvcache's _write_run_summary
already persists; reportgen now surfaces it as kvcache_num_client_nodes.

The table's Read/Write B/W (GiB/s) and P95 Read Latency columns already
flow verbatim via the existing per-option flattening: the per-option
aggregated_read/write_bandwidth_gbps values are already GiB/s binary
(kvcache cache.py divides bytes by 1024**3 despite the _gbps name), so
no unit conversion is applied. host_count was the only missing field.
Read B/W (GiB/s), # Client Nodes, # Simulated Accelerators — sourced from
summary.json top-level num_hosts/num_accelerators and DLIO's scalar
train_io_mean_MB_per_second (MiB/s, per statscounter.py 'MiB/second' log).
Emits the v3.0 training final-table columns that the list-valued metric
aggregation did not carry, read straight from each run's summary.json
(the metadata-complete parse path drops them: system_info is never
reconstructed and scalar metrics are filtered out):

  - train_num_client_nodes        <- summary top-level num_hosts
  - train_num_simulated_accelerators <- summary top-level num_accelerators
  - train_read_bw_gibps           <- mean of DLIO's per-run scalar
      train_io_mean_MB_per_second across non-warmup runs, /1024

Read B/W unit: DLIO's train_io_mean_MB_per_second is MiB/s despite the
'MB' label (statscounter.py computes samples/s * record_size / 1024/1024
and logs it as 'MiB/second'), so GiB/s = value / 1024 (binary), matching
the vdb/kvcache slices. Blank-but-present when any run omits the scalar.

Updates the D-13 prefix invariant test: metric-mean columns keep
train_mean_of_; the new final-table columns keep only the train_ group
prefix (preserving column ordering) without mean_of_.
…pointing)

Write/Read B/W (GiB/s, verbatim — already binary) + Write/Read Duration
from DLIO scalars save_/load_checkpoint_io_mean_GB_per_second and
_duration_mean_seconds; # Client Nodes from num_hosts; Checkpoint Mode
from checkpoint.mode param; DP Instances = int(ClosedGPUs/GPUpDP).
…eckpointing)

Emits the v3.0 checkpointing final-table columns, read from each run's
summary.json (the metadata-complete parse path drops the DLIO scalar
metric keys via its list-only filter, and they are absent from the
fabricated fixtures):

  - checkpoint_num_client_nodes  <- summary top-level num_hosts
  - checkpoint_mode              <- checkpoint.mode param (subset->Subset,
                                    default/absent->Full)
  - checkpoint_dp_instances      <- int(ClosedGPUs/GPUpDP) from
                                    LLM_ALLOWED_VALUES[model]
  - checkpoint_write_bw_gibps    <- save_checkpoint_io_mean_GB_per_second
  - checkpoint_write_duration_secs <- save_checkpoint_duration_mean_seconds
  - checkpoint_read_bw_gibps     <- load_checkpoint_io_mean_GB_per_second
  - checkpoint_read_duration_secs  <- load_checkpoint_duration_mean_seconds

B/W unit: DLIO's *_io_mean_GB_per_second is already GiB/s binary
(checkpoint_size in GiB / seconds, logged 'GiB/second'), so NO conversion
— unlike training's MiB-labelled figure. Blank-but-present when any run
omits a scalar. Existing checkpoint_mean_of_* columns (built on the
fabricated list fixture keys) are left untouched per the agreed scope.
@github-actions

Copy link
Copy Markdown

MLCommons CLA bot All contributors have signed the MLCommons CLA ✍️ ✅

@FileSystemGuy FileSystemGuy changed the title feat(reportgen): populate v3.0 final results tables (all 8 tables) 1st: feat(reportgen): populate v3.0 final results tables (all 8 tables) Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant