项目文件夹

文件
wehub-resource-sync 593b94c120
pytest / Unit Tests (push) Has been cancelled
pytest / Integration (integration_tests_a) (push) Has been cancelled
pytest / Integration (integration_tests_b) (push) Has been cancelled
pytest / Integration (integration_tests_c) (push) Has been cancelled
pytest / Integration (integration_tests_d) (push) Has been cancelled
pytest / Integration (integration_tests_e) (push) Has been cancelled
pytest / Integration (integration_tests_f) (push) Has been cancelled
pytest / Integration (integration_tests_g) (push) Has been cancelled
pytest / Integration (integration_tests_h) (push) Has been cancelled
pytest / Integration (integration_tests_i) (push) Has been cancelled
pytest / Integration (integration_tests_j) (push) Has been cancelled
pytest / Distributed (distributed_a) (push) Has been cancelled
pytest / Distributed (distributed_b) (push) Has been cancelled
pytest / Distributed (distributed_c) (push) Has been cancelled
pytest / Distributed (distributed_d) (push) Has been cancelled
pytest / Distributed (distributed_e) (push) Has been cancelled
pytest / Distributed (distributed_f) (push) Has been cancelled
pytest / Minimal Install (push) Has been cancelled
pytest / Event File (push) Has been cancelled
pytest (slow) / py-slow (push) Has been cancelled
Publish JSON Schema / publish-schema (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:49:20 +08:00

127 行
5.1 KiB
Python

import logging
from collections import OrderedDict
import numpy as np
import torch
logger = logging.getLogger(__name__)
NUMPY_TO_TORCH_DTYPE = {
bool: torch.bool,
np.bool_: torch.bool,
np.uint8: torch.uint8,
np.int8: torch.int8,
np.int16: torch.int16,
np.int32: torch.int32,
np.int64: torch.int64,
np.float16: torch.float16,
np.float32: torch.float32,
np.float64: torch.float64,
np.complex64: torch.complex64,
np.complex128: torch.complex128,
}
def extract_tensors(model: torch.nn.Module) -> tuple[torch.nn.Module, list[dict]]:
"""Remove the tensors from a PyTorch model, convert them to NumPy arrays, and return the stripped model and
tensors.
Reference implementation: https://medium.com/ibm-data-ai/how-to-load-pytorch-models-340-times-faster-with-
ray-8be751a6944c # noqa
"""
tensors = []
for _, module in model.named_modules():
# Store the tensors as numpy arrays in Python dictionaries
# Delete the same tensors since we no longer need them and we want to reduce memory pressure.
# This ensures that throughout this process, we keep memory nearly linear w.r.t model parameters.
params = OrderedDict()
buffers = OrderedDict()
for name, param in module.named_parameters(recurse=False):
params[name] = torch.clone(param).detach().numpy()
del param
for name, buf in module.named_buffers(recurse=False):
buffers[name] = torch.clone(buf).detach().numpy()
del buf
tensors.append({"params": params, "buffers": buffers})
# Strip all tensors and buffers out of the original model.
for _, module in model.named_modules():
for name in [name for name, _ in module.named_parameters(recurse=False)] + [
name for name, _ in module.named_buffers(recurse=False)
]:
setattr(module, name, None)
return model, tensors
def replace_tensors(m: torch.nn.Module, tensors: list[dict], device: torch.device):
"""Restore the tensors that extract_tensors() stripped out of a PyTorch model. This operation is performed in
place.
Reference implementation: https://medium.com/ibm-data-ai/how-to-load-pytorch-models-340-times-faster-with-
ray-8be751a6944c # noqa
"""
modules = [module for _, module in m.named_modules()]
for module, tensor_dict in zip(modules, tensors):
# There are separate APIs to set parameters and buffers.
for name, array in tensor_dict["params"].items():
module.register_parameter(
name,
torch.nn.Parameter(torch.as_tensor(array, device=device, dtype=NUMPY_TO_TORCH_DTYPE.get(array.dtype))),
)
for name, array in tensor_dict["buffers"].items():
module.register_buffer(
name,
torch.as_tensor(array, device=device, dtype=NUMPY_TO_TORCH_DTYPE.get(array.dtype)),
)
def find_embedding_layer_with_path(module, module_names: list[str] | None = None):
"""Recursively search through a module to find an embedding layer and its module path.
Returns a tuple containing the embedding layer and its module path.
"""
if module_names is None:
module_names = []
for name, child_module in module.named_children():
if isinstance(child_module, torch.nn.Embedding):
# If an embedding layer is found, return it along with the module path
return child_module, ".".join(module_names + [name])
else:
# Recursively search in the child module and update the module_names list
found, path = find_embedding_layer_with_path(child_module, module_names + [name])
if found is not None:
return found, path
return None, None
def contains_nan_or_inf_tensors(module: torch.nn.Module) -> bool:
"""Check for NaN or infinity (inf) values in the tensors (parameters and buffers) of a PyTorch module. This
function recursively inspects the module's parameters and buffers to identify NaN or inf values. It is designed
to ensure the numerical stability of the model by detecting any irregularities in the tensor values.
Parameters:
module (torch.nn.Module): The PyTorch module to check for NaN or inf values.
Returns:
bool: Returns True if any NaN or inf values are found in the module's tensors. Otherwise, returns False.
"""
for name, param in module.named_parameters():
if param.requires_grad and (torch.isnan(param).any() or torch.isinf(param).any()):
logger.info(f"Found NaN or inf values in parameter '{name}' of module '{module.__class__.__name__}'")
return True
for name, buffer in module.named_buffers():
if torch.isnan(buffer).any() or torch.isinf(buffer).any():
logger.info(f"Found NaN or inf values in buffer '{name}' of module '{module.__class__.__name__}'")
return True
for name, submodule in module.named_children():
if contains_nan_or_inf_tensors(submodule):
logger.info(f"Found NaN or inf values in submodule '{name}' of module '{module.__class__.__name__}'")
return True
return False