-
Notifications
You must be signed in to change notification settings - Fork 525
Add some basic xnnpack recipes #10035
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
base: gh/tarun292/5/base
Are you sure you want to change the base?
Changes from all commits
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 |
---|---|---|
@@ -0,0 +1,18 @@ | ||
load("@fbcode_macros//build_defs:python_library.bzl", "python_library") | ||
|
||
|
||
oncall("executorch") | ||
|
||
python_library( | ||
name = "xnnpack_recipes", | ||
srcs = [ | ||
"recipes.py", | ||
], | ||
deps = [ | ||
"//caffe2:torch", | ||
"//executorch/exir:lib", | ||
"//executorch/backends/transforms:duplicate_dynamic_quant_chain", | ||
"//executorch/backends/xnnpack/quantizer:xnnpack_quantizer", | ||
"//executorch/backends/xnnpack/partition:xnnpack_partitioner", | ||
], | ||
) |
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,51 @@ | ||||||||||
# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. | ||||||||||
|
||||||||||
# pyre-strict | ||||||||||
from typing import Any, Callable | ||||||||||
|
||||||||||
from executorch.backends.transforms.duplicate_dynamic_quant_chain import ( | ||||||||||
duplicate_dynamic_quant_chain_pass, | ||||||||||
DuplicateDynamicQuantChainPass, | ||||||||||
) | ||||||||||
|
||||||||||
from executorch.backends.xnnpack.partition.xnnpack_partitioner import XnnpackPartitioner | ||||||||||
|
||||||||||
from executorch.backends.xnnpack.quantizer.xnnpack_quantizer import ( | ||||||||||
get_symmetric_quantization_config, | ||||||||||
XNNPACKQuantizer, | ||||||||||
) | ||||||||||
from executorch.exir import ExportRecipe | ||||||||||
|
||||||||||
def get_generic_fp32_cpu_recipe() -> ExportRecipe: | ||||||||||
quantizer = XNNPACKQuantizer() | ||||||||||
operator_config = get_symmetric_quantization_config(is_per_channel=False) | ||||||||||
quantizer.set_global(operator_config) | ||||||||||
Comment on lines
+20
to
+22
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.
Suggested change
|
||||||||||
return ExportRecipe( | ||||||||||
name = "fp32_recipe", | ||||||||||
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
Suggested change
|
||||||||||
quantizer = None, | ||||||||||
partitioners=[XnnpackPartitioner()], | ||||||||||
|
||||||||||
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.
Suggested change
|
||||||||||
) | ||||||||||
|
||||||||||
def get_dynamic_quant_recipe() -> ExportRecipe: | ||||||||||
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. organizationally maybe quant recipes can be in a separate folder? |
||||||||||
quantizer = XNNPACKQuantizer() | ||||||||||
operator_config = get_symmetric_quantization_config( | ||||||||||
is_per_channel=True, is_dynamic=True | ||||||||||
) | ||||||||||
quantizer.set_global(operator_config) | ||||||||||
DuplicateDynamicQuantChainPass | ||||||||||
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. i've actually done some work to remove the need for this. I guess it's ok to have for now as it should still work. 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. Let's remove it if not needed? |
||||||||||
return ExportRecipe( | ||||||||||
name = "dynamic_quant_recipe", | ||||||||||
quantizer = quantizer, | ||||||||||
partitioners=[XnnpackPartitioner()], | ||||||||||
pre_edge_transform_passes=duplicate_dynamic_quant_chain_pass, | ||||||||||
) | ||||||||||
|
||||||||||
RECIPE_MAP: dict[str, Callable[[], ExportRecipe]] = { | ||||||||||
"FP32_CPU_ACCELERATED_RECIPE": get_generic_fp32_cpu_recipe, | ||||||||||
"DYNAMIC_QUANT_CPU_ACCELERATED_RECIPE": get_dynamic_quant_recipe, | ||||||||||
Comment on lines
+45
to
+46
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
Suggested change
|
||||||||||
} | ||||||||||
|
||||||||||
def get_xnnpack_recipe(recipe_name:str, **kwargs: Any) -> ExportRecipe: | ||||||||||
assert recipe_name in RECIPE_MAP, f"Recipe {recipe_name} not found." | ||||||||||
return RECIPE_MAP[recipe_name](**kwargs) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. | ||
|
||
# pyre-strict | ||
|
||
import unittest | ||
|
||
import torch | ||
from executorch.backends.xnnpack import get_xnnpack_recipe | ||
from executorch.export import export | ||
from torch.testing._internal.common_quantization import TestHelperModules | ||
|
||
class TestXnnpackRecipes(unittest.TestCase): | ||
def setUp(self) -> None: | ||
super().setUp() | ||
|
||
def tearDown(self) -> None: | ||
super().tearDown() | ||
Comment on lines
+13
to
+17
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. do we need these? |
||
|
||
def test_basic_recipe(self) -> None: | ||
m_eager = TestHelperModules.TwoLinearModule().eval() | ||
example_inputs = [(torch.randn(9, 8),)] | ||
export_session = export( | ||
model=m_eager, | ||
example_inputs=example_inputs, | ||
export_recipe=get_xnnpack_recipe("FP32_CPU_ACCELERATED_RECIPE") | ||
) | ||
export_session.export() | ||
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. will this raise? should we catch it? |
||
|
||
def test_dynamic_quant_recipe(self) -> None: | ||
m_eager = TestHelperModules.TwoLinearModule().eval() | ||
example_inputs = [(torch.randn(9, 8),)] | ||
export_session = export( | ||
model=m_eager, | ||
example_inputs=example_inputs, | ||
export_recipe=get_xnnpack_recipe("DYNAMIC_QUANT_CPU_ACCELERATED_RECIPE") | ||
) | ||
export_session.export() |
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.
if namespaced to XNNPACK then cpu may not be needed?