@@ -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