Skip to content

Commit 15914d2

Browse files
[Torch] Lora kernels compilation
1 parent 0926d96 commit 15914d2

3 files changed

Lines changed: 81 additions & 30 deletions

File tree

src/nncf/torch/quantization/quantize_functions.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from nncf.torch.quantization.extensions import QuantizedFunctionsCPU
2020
from nncf.torch.quantization.extensions import QuantizedFunctionsCUDA
2121
from nncf.torch.quantization.reference import ReferenceQuantizedFunctions as RQ
22+
from nncf.torch.utils import CompilationWrapper
2223
from nncf.torch.utils import add_ov_domain
2324

2425

@@ -302,6 +303,32 @@ def asymmetric_quantize_lora(
302303
)
303304
if skip:
304305
return input_
306+
return _asymmetric_quantize_lora(
307+
input_,
308+
input_shape,
309+
A,
310+
B,
311+
input_low_,
312+
input_range_,
313+
level_low,
314+
level_high,
315+
levels,
316+
eps,
317+
)
318+
319+
320+
def _asymmetric_quantize_lora(
321+
input_,
322+
input_shape,
323+
A,
324+
B,
325+
input_low_,
326+
input_range_,
327+
level_low,
328+
level_high,
329+
levels,
330+
eps,
331+
):
305332
input_range_safe = abs(input_range_) + eps
306333
input_low, input_range = TuneRange.apply(input_low_, input_range_safe, levels)
307334
input_ = (input_ + B @ A).type(input_.dtype) # input(float16) + lora(bfloat16) = float32, need a cast to float16
@@ -334,6 +361,10 @@ def symmetric_quantize_lora(input_, input_shape, A, B, scale, level_low, level_h
334361
)
335362
if skip:
336363
return input_
364+
return _symmetric_quantize_lora(input_, input_shape, A, B, scale, level_low, level_high, levels, eps)
365+
366+
367+
def _symmetric_quantize_lora(input_, input_shape, A, B, scale, level_low, level_high, levels, eps):
337368
scale_safe = torch.where(torch.abs(scale) < eps, eps, scale)
338369
input_ = (input_ + B @ A).type(input_.dtype) # input(float16) + lora(bfloat16) = float32, need a cast to float16
339370
return QuantizeSymmetricTorch.apply(
@@ -471,3 +502,7 @@ def unpack_int4(packed_tensor: torch.Tensor) -> torch.Tensor:
471502
"""
472503
t = unpack_uint4(packed_tensor)
473504
return t.type(torch.int8) - 8
505+
506+
507+
_asymmetric_quantize_lora = CompilationWrapper(_asymmetric_quantize_lora)
508+
_symmetric_quantize_lora = CompilationWrapper(_symmetric_quantize_lora)

src/nncf/torch/quantization/reference.py

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,34 +21,6 @@
2121
GeneralizedTensor = TypeVar("GeneralizedTensor", torch.Tensor, np.ndarray)
2222

2323

24-
def fp32_accum_wrapper(func):
25-
def wrapper(tensor_to_sum, ret_tensor):
26-
half = tensor_to_sum.dtype == np.float16
27-
if half:
28-
tensor_to_sum = tensor_to_sum.astype(np.float32)
29-
retval = func(tensor_to_sum, ret_tensor)
30-
if half:
31-
retval = retval.astype(np.float16)
32-
return retval
33-
34-
return wrapper
35-
36-
37-
@fp32_accum_wrapper
38-
def sum_like(tensor_to_sum, ref_tensor):
39-
"""Warning: may modify tensor_to_sum"""
40-
if ref_tensor.size == 1:
41-
return tensor_to_sum.sum()
42-
43-
for dim, size in enumerate(ref_tensor.shape):
44-
if size == 1:
45-
if isinstance(tensor_to_sum, np.ndarray):
46-
tensor_to_sum = tensor_to_sum.sum(dim, keepdims=True)
47-
else:
48-
tensor_to_sum = tensor_to_sum.sum(dim, keepdim=True)
49-
return tensor_to_sum
50-
51-
5224
class ReferenceBackendType(Enum):
5325
NUMPY = "numpy"
5426
TORCH = "torch"
@@ -79,6 +51,46 @@ def _reciprocal(self, tensor: GeneralizedTensor) -> GeneralizedTensor:
7951
return np.reciprocal(tensor)
8052
return torch.reciprocal(tensor)
8153

54+
def _sum_like(self, tensor_to_sum: GeneralizedTensor, ref_tensor: GeneralizedTensor):
55+
"""Warning: may modify tensor_to_sum"""
56+
if self.backend is np:
57+
half = tensor_to_sum.dtype == np.float16
58+
if half:
59+
tensor_to_sum = tensor_to_sum.astype(np.float32)
60+
retval = self._sum_like_fp32(tensor_to_sum, ref_tensor)
61+
if half:
62+
retval = retval.astype(np.float16)
63+
return retval
64+
65+
half = tensor_to_sum.dtype == torch.float16
66+
if half:
67+
tensor_to_sum = tensor_to_sum.type(torch.float32)
68+
retval = self._sum_like_fp32(tensor_to_sum, ref_tensor)
69+
if half:
70+
retval = retval.type(torch.float16)
71+
return retval
72+
73+
def _sum_like_fp32(self, tensor_to_sum: GeneralizedTensor, ref_tensor: GeneralizedTensor):
74+
"""Warning: may modify tensor_to_sum"""
75+
if self.backend is np:
76+
n_elements = ref_tensor.size
77+
if n_elements == 1:
78+
return tensor_to_sum.sum()
79+
80+
for dim, size in enumerate(ref_tensor.shape):
81+
if size == 1:
82+
tensor_to_sum = tensor_to_sum.sum(dim, keepdims=True)
83+
return tensor_to_sum
84+
85+
n_elements = ref_tensor.numel()
86+
if n_elements == 1:
87+
return tensor_to_sum.sum()
88+
89+
for dim, size in enumerate(ref_tensor.shape):
90+
if size == 1:
91+
tensor_to_sum = tensor_to_sum.sum(dim, keepdim=True)
92+
return tensor_to_sum
93+
8294
def forward(
8395
self, input_: GeneralizedTensor, input_low: GeneralizedTensor, input_range: GeneralizedTensor, levels: int
8496
) -> GeneralizedTensor:
@@ -114,12 +126,12 @@ def backward(
114126
output = self.forward(input_, input_low, input_range, levels)
115127
err = (output - input_) * self._reciprocal(input_range * range_sign)
116128
grad_range = grad_output * (err * mask_in + range_sign * (level_low / level_high) * mask_lo + mask_hi)
117-
grad_range = sum_like(grad_range, input_range)
129+
grad_range = self._sum_like(grad_range, input_range)
118130

119131
grad_input = grad_output * mask_in
120132

121133
grad_low = grad_output * (mask_hi + mask_lo)
122-
grad_low = sum_like(grad_low, input_low)
134+
grad_low = self._sum_like(grad_low, input_low)
123135
return [grad_input, grad_low, grad_range]
124136

125137
def tune_range(

src/nncf/torch/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ def __call__(self, *args: Any, **kwargs: Any) -> Any:
171171
172172
:return: Result of the function call.
173173
"""
174+
# Prevent nested compilation
175+
if torch.compiler.is_compiling():
176+
return self._func(*args, **kwargs)
177+
174178
if self._compiled_func is None:
175179
try:
176180
self._compiled_func = torch.compile(self._func)

0 commit comments

Comments
 (0)