Skip to content

Commit e898e72

Browse files
ryan-williamsclaude
andcommitted
Add per-epoch profiling to benchmark, push trigger for iteration
- Track epoch times in `EpochLossCallback` (train epoch start → end) - Print epoch timing breakdown in both CLI (`--verbose`) and Modal benchmark - Shows overhead = wallclock - sum(epoch times) to isolate setup/teardown - Temporary `push: branches: [modal-benchmark-v2]` for GHA iteration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0e4d54f commit e898e72

3 files changed

Lines changed: 28 additions & 0 deletions

File tree

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
name: GPU Benchmark (Modal)
22

33
on:
4+
push:
5+
branches: [modal-benchmark-v2]
46
workflow_dispatch:
57
inputs:
68
gpu:

‎modal/benchmark.py‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,15 @@ def run_benchmark(
220220
log.info("train_loss: %.6f", results["final_train_loss"])
221221
log.info("Wallclock: %.1fs", results["wallclock_s"])
222222
log.info("GPU: %s (Modal)", gpu_type)
223+
epoch_times = results.get("epoch_times", [])
224+
if epoch_times:
225+
for i, t in enumerate(epoch_times):
226+
log.info(" Epoch %d: %.1fs", i, t)
227+
log.info(" Mean epoch: %.1fs", sum(epoch_times) / len(epoch_times))
228+
log.info(
229+
" Overhead (wallclock - sum epochs): %.1fs",
230+
results["wallclock_s"] - sum(epoch_times),
231+
)
223232

224233
return results
225234

‎scripts/e2e_train.py‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,8 +202,19 @@ class EpochLossCallback(Callback):
202202
def __init__(self):
203203
self.epoch_train_losses: list[float] = []
204204
self.epoch_val_losses: list[float] = []
205+
self.epoch_times: list[float] = []
206+
self._epoch_start: float = 0
207+
208+
def on_train_epoch_start(self, _trainer, _pl_module):
209+
from time import monotonic
210+
211+
self._epoch_start = monotonic()
205212

206213
def on_train_epoch_end(self, trainer, _pl_module):
214+
from time import monotonic
215+
216+
if self._epoch_start:
217+
self.epoch_times.append(monotonic() - self._epoch_start)
207218
train_loss = trainer.callback_metrics.get("train_loss_epoch")
208219
if train_loss is not None:
209220
self.epoch_train_losses.append(float(train_loss))
@@ -316,6 +327,7 @@ def on_validation_epoch_end(self, trainer, _pl_module):
316327
"final_train_loss": final_train_loss,
317328
"epoch_val_losses": loss_callback.epoch_val_losses,
318329
"epoch_train_losses": loss_callback.epoch_train_losses,
330+
"epoch_times": loss_callback.epoch_times,
319331
"wallclock_s": train_wallclock,
320332
"wandb_run_url": wandb_run_url,
321333
}
@@ -377,6 +389,11 @@ def main(
377389
echo(f" Final train_loss: {results['final_train_loss']:.6f}")
378390
echo(f" Epoch val_losses: {[f'{v:.6f}' for v in results['epoch_val_losses']]}")
379391
echo(f" Epoch train_losses: {[f'{v:.6f}' for v in results['epoch_train_losses']]}")
392+
epoch_times = results.get("epoch_times", [])
393+
if epoch_times:
394+
echo(f" Epoch times: {[f'{t:.1f}s' for t in epoch_times]}")
395+
echo(f" Mean epoch: {sum(epoch_times) / len(epoch_times):.1f}s")
396+
echo(f" Overhead (wallclock - sum epochs): {results['wallclock_s'] - sum(epoch_times):.1f}s")
380397

381398
echo(f"Final val_loss: {final_val_loss:.6f}")
382399

0 commit comments

Comments
 (0)