Download scripts/print_efficiency.py from KCBtheone/SplatAtlas: direct link, hf CLI and curl.
- Browser
- Download file 5.39 kB
-
https://huggingface.co/KCBtheone/SplatAtlas/resolve/main/scripts/print_efficiency.py
- Command line
-
hf download hf://KCBtheone/SplatAtlas/scripts/print_efficiency.py
-
curl -L -o print_efficiency.py https://huggingface.co/KCBtheone/SplatAtlas/resolve/main/scripts/print_efficiency.py
5.39 kB
| #!/usr/bin/env python3 | |
| """ | |
| Print Gaussian count, timing, and VRAM for all our completed experiments. | |
| Data sources (in priority order): | |
| - Gaussian count : PLY header (element vertex N) | |
| - iter_time_ms : TensorBoard train/iter_time_ms (last value) | |
| - peak_vram_GB : TensorBoard train/peak_vram_GB (max across run) | |
| - timing fallback : timing.json cumulative_gpu_time_sec / iters | |
| Usage: | |
| python scripts/print_efficiency.py | |
| """ | |
| import os | |
| import json | |
| import glob | |
| import numpy as np | |
| OUTPUTS_ROOT = "/root/autodl-tmp/SplatAtlas/outputs" | |
| ITERS = 30000 | |
| KNOWN = ("vanillasgf", "vanilla_3dgs", "vanilla_logged", "vanilla_thresh", | |
| "absgs", "pixelgs", "edgeloss") | |
| OUTDOOR_360 = {"bicycle", "flowers", "garden", "stump", "treehill"} | |
| INDOOR_360 = {"bonsai", "counter", "kitchen", "room"} | |
| TNT = { | |
| "auditorium", "ballroom", "courtroom", "family", "francis", "horse", | |
| "lighthouse", "m60", "museum", "palace", "panther", "playground", | |
| "temple", "train" | |
| } | |
| ALL_SCENES = OUTDOOR_360 | INDOOR_360 | TNT | |
| def is_ours(method): | |
| return any(method == p or method.startswith(p) for p in KNOWN) | |
| def parse_dir(d): | |
| if d.startswith("vanilla_thresh_"): | |
| rest = d[len("vanilla_thresh_"):] | |
| for s in ALL_SCENES: | |
| if rest == s or rest.startswith(s + "_"): | |
| return "vanilla_thresh", s | |
| return None, None | |
| tok = d.split("_") | |
| for i in range(len(tok) - 1, 0, -1): | |
| sc = "_".join(tok[i:]) | |
| me = "_".join(tok[:i]) | |
| if sc in ALL_SCENES: | |
| return me, sc | |
| return None, None | |
| def count_gaussians(ply_path): | |
| try: | |
| with open(ply_path, "rb") as f: | |
| for line in f: | |
| line = line.decode("ascii", errors="ignore").strip() | |
| if line.startswith("element vertex"): | |
| return int(line.split()[-1]) | |
| if line == "end_header": | |
| break | |
| except Exception: | |
| pass | |
| return None | |
| def read_tb(model_path): | |
| """Read last iter_time_ms and max peak_vram_GB from TensorBoard events.""" | |
| try: | |
| from tensorboard.backend.event_processing.event_accumulator import EventAccumulator | |
| ea = EventAccumulator(model_path, size_guidance={"scalars": 0}) | |
| ea.Reload() | |
| tags = ea.Tags().get("scalars", []) | |
| it_ms = None | |
| for tag in ["train/iter_time_ms", "iter_time_ms"]: | |
| if tag in tags: | |
| vals = ea.Scalars(tag) | |
| if vals: | |
| # mean of last 10% steps (stable phase) | |
| n = max(1, len(vals) // 10) | |
| it_ms = float(np.mean([v.value for v in vals[-n:]])) | |
| break | |
| vram = None | |
| for tag in ["train/peak_vram_GB", "peak_vram_GB"]: | |
| if tag in tags: | |
| vals = ea.Scalars(tag) | |
| if vals: | |
| vram = float(max(v.value for v in vals)) | |
| break | |
| return it_ms, vram | |
| except Exception: | |
| return None, None | |
| def read_timing_json(model_path, iters): | |
| """Fallback: cumulative_gpu_time_sec from timing.json.""" | |
| try: | |
| p = os.path.join(model_path, "timing.json") | |
| d = json.load(open(p)) | |
| cgt = d.get("cumulative_gpu_time_sec") | |
| if cgt: | |
| return float(cgt) / iters * 1000 # ms/iter | |
| except Exception: | |
| pass | |
| return None | |
| def main(): | |
| plys = sorted(glob.glob( | |
| f"{OUTPUTS_ROOT}/*/point_cloud/iteration_{ITERS}/point_cloud.ply")) | |
| rows = [] | |
| for ply_path in plys: | |
| parts = ply_path.split("/") | |
| dirname = parts[-4] | |
| method, scene = parse_dir(dirname) | |
| if method is None or not is_ours(method): | |
| continue | |
| model_path = os.path.join(OUTPUTS_ROOT, dirname) | |
| n_gauss = count_gaussians(ply_path) | |
| it_ms, vram = read_tb(model_path) | |
| if it_ms is None: | |
| it_ms = read_timing_json(model_path, ITERS) | |
| rows.append((dirname, method, scene, n_gauss, it_ms, vram)) | |
| # ββ Print ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\n{'Dir':<42} {'#Gauss':>10} {'ms/iter':>9} {'PeakGB':>8}") | |
| print("-" * 73) | |
| by_method = {} | |
| for dirname, method, scene, n, t, v in rows: | |
| ns = f"{n:,}" if n else "-" | |
| ts = f"{t:.2f}" if t else "-" | |
| vs = f"{v:.3f}" if v else "-" | |
| print(f"{dirname:<42} {ns:>10} {ts:>9} {vs:>8}") | |
| by_method.setdefault(method, []).append((n, t, v)) | |
| # ββ Per-method averages ββββββββββββββββββββββββββββββββββββββββββββββββ | |
| print(f"\n{'Method':<35} {'Avg #Gauss':>11} {'Avg ms/iter':>12} {'Avg PeakGB':>11} {'N':>4}") | |
| print("-" * 67) | |
| for m, vals in sorted(by_method.items()): | |
| ns = [x[0] for x in vals if x[0] is not None] | |
| ts = [x[1] for x in vals if x[1] is not None] | |
| vs = [x[2] for x in vals if x[2] is not None] | |
| nav = f"{int(np.mean(ns)):,}" if ns else "-" | |
| tav = f"{np.mean(ts):.2f}" if ts else "-" | |
| vav = f"{np.mean(vs):.3f}" if vs else "-" | |
| print(f"{m:<35} {nav:>11} {tav:>12} {vav:>11} {len(vals):>4}") | |
| if __name__ == "__main__": | |
| main() | |