Skip to content

Commit bdbd699

Browse files
metascroyfacebook-github-bot
authored andcommitted
Enable do_quant_fusion_and_const_prop by default
Summary: This diff enables const_prop + quant fusion during to_executorch by default (do_quant_fusion_and_const_prop: bool = True in ExecuTorchBackendConfig). This requires updating various tests in CI. Differential Revision: D73749914
1 parent e4386c5 commit bdbd699

File tree

8 files changed

+61
-31
lines changed

8 files changed

+61
-31
lines changed

exir/capture/_config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,4 @@ class ExecutorchBackendConfig:
104104
emit_mutable_buffer_names: bool = False
105105

106106
# If set to true, we run quant fusion and constant propagation passes
107-
do_quant_fusion_and_const_prop: bool = False
107+
do_quant_fusion_and_const_prop: bool = True

exir/emit/test/test_emit.py

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -431,8 +431,8 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:
431431
.executorch_program
432432
)
433433
# The value for beta should appear before alpha
434-
self.assertEqual(program.execution_plan[0].values[12].val, Int(3))
435-
self.assertEqual(program.execution_plan[0].values[13].val, Int(2))
434+
self.assertEqual(program.execution_plan[0].values[4].val, Int(3))
435+
self.assertEqual(program.execution_plan[0].values[5].val, Int(2))
436436

437437
def test_kwargs2(self) -> None:
438438
"""Tests that the kwargs are placed in the order specified by
@@ -451,10 +451,10 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:
451451
to_edge(export(f, (x,), strict=True)).to_executorch().executorch_program
452452
)
453453
# The value for right should appear before side
454-
self.assertEqual(program.execution_plan[0].values[6].val, Bool(False))
455-
self.assertEqual(program.execution_plan[0].values[7].val, Bool(True))
456-
self.assertEqual(program.execution_plan[0].values[8].val, String("right"))
457-
self.assertEqual(program.execution_plan[0].values[9].val, Null())
454+
self.assertEqual(program.execution_plan[0].values[3].val, Bool(False))
455+
self.assertEqual(program.execution_plan[0].values[4].val, Bool(True))
456+
self.assertEqual(program.execution_plan[0].values[5].val, String("right"))
457+
self.assertEqual(program.execution_plan[0].values[6].val, Null())
458458

459459
def _assertCallLength(self, program: Program, idx: int, expected_len: int) -> None:
460460
instr_args = program.execution_plan[0].chains[0].instructions[idx].instr_args
@@ -532,24 +532,24 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:
532532
# Check the mul operator's stack trace contains f -> g -> h
533533
self.assertTrue(
534534
"return torch.mul(x, torch.randn(3, 2))"
535-
in program.execution_plan[0].chains[0].stacktrace[1].items[-1].context
535+
in program.execution_plan[0].chains[0].stacktrace[0].items[-1].context
536536
)
537537
self.assertEqual(
538-
program.execution_plan[0].chains[0].stacktrace[1].items[-1].name, "f"
538+
program.execution_plan[0].chains[0].stacktrace[0].items[-1].name, "f"
539539
)
540540
self.assertEqual(
541-
program.execution_plan[0].chains[0].stacktrace[1].items[-2].name, "g"
541+
program.execution_plan[0].chains[0].stacktrace[0].items[-2].name, "g"
542542
)
543543
self.assertEqual(
544-
program.execution_plan[0].chains[0].stacktrace[1].items[-3].name, "forward"
544+
program.execution_plan[0].chains[0].stacktrace[0].items[-3].name, "forward"
545545
)
546546

547547
# Check the sin operator's stack trace contains g -> h
548548
self.assertEqual(
549-
program.execution_plan[0].chains[0].stacktrace[2].items[-1].name, "g"
549+
program.execution_plan[0].chains[0].stacktrace[1].items[-1].name, "g"
550550
)
551551
self.assertEqual(
552-
program.execution_plan[0].chains[0].stacktrace[2].items[-2].name, "forward"
552+
program.execution_plan[0].chains[0].stacktrace[1].items[-2].name, "forward"
553553
)
554554

555555
def test_stacktrace_off(self) -> None:
@@ -878,10 +878,13 @@ def forward(self, x: torch.Tensor) -> torch.Tensor:
878878
.executorch_program.execution_plan[0]
879879
.non_const_buffer_sizes
880880
)
881-
881+
882+
config = ExecutorchBackendConfig(
883+
do_quant_fusion_and_const_prop=False,
884+
)
882885
edge_program_manager = to_edge(export(f, (torch.ones(3, 2),), strict=True))
883886
non_const_buffer_size_without_const_prop_pass = (
884-
edge_program_manager.to_executorch()
887+
edge_program_manager.to_executorch(config)
885888
.executorch_program.execution_plan[0]
886889
.non_const_buffer_sizes
887890
)
@@ -1510,7 +1513,12 @@ def forward(self, x):
15101513
self.assertEqual(model.W1.untyped_storage().nbytes(), 8)
15111514
self.assertEqual(model.W2.nbytes, 4)
15121515
self.assertEqual(model.W2.untyped_storage().nbytes(), 8)
1513-
program = to_edge(export(model, (torch.ones(1),), strict=True)).to_executorch()
1516+
1517+
# Without this, the views get
1518+
config = exir.ExecutorchBackendConfig(
1519+
do_quant_fusion_and_const_prop=False,
1520+
)
1521+
program = to_edge(export(model, (torch.ones(1),), strict=True)).to_executorch(config)
15141522

15151523
program = program._emitter_output.program
15161524
# each emitted weight is not a view
@@ -1531,7 +1539,10 @@ def forward(self, x):
15311539
program = program._emitter_output.program
15321540
# confirm that the buffer was emitted
15331541
self.assertEqual(len(program.constant_buffer), 2)
1534-
self.assertEqual(len(program.constant_buffer[1].storage), 8)
1542+
1543+
# executorch_exir_dialects_edge__ops_dim_order_ops__to_dim_order_copy_default
1544+
# converts the buffer from i64 to fp32 (4 bytes), which gets const propagated
1545+
self.assertEqual(len(program.constant_buffer[1].storage), 4)
15351546

15361547
def test_emit_lifted_tensor_constant(self) -> None:
15371548
class LiftedTensorConstants(nn.Module):
@@ -1544,7 +1555,7 @@ def forward(self, x):
15441555

15451556
model = LiftedTensorConstants()
15461557
# Specify that we want to move non-lifted constants to external file
1547-
et_cfg = ExecutorchBackendConfig(external_constants=True)
1558+
et_cfg = ExecutorchBackendConfig(external_constants=True, do_quant_fusion_and_const_prop=False)
15481559
program = to_edge(
15491560
export(model, (torch.ones(3, 2),), strict=True)
15501561
).to_executorch(et_cfg)
@@ -1566,7 +1577,7 @@ def forward(self, x):
15661577

15671578
model = LiftedConstants()
15681579
# Specify that we want to move non-lifted constants to external file
1569-
et_cfg = ExecutorchBackendConfig(external_constants=True)
1580+
et_cfg = ExecutorchBackendConfig(external_constants=True, do_quant_fusion_and_const_prop=False)
15701581
program = to_edge(
15711582
export(model, (torch.ones(3, 2),), strict=True)
15721583
).to_executorch(et_cfg)
@@ -1658,7 +1669,10 @@ def forward(self, x):
16581669
model = to_edge(export(InfinityMaskModel(), (torch.randn(2, 2),), strict=True))
16591670

16601671
# Confirm that we can serialize the model with infinity in it.
1661-
model = model.to_executorch()
1672+
config = ExecutorchBackendConfig(
1673+
do_quant_fusion_and_const_prop=False,
1674+
)
1675+
model = model.to_executorch(config)
16621676

16631677
# Assert that the infinity is stored as a string "-inf".
16641678
values = model.executorch_program.execution_plan[0].values
@@ -1716,8 +1730,8 @@ def forward(self, x):
17161730
external_map = emitter_output.external_constant_map[
17171731
"_default_external_constant"
17181732
]
1719-
self.assertEqual(external_map["linear.weight"], 0)
1720-
self.assertEqual(external_map["linear.bias"], 1)
1733+
self.assertEqual(external_map["_prop_tensor_constant0"], 1)
1734+
self.assertEqual(external_map["linear.bias"], 0)
17211735

17221736
def test_delegate_deduplicate(self) -> None:
17231737
class SharedModule(torch.nn.Module):
@@ -1804,7 +1818,7 @@ def forward(self, input, label):
18041818
ep = to_edge(ep)
18051819
# Lower the graph to executorch.
18061820
ep = ep.to_executorch(
1807-
config=ExecutorchBackendConfig(external_mutable_weights=True)
1821+
config=ExecutorchBackendConfig(external_mutable_weights=True, do_quant_fusion_and_const_prop=False)
18081822
)
18091823

18101824
emitter_output = ep._emitter_output

exir/tests/test_joint_graph.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import torch
1111
import torch._dynamo
1212

13-
from executorch.exir import to_edge
13+
from executorch.exir import to_edge, ExecutorchBackendConfig
1414

1515
from executorch.extension.pybindings.portable_lib import (
1616
_load_for_executorch_from_buffer,
@@ -49,8 +49,11 @@ def forward(self, x, y):
4949
break
5050

5151
orig_outputs = len(output_node.args[0])
52-
53-
et = edge.to_executorch()
52+
53+
config = ExecutorchBackendConfig(
54+
do_quant_fusion_and_const_prop=False,
55+
)
56+
et = edge.to_executorch(config)
5457

5558
weight_output_specs = [
5659
spec

exir/tests/test_memory_planning.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,8 @@ def forward(self, input, label):
769769
ep = export(net, inputs, strict=True)
770770
ep = _export_forward_backward(ep)
771771
ep = to_edge(ep)
772-
ep = ep.to_executorch()
772+
config = ExecutorchBackendConfig(do_quant_fusion_and_const_prop=False)
773+
ep = ep.to_executorch(config)
773774

774775
ep.dump_executorch_program(True)
775776

exir/tests/test_passes.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,16 @@ def forward(self) -> torch.Tensor:
10851085
self.assertEqual(ep.graph_signature.input_specs[1].arg.name, "b_a")
10861086

10871087
# Validate that the program successfully passes validation to executorch:
1088-
edge.to_executorch()
1088+
1089+
# The test fails when do_quant_fusion_and_const_prop=True, but it is not related to
1090+
# the pass, but rather that memory planning fails (AssertionError: graph_output_allocated not set)
1091+
# when a graph has no user inputs and no operations. We can construct a failure case
1092+
# even with do_quant_fusion_and_const_prop = False by changing the forward method in NoUserInputs
1093+
# to just return self.a
1094+
config = exir.ExecutorchBackendConfig(
1095+
do_quant_fusion_and_const_prop=False,
1096+
)
1097+
edge.to_executorch(config)
10891098

10901099
def test_constant_prop_pass_for_parameter(self) -> None:
10911100
def count_additions(gm: torch.fx.GraphModule) -> int:

exir/tests/test_remove_view_copy.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ def test_spec(self) -> None:
102102
config=ExecutorchBackendConfig(
103103
remove_view_copy=True,
104104
memory_planning_pass=MemoryPlanningPass(alloc_graph_input=False),
105+
do_quant_fusion_and_const_prop=False,
105106
),
106107
)
107108

extension/training/examples/XOR/export_model.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ def _export_model(external_mutable_weights: bool = False):
3232
# Lower the graph to executorch.
3333
ep = ep.to_executorch(
3434
config=ExecutorchBackendConfig(
35-
external_mutable_weights=external_mutable_weights
35+
external_mutable_weights=external_mutable_weights,
36+
do_quant_fusion_and_const_prop=False,
3637
)
3738
)
3839
return ep

extension/training/pybindings/test/test.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import unittest
1010

1111
import torch
12-
from executorch.exir import to_edge
12+
from executorch.exir import to_edge, ExecutorchBackendConfig
1313

1414
from executorch.extension.training import (
1515
_load_for_executorch_for_training_from_buffer,
@@ -36,7 +36,8 @@ def test(self):
3636
ep = torch.export.export(m, m.get_inputs(), strict=True)
3737
ep = _export_forward_backward(ep)
3838
ep = to_edge(ep)
39-
ep = ep.to_executorch()
39+
config = ExecutorchBackendConfig(do_quant_fusion_and_const_prop=False)
40+
ep = ep.to_executorch(config)
4041
buffer = ep.buffer
4142
tm = _load_for_executorch_for_training_from_buffer(buffer)
4243

0 commit comments

Comments
 (0)