-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathutils_optimization.py
More file actions
187 lines (148 loc) · 5.27 KB
/
Copy pathutils_optimization.py
File metadata and controls
187 lines (148 loc) · 5.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
"""
Model optimization utilities: quantization, compilation, and performance enhancements.
"""
import torch
import torch.nn as nn
from typing import Optional, Dict, Any
import logging
logger = logging.getLogger(__name__)
def apply_quantization(
model: nn.Module,
quantization_bits: int = 8,
quantization_type: str = "dynamic"
) -> nn.Module:
"""
Apply quantization to the model.
Args:
model: PyTorch model to quantize
quantization_bits: Number of bits (8 or 4)
quantization_type: Type of quantization ('dynamic', 'static', 'qat')
Returns:
Quantized model
"""
if quantization_bits == 8:
if quantization_type == "dynamic":
logger.info("Applying dynamic 8-bit quantization")
model = torch.quantization.quantize_dynamic(
model, {nn.Linear}, dtype=torch.qint8
)
elif quantization_type == "static":
logger.info("Applying static 8-bit quantization")
# Static quantization requires calibration data
model.eval()
model.qconfig = torch.quantization.get_default_qconfig('fbgemm')
torch.quantization.prepare(model, inplace=True)
# Note: Calibration should be done with actual data
torch.quantization.convert(model, inplace=True)
elif quantization_bits == 4:
logger.info("Applying 4-bit quantization (requires bitsandbytes)")
try:
import bitsandbytes as bnb
# Apply 4-bit quantization to linear layers
for name, module in model.named_modules():
if isinstance(module, nn.Linear):
# Replace with 4-bit quantized linear
model._modules[name] = bnb.nn.Linear4bit(
module.in_features,
module.out_features,
bias=module.bias is not None
)
except ImportError:
logger.warning("bitsandbytes not available, skipping 4-bit quantization")
return model
def apply_torch_compile(
model: nn.Module,
mode: str = "reduce-overhead",
fullgraph: bool = False
) -> nn.Module:
"""
Apply torch.compile for faster inference.
Args:
model: PyTorch model to compile
mode: Compilation mode ('default', 'reduce-overhead', 'max-autotune')
fullgraph: Whether to compile the entire graph
Returns:
Compiled model
"""
if hasattr(torch, "compile"):
logger.info(f"Compiling model with mode={mode}")
try:
model = torch.compile(model, mode=mode, fullgraph=fullgraph)
logger.info("Model compilation successful")
except Exception as e:
logger.warning(f"Model compilation failed: {e}")
else:
logger.warning("torch.compile not available (requires PyTorch 2.0+)")
return model
def apply_gradient_checkpointing(model: nn.Module, enable: bool = True):
"""
Enable gradient checkpointing to save memory during training.
Args:
model: PyTorch model
enable: Whether to enable gradient checkpointing
"""
if enable:
if hasattr(model, "gradient_checkpointing_enable"):
model.gradient_checkpointing_enable()
logger.info("Gradient checkpointing enabled")
else:
logger.warning("Model does not support gradient checkpointing")
def get_model_size_mb(model: nn.Module) -> float:
"""
Calculate model size in megabytes.
Args:
model: PyTorch model
Returns:
Model size in MB
"""
param_size = 0
buffer_size = 0
for param in model.parameters():
param_size += param.nelement() * param.element_size()
for buffer in model.buffers():
buffer_size += buffer.nelement() * buffer.element_size()
size_all_mb = (param_size + buffer_size) / 1024**2
return size_all_mb
def count_parameters(model: nn.Module) -> Dict[str, int]:
"""
Count trainable and total parameters.
Args:
model: PyTorch model
Returns:
Dictionary with parameter counts
"""
trainable = sum(p.numel() for p in model.parameters() if p.requires_grad)
total = sum(p.numel() for p in model.parameters())
return {
"trainable": trainable,
"total": total,
"trainable_millions": trainable / 1e6,
"total_millions": total / 1e6,
}
def optimize_model_for_inference(
model: nn.Module,
use_quantization: bool = False,
quantization_bits: int = 8,
use_torch_compile: bool = False,
compile_mode: str = "reduce-overhead"
) -> nn.Module:
"""
Apply multiple optimizations for inference.
Args:
model: PyTorch model
use_quantization: Whether to apply quantization
quantization_bits: Bits for quantization
use_torch_compile: Whether to compile model
compile_mode: Compilation mode
Returns:
Optimized model
"""
model.eval()
if use_quantization:
model = apply_quantization(model, quantization_bits)
if use_torch_compile:
model = apply_torch_compile(model, mode=compile_mode)
# Set to inference mode
with torch.no_grad():
model.eval()
return model