Repository navigation
XNNPACK: fix enable_bf16 load failures and BatchNorm folding into a 3-D linear output #24464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
aebfa9b
e7fa599
fdbbcb5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,13 @@ class ConfigPrecisionType(Enum): | |
| DYNAMIC_QUANT = 3 | ||
|
|
||
|
|
||
| def _input_and_output_values(node: torch.fx.Node) -> List[object]: | ||
| values = [arg.meta.get("val") for arg in node.all_input_nodes] | ||
| node_val = node.meta.get("val") | ||
| values.extend(node_val if isinstance(node_val, (list, tuple)) else [node_val]) | ||
| return values | ||
|
|
||
|
|
||
| class XNNPartitionerConfig(PartitionerConfig): | ||
| """ | ||
| Base partitioner config for XNNPACK Partitioner Configs. Base wrapper class | ||
|
|
@@ -45,6 +52,11 @@ class XNNPartitionerConfig(PartitionerConfig): | |
| types they want to enable | ||
| """ | ||
|
|
||
| # At the pinned XNNPACK commit, some ops are defined only for fp32 and fp16 | ||
| # tensors. Their configs set this to False, so their bf16 nodes stay on the | ||
| # portable kernels instead of failing when the program loads. | ||
| supports_bf16 = True | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: since this is opt-out, a new config whose XNNPACK define rejects bf16 will still be partitioned and fail only at load. A test that walks
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the I kept the default at |
||
|
|
||
| def __init__(self, **kwargs): | ||
| super().__init__() | ||
| self.enabled_precision_types = self.supported_precision_types() | ||
|
|
@@ -168,6 +180,13 @@ def check_common_constraints( | |
| why(node, reason="not enabled precision types") | ||
| return False | ||
|
|
||
| if not self.supports_bf16 and any( | ||
| isinstance(val, torch.Tensor) and val.dtype == torch.bfloat16 | ||
| for val in _input_and_output_values(node) | ||
| ): | ||
| why(node, reason="XNNPACK does not support bf16 for this op") | ||
| return False | ||
|
|
||
| has_valid_dtypes = self._check_node_has_valid_dtype(node) | ||
| if not has_valid_dtypes: | ||
| why(node, reason="invalid dtype") | ||
|
|
@@ -176,10 +195,7 @@ def check_common_constraints( | |
| return self._check_tensor_ranks(node) | ||
|
|
||
| def _check_tensor_ranks(self, node: torch.fx.Node) -> bool: | ||
| vals = [arg.meta.get("val") for arg in node.all_input_nodes] | ||
| node_val = node.meta.get("val") | ||
| vals.extend(node_val if isinstance(node_val, (list, tuple)) else [node_val]) | ||
| for val in vals: | ||
| for val in _input_and_output_values(node): | ||
| if isinstance(val, torch.Tensor) and val.dim() > XNN_MAX_TENSOR_DIMS: | ||
| why( | ||
| node, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the pinned XNNPACK, softmax, mean, pooling and resize fail only at define time (e.g.
subgraph/softmax.c:165).xnn_subgraph_fallback_from_bf16_to_fp32would otherwise rewrite them to fp32 with converts.GetOpActionBf16returnskRewritefor them, and also for FC and BMM, so linear and bmm already run as fp32 GEMMs. Did you consider defining these ops in fp32 in XNNCompiler with converts around them, like you do for bmm here? That would keep a bf16 attention block in one delegate instead of running softmax on single-threaded portable between two partitions. Happy for that to be a follow-up, but if we keep the flags, it'd help to note that they're tied to the XNNPACK pin.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, that is a good follow-up. It would keep softmax in XNNPACK instead of on the single-threaded portable kernel. It would not put this block into 1 delegate, though: the expand copies from the 3-D matmul split it into 3 delegates in fp32 too. I left it for a follow-up, as you suggested. The comment on
supports_bf16now ties the flags to the pinned XNNPACK commit.