(
cls,
bias: torch.fx.Node,
weight_quantizer: Optional[QuantParams],
input_quantizer: Optional[QuantParams],
)
| 372 | |
| 373 | @classmethod |
| 374 | def from_bias( |
| 375 | cls, |
| 376 | bias: torch.fx.Node, |
| 377 | weight_quantizer: Optional[QuantParams], |
| 378 | input_quantizer: Optional[QuantParams], |
| 379 | ) -> Optional[QuantParams]: |
| 380 | if weight_quantizer is None or input_quantizer is None: |
| 381 | check_or_raise( |
| 382 | weight_quantizer is None and input_quantizer is None, |
| 383 | "Weight and Input should both be quantized", |
| 384 | ) |
| 385 | return None |
| 386 | |
| 387 | if input_quantizer.is_dynamic: |
| 388 | # No need to quantize bias for dyanamic quantization |
| 389 | return None |
| 390 | |
| 391 | check_or_raise( |
| 392 | not input_quantizer.per_channel, |
| 393 | "Input can not be quantized per channel", |
| 394 | ) |
| 395 | |
| 396 | # Only per_tensor quantization is supported for input here |
| 397 | check_or_raise( |
| 398 | isinstance(input_quantizer.scale, float), |
| 399 | f"q_input scale should be float, but got {input_quantizer.scale}", |
| 400 | ) |
| 401 | return cls( |
| 402 | per_channel=weight_quantizer.per_channel, |
| 403 | q_input=bias, |
| 404 | scale=weight_quantizer.scale * cast(float, input_quantizer.scale), |
| 405 | zp=weight_quantizer.zp * 0, |
| 406 | axis=0, # not using weight_quantizer.axis because bias is always of shape [out_channels] i.e. 1D |
| 407 | dtype=torch.int32, |
| 408 | qmin=-(2**31), |
| 409 | qmax=(2**31) - 1, |
| 410 | is_output=False, |
| 411 | is_input=False, |
| 412 | ) |
no test coverage detected