Skip to content

Commit 0e4d54f

Browse files
ryan-williamsclaude
andcommitted
Fix RhoData trailing-newline bug, add GHA summary, improve WandB naming
- Fix `RhoData`: `strip()` + filter blank lines in filelist parsing (was treating trailing newlines as empty sample IDs → `.CHGCAR`) - Add GHA summary step to Modal benchmark workflow (config table + results, matching EC2 benchmark format) - WandB run names include dataset/samples/timestamp for local runs, GHA run number for CI runs - Print parseable `BENCHMARK_*` output for GHA step summary Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent de96b49 commit 0e4d54f

3 files changed

Lines changed: 67 additions & 7 deletions

File tree

.github/workflows/gpu-benchmark-modal.yml

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
run: uv pip install --system modal
5050

5151
- name: Run benchmark
52+
id: bench
5253
env:
5354
GPU: ${{ inputs.gpu || 'L4' }}
5455
EPOCHS: ${{ inputs.epochs || '5' }}
@@ -58,11 +59,57 @@ jobs:
5859
DATASET: ${{ inputs.dataset || 's3' }}
5960
WANDB_PROJECT: ${{ inputs.wandb_project || 'elf-net-ci' }}
6061
run: |
61-
modal run modal/benchmark.py \
62+
OUTPUT=$(modal run modal/benchmark.py \
6263
--gpu "$GPU" \
6364
--epochs "$EPOCHS" \
6465
--channels "$CHANNELS" \
6566
--residual-blocks "$RESIDUAL_BLOCKS" \
6667
--samples "$SAMPLES" \
6768
--dataset "$DATASET" \
68-
--wandb-project "$WANDB_PROJECT"
69+
--wandb-project "$WANDB_PROJECT" 2>&1 | tee /dev/stderr)
70+
71+
# Parse metrics from output
72+
for key in VAL_LOSS TRAIN_LOSS WALLCLOCK GPU DATASET SAMPLES WANDB_URL; do
73+
val=$(echo "$OUTPUT" | grep -oP "BENCHMARK_${key}=\K.*" || true)
74+
if [ -n "$val" ]; then
75+
echo "BENCHMARK_${key}=${val}" >> "$GITHUB_OUTPUT"
76+
fi
77+
done
78+
79+
- name: Summary
80+
env:
81+
EPOCHS: ${{ inputs.epochs || '5' }}
82+
CHANNELS: ${{ inputs.channels || '32' }}
83+
RESIDUAL_BLOCKS: ${{ inputs.residual_blocks || '16' }}
84+
VAL_LOSS: ${{ steps.bench.outputs.BENCHMARK_VAL_LOSS }}
85+
TRAIN_LOSS: ${{ steps.bench.outputs.BENCHMARK_TRAIN_LOSS }}
86+
WALLCLOCK: ${{ steps.bench.outputs.BENCHMARK_WALLCLOCK }}
87+
GPU: ${{ steps.bench.outputs.BENCHMARK_GPU }}
88+
DATASET: ${{ steps.bench.outputs.BENCHMARK_DATASET }}
89+
SAMPLES: ${{ steps.bench.outputs.BENCHMARK_SAMPLES }}
90+
WANDB_URL: ${{ steps.bench.outputs.BENCHMARK_WANDB_URL }}
91+
WANDB_PROJECT: ${{ inputs.wandb_project || 'elf-net-ci' }}
92+
run: |
93+
echo "## GPU Benchmark Results (Modal)" >> "$GITHUB_STEP_SUMMARY"
94+
echo "" >> "$GITHUB_STEP_SUMMARY"
95+
echo "### Configuration" >> "$GITHUB_STEP_SUMMARY"
96+
echo "| Parameter | Value |" >> "$GITHUB_STEP_SUMMARY"
97+
echo "|-----------|-------|" >> "$GITHUB_STEP_SUMMARY"
98+
echo "| Platform | Modal ($GPU) |" >> "$GITHUB_STEP_SUMMARY"
99+
echo "| Epochs | $EPOCHS |" >> "$GITHUB_STEP_SUMMARY"
100+
echo "| Channels | $CHANNELS |" >> "$GITHUB_STEP_SUMMARY"
101+
echo "| Residual Blocks | $RESIDUAL_BLOCKS |" >> "$GITHUB_STEP_SUMMARY"
102+
echo "| Dataset | $DATASET ($SAMPLES samples) |" >> "$GITHUB_STEP_SUMMARY"
103+
COMMIT_LINK="[\`${GITHUB_SHA::7}\`](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commit/${GITHUB_SHA})"
104+
echo "| Commit | $COMMIT_LINK |" >> "$GITHUB_STEP_SUMMARY"
105+
if [ -n "$WANDB_URL" ]; then
106+
WANDB_RUN_ID=$(echo "$WANDB_URL" | grep -oP '[^/]+$')
107+
echo "| WandB | [$WANDB_PROJECT](https://wandb.ai/PrinceOA/$WANDB_PROJECT) run [$WANDB_RUN_ID]($WANDB_URL) |" >> "$GITHUB_STEP_SUMMARY"
108+
fi
109+
echo "" >> "$GITHUB_STEP_SUMMARY"
110+
echo "### Results" >> "$GITHUB_STEP_SUMMARY"
111+
echo "| Metric | Value |" >> "$GITHUB_STEP_SUMMARY"
112+
echo "|--------|-------|" >> "$GITHUB_STEP_SUMMARY"
113+
echo "| val_loss | $VAL_LOSS |" >> "$GITHUB_STEP_SUMMARY"
114+
echo "| train_loss | $TRAIN_LOSS |" >> "$GITHUB_STEP_SUMMARY"
115+
echo "| Wallclock | ${WALLCLOCK}s |" >> "$GITHUB_STEP_SUMMARY"

modal/benchmark.py

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,6 @@ def run_benchmark(
112112
# Build filelist from files on disk (S3 set has no mp_filelist.txt)
113113
data_dir = ds_root / input_dir
114114
all_ids = sorted(p.stem for p in data_dir.glob("*.CHGCAR"))
115-
all_ids = [s for s in all_ids if s] # filter blanks
116115
log.info("Dataset %r: %d total samples in %s", dataset, len(all_ids), data_dir)
117116

118117
# Filter by file size (avoid OOM on large grids)
@@ -176,7 +175,7 @@ def run_benchmark(
176175
label_link.symlink_to(ds_root / "label")
177176
log.info("Using volume directly (no local copy)")
178177

179-
Path(data_root, "mp_filelist.txt").write_text("\n".join(subset))
178+
Path(data_root, "mp_filelist.txt").write_text("\n".join(subset) + "\n")
180179

181180
# Always use gradient checkpointing (32ch/16blk needs it even for ≤25MB files)
182181
use_grad_ckpt = True
@@ -195,11 +194,14 @@ def run_benchmark(
195194

196195
# Set WandB run name and env vars for platform tagging
197196
import os
197+
import time
198198

199199
os.environ["INSTANCE_TYPE"] = f"modal-{gpu_type}"
200-
# Set workflow-like name so WandB run name is descriptive
200+
# Set workflow-like name so WandB run name is descriptive.
201+
# GHA sets GITHUB_RUN_NUMBER; for local runs, use timestamp.
201202
os.environ["GITHUB_WORKFLOW"] = "Modal Benchmark"
202-
os.environ.setdefault("GITHUB_RUN_NUMBER", f"{dataset}-{samples}s")
203+
if "GITHUB_RUN_NUMBER" not in os.environ:
204+
os.environ["GITHUB_RUN_NUMBER"] = time.strftime("%y%m%d-%H%M")
203205

204206
results = run_training(
205207
channels=channels,
@@ -263,3 +265,14 @@ def main(
263265
results["wallclock_s"],
264266
gpu,
265267
)
268+
269+
# Print parseable output for GHA summary
270+
wandb_url = results.get("wandb_run_url") or ""
271+
print(f"BENCHMARK_VAL_LOSS={results['final_val_loss']:.6f}") # noqa: T201
272+
print(f"BENCHMARK_TRAIN_LOSS={results['final_train_loss']:.6f}") # noqa: T201
273+
print(f"BENCHMARK_WALLCLOCK={results['wallclock_s']:.0f}") # noqa: T201
274+
print(f"BENCHMARK_GPU={gpu}") # noqa: T201
275+
print(f"BENCHMARK_DATASET={dataset}") # noqa: T201
276+
print(f"BENCHMARK_SAMPLES={samples}") # noqa: T201
277+
if wandb_url:
278+
print(f"BENCHMARK_WANDB_URL={wandb_url}") # noqa: T201

src/electrai/dataloader/dataset.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def __init__(self, datapath: str, precision: str, augmentation: bool, **kwargs):
103103
if isinstance(datapath, str) and Path(datapath).is_file():
104104
with Path(datapath).open() as f:
105105
lines = f.readlines()
106-
member_list = [line.replace("\n", "") for line in lines]
106+
member_list = [line.strip() for line in lines if line.strip()]
107107
else:
108108
raise ValueError("No filename found.")
109109

0 commit comments

Comments
 (0)