Skip to content

Commit 4c843f4

Browse files
committed
Add custom D3.js memory visualization backend
Add `viz="d3"` option to `save_memory_snapshot` and `attach_oom_observer` that produces an interactive stacked polygon timeline matching PyTorch's MemoryViz layout algorithm. Allocations stack from the bottom and collapse when freed, with color-coded blocks, full C++/Python stack traces, HWM toggle, zoom/pan, and click-to-inspect detail panel.
1 parent 3c00b6f commit 4c843f4

2 files changed

Lines changed: 617 additions & 5 deletions

File tree

transformer_nuggets/utils/benchmark.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -206,17 +206,22 @@ def __exit__(self, exc_type, exc_val, exc_tb):
206206

207207

208208
@contextmanager
209-
def save_memory_snapshot(file_path: Path | str):
209+
def save_memory_snapshot(file_path: Path | str, viz: str = "torch"):
210210
"""Save a memory snapshot information to a folder
211211
212212
Args:
213213
file_path: The path to the folder to save the snapshot to
214214
will create the folder if it doesn't exist
215+
viz: Visualization backend - "torch" for PyTorch's built-in viz,
216+
"d3" for custom D3.js interactive viz
215217
216218
Usage:
217219
```
218220
with save_memory_snapshot(file_path):
219221
# code to profile
222+
223+
with save_memory_snapshot(file_path, viz="d3"):
224+
# code to profile with custom D3 visualization
220225
```
221226
"""
222227
from transformer_nuggets import init_logging
@@ -243,7 +248,6 @@ def save_memory_snapshot(file_path: Path | str):
243248
if file_path.is_dir():
244249
raise ValueError(f"{file_path} is a directory")
245250

246-
# make parent dir
247251
file_path.parent.mkdir(parents=True, exist_ok=True)
248252
torch.cuda.memory._record_memory_history()
249253
try:
@@ -255,8 +259,18 @@ def save_memory_snapshot(file_path: Path | str):
255259
output_path = file_path / f"_rank_{local_rank}.html"
256260
else:
257261
output_path = file_path.with_suffix(".html")
262+
263+
match viz:
264+
case "torch":
265+
html = torch.cuda._memory_viz.trace_plot(s) # type: ignore
266+
case "d3":
267+
from transformer_nuggets.utils.memory_viz import generate_memory_html
268+
html = generate_memory_html(s)
269+
case _:
270+
raise ValueError(f"Unknown viz backend: {viz!r}, expected 'torch' or 'd3'")
271+
258272
with open(output_path, "w") as f:
259-
f.write(torch.cuda._memory_viz.trace_plot(s)) # type: ignore
273+
f.write(html)
260274
logger.info(f"💾 Trace file 📄 saved to: {bcolors.OKGREEN}{output_path}{bcolors.ENDC}")
261275

262276

@@ -270,7 +284,11 @@ def _is_distributed():
270284
return False
271285

272286

273-
def attach_oom_observer(save_path: Path | None = None, max_entries: int = 1000000):
287+
def attach_oom_observer(
288+
save_path: Path | None = None,
289+
max_entries: int = 1000000,
290+
viz: str = "torch",
291+
):
274292
"""
275293
Attach an out-of-memory (OOM) observer to the CUDA device.
276294
The observer will save a memory snapshot when an OOM error occurs.
@@ -280,6 +298,7 @@ def attach_oom_observer(save_path: Path | None = None, max_entries: int = 100000
280298
The cwd will be used.
281299
max_entries (int): Maximum number of memory history entries to record.
282300
Default is 1000000.
301+
viz: Visualization backend - "torch" or "d3"
283302
284303
Usage:
285304
```
@@ -309,8 +328,18 @@ def oom_observer(device, alloc, device_alloc, device_free):
309328

310329
logging.info("Saving allocated state during OOM")
311330
snapshot = torch.cuda.memory._snapshot()
331+
332+
match viz:
333+
case "torch":
334+
html = torch.cuda._memory_viz.trace_plot(snapshot) # type: ignore
335+
case "d3":
336+
from transformer_nuggets.utils.memory_viz import generate_memory_html
337+
html = generate_memory_html(snapshot)
338+
case _:
339+
html = torch.cuda._memory_viz.trace_plot(snapshot) # type: ignore
340+
312341
with open(current_trace_name, "w") as f:
313-
f.write(torch.cuda._memory_viz.trace_plot(snapshot)) # type: ignore
342+
f.write(html)
314343
logging.info(f"Wrote memory snapshot to {current_trace_name}")
315344
except Exception as e:
316345
logging.error(f"Failed to save memory snapshot: {e}")

0 commit comments

Comments
 (0)