minimind/mem_utils.py

97 lines
3.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
一些显存调试的工具函数
"""
import torch
def get_model_memory_usage(model):
total_param_memory = 0
param_info = {}
for name, param in model.named_parameters():
# 计算单个参数的显存(单位:MB)
param_size = param.data.element_size() * param.data.nelement() / 1024 ** 2
total_param_memory += param_size
param_info[name] = {
"size_mb": f"{param_size:.2f} MB",
"shape": param.shape,
"dtype": param.dtype,
}
param_info["total_param_memory"] = f"{total_param_memory:.2f} MB"
return param_info
def get_optimizer_memory_usage(optimizer):
total_state_memory = 0
state_info = {}
for group in optimizer.param_groups:
for p in group["params"]:
if p in optimizer.state:
state = optimizer.state[p]
for key, value in state.items():
if isinstance(value, torch.Tensor):
# 计算优化器状态张量的显存
state_size = value.element_size() * value.nelement() / 1024 ** 2
total_state_memory += state_size
state_info[f"Param_{id(p)}_{key}"] = {
"size_mb": f"{state_size:.2f} MB",
"shape": value.shape,
"dtype": value.dtype,
}
state_info["total_optimizer_state_memory"] = f"{total_state_memory:.2f} MB"
return state_info
def log_memory_snapshot(model, optimizer, step):
print(f"--- Memory Snapshot (Step {step}) ---")
# 模型参数显存
model_mem = get_model_memory_usage(model)
print("Model Parameters:")
for name, info in model_mem.items():
print(f" {name}: {info}")
# 优化器状态显存
optimizer_mem = get_optimizer_memory_usage(optimizer)
print("\nOptimizer State:")
for name, info in optimizer_mem.items():
print(f" {name}: {info}")
# 总显存占用(模型 + 优化器)
total_memory = float(model_mem["total_param_memory"].split()[0]) + \
float(optimizer_mem["total_optimizer_state_memory"].split()[0])
print(f"\nTotal Memory: {total_memory:.2f} MB")
class ActivationMemoryTracker:
def __init__(self):
self.activation_info = {}
self.hooks = []
def track_activations(self, model):
for name, module in model.named_modules():
hook = module.register_forward_hook(self._hook_fn(name))
self.hooks.append(hook)
def _hook_fn(self, name):
def hook(_, __, output):
# 计算激活值的显存(单位:MB)
if isinstance(output, torch.Tensor):
mem = output.element_size() * output.nelement() / 1024 ** 2
self.activation_info[name] = {
"size_mb": f"{mem:.2f} MB",
"size": mem,
"shape": output.shape,
"dtype": output.dtype,
}
return hook
def clear(self):
for hook in self.hooks:
hook.remove()
self.activation_info = {}
self.hooks = []