Skip to content

Commit 500849b

Browse files
Arm backend: Shorten pass pipeline logging (#22825)
Modifies 11 passes to only log once rather than once per modification, as this would lead to unnecessarily long outputs in many cases. Signed-off-by: Adrian Lundell <adrian.lundell@arm.com>
1 parent 04a2d72 commit 500849b

11 files changed

Lines changed: 132 additions & 115 deletions

‎backends/arm/_passes/cast_int64_pass.py‎

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -68,16 +68,12 @@ def _cast_buffer_to_int32(self, node: torch.fx.Node) -> bool:
6868

6969
buffer = store[buffer_name]
7070
self._assert_within_int32(buffer, node)
71-
logger.warning(
72-
f"Casting buffer {node.name} from torch.int64 to torch.int32"
73-
f" defined in {node.meta.get('stack_trace','[no stack trace found]')}"
74-
)
7571
store[buffer_name] = buffer.to(torch.int32)
7672
node.meta["val"] = node.meta["val"].to(torch.int32)
7773
return True
7874

79-
def _to_int32(self, graph_module: torch.fx.GraphModule) -> bool:
80-
modified = False
75+
def _to_int32(self, graph_module: torch.fx.GraphModule) -> int:
76+
converted = 0
8177
for node in graph_module.graph.nodes:
8278
if len(node.users) == 0:
8379
continue
@@ -89,11 +85,16 @@ def _to_int32(self, graph_module: torch.fx.GraphModule) -> bool:
8985
if fake_tensor.dtype != torch.int64:
9086
continue
9187
if is_buffer(self.exported_program, node):
92-
modified |= self._cast_buffer_to_int32(node)
93-
return modified
88+
converted += self._cast_buffer_to_int32(node)
89+
return converted
9490

9591
def call(self, graph_module: torch.fx.GraphModule):
96-
modified = self._to_int32(graph_module)
92+
converted = self._to_int32(graph_module)
93+
modified = converted > 0
9794
if modified:
9895
graph_module = super().call(graph_module).graph_module
96+
logger.warning(
97+
"CastInt64BuffersToInt32Pass: cast %d int64 buffer(s) to int32.",
98+
converted,
99+
)
99100
return PassResult(graph_module, modified)

‎backends/arm/_passes/convert_expand_copy_to_repeat.py‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,17 @@ class ConvertExpandCopyToRepeatPass(ArmOpTargetedPass):
6262
repeat = exir_ops.edge.aten.repeat.default
6363
target_ops = (expand_copy,)
6464

65+
def call(self, graph_module):
66+
self._removed_noop_expands = 0
67+
result = super().call(graph_module)
68+
if self._removed_noop_expands:
69+
logger.info(
70+
"ConvertExpandCopyToRepeatPass: removed %d redundant "
71+
"expand_copy operator(s).",
72+
self._removed_noop_expands,
73+
)
74+
return result
75+
6576
def call_operator(self, op, args, kwargs, meta):
6677
if op not in self.target_ops:
6778
return super().call_operator(op, args, kwargs, meta)
@@ -71,7 +82,7 @@ def call_operator(self, op, args, kwargs, meta):
7182
if all((x == 1 for x in multiples)) and not changes_rank:
7283
# All dimensions/repetitions occur only once. Remove node
7384
# altogether since it's in practice just a copy.
74-
logger.info("Found redundant expand node (no-op). Removing it.")
85+
self._removed_noop_expands += 1
7586

7687
return args[0]
7788

‎backends/arm/_passes/convert_int64_const_ops_to_int32.py‎

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class ConvertInt64ConstOpsToInt32Pass(ArmPass):
4545

4646
def call(self, graph_module: torch.fx.GraphModule):
4747
modified = False
48+
converted = 0
49+
skipped = 0
4850
for node in graph_module.graph.nodes:
4951
if node.op != "call_function":
5052
continue
@@ -61,21 +63,23 @@ def call(self, graph_module: torch.fx.GraphModule):
6163

6264
min_val, max_val = torch.min(data), torch.max(data)
6365
if INT32_MIN <= min_val and max_val <= INT32_MAX:
64-
logger.warning(
65-
f"Casting {node.name} from torch.int64 to torch.int32"
66-
f" defined in {node.meta.get('stack_trace','[no stack trace found]')}"
67-
)
6866
node.update_kwarg("dtype", torch.int32)
6967
modified = True
68+
converted += 1
7069
else:
71-
logger.warning(
72-
f"[{node.name}] has values: min={min_val}, max={max_val}, which exceeds int32 range "
73-
f"([{INT32_MIN}, {INT32_MAX}]); not converting dtype to int32."
74-
)
70+
skipped += 1
7571

7672
if modified:
7773
graph_module.graph.eliminate_dead_code()
7874
graph_module.recompile()
7975
graph_module = super().call(graph_module).graph_module
8076

77+
if converted or skipped:
78+
logger.warning(
79+
"ConvertInt64ConstOpsToInt32Pass: cast %d constant operator(s) "
80+
"to int32 and skipped %d outside the int32 range.",
81+
converted,
82+
skipped,
83+
)
84+
8185
return PassResult(graph_module, modified)

‎backends/arm/_passes/convert_int64_output_ops_to_int32.py‎

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,8 @@ def _convert_casting_operators(self, node: torch.fx.Node):
148148
if input_dtype == torch.int32:
149149
users = [user for user in node.users if node != user]
150150
for user in users:
151-
logger.warning(
152-
f"Removing int32->int64 casting node {node.name} defined in"
153-
f" {node.meta.get('stack_trace','[no stack trace found]')}"
154-
)
155151
user.replace_input_with(node, input_node)
152+
self._removed_casts += 1
156153
# Case 2: other types -> int64 - rewrites to cast to int32
157154
else:
158155
if node.target in self.cast_ops_kwargs:
@@ -161,11 +158,7 @@ def _convert_casting_operators(self, node: torch.fx.Node):
161158
set_node_arg(node, 1, torch.int32)
162159
else:
163160
raise RuntimeError(f"Unexpected target {node.target} in {node.name}")
164-
output_dtype = get_first_fake_tensor(node).dtype
165-
logger.warning(
166-
f"Converting casting node {node.name} from {input_dtype}->{output_dtype} to"
167-
f" {input_dtype}->torch.int32 defined in {node.meta.get('stack_trace','[no stack trace found]')}"
168-
)
161+
self._converted_casts += 1
169162

170163
def _range_fits_int32(self, value_range: Tuple[int, int]) -> bool:
171164
return -self._INT32_MAX - 1 <= value_range[0] and (
@@ -471,15 +464,25 @@ def _cast_safe_index_paths_to_int32(
471464
)
472465
user.replace_input_with(node, boundary)
473466

474-
logger.warning(
475-
f"Inserting a casting node {cast_to_int32.name} after "
476-
f"{source.name} for range-safe index consumers defined in "
477-
f"{source.meta.get('stack_trace','[no stack trace found]')}"
478-
)
467+
self._safe_index_casts += 1
479468
return True
480469

470+
def _log_summary(self) -> None:
471+
if self._removed_casts or self._converted_casts or self._safe_index_casts:
472+
logger.warning(
473+
"ConvertInt64OutputOpsToInt32Pass: removed %d int32-to-int64 "
474+
"cast(s), rewrote %d cast(s) to int32, and inserted %d "
475+
"range-safe index cast(s).",
476+
self._removed_casts,
477+
self._converted_casts,
478+
self._safe_index_casts,
479+
)
480+
481481
def call(self, graph_module: torch.fx.GraphModule):
482482
modified = False
483+
self._removed_casts = 0
484+
self._converted_casts = 0
485+
self._safe_index_casts = 0
483486
graph = graph_module.graph
484487
for node in list(graph.nodes):
485488
if node.op != "call_function":
@@ -523,4 +526,6 @@ def call(self, graph_module: torch.fx.GraphModule):
523526
graph_module.recompile()
524527
graph_module = super().call(graph_module).graph_module
525528

529+
self._log_summary()
530+
526531
return PassResult(graph_module, modified)

‎backends/arm/_passes/decompose_asin_and_acos_pass.py‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
# For MI case
2828
edge_asin_op = (exir_ops.edge.aten.asin.default,)
2929
edge_acos_op = (exir_ops.edge.aten.acos.default,)
30+
logger = logging.getLogger(__name__)
3031

3132

3233
def get_decomposition(op) -> tuple:
@@ -73,6 +74,17 @@ class DecomposeAsinAndAcosPass(ArmOpTargetedPass):
7374
}
7475
target_ops = edge_asin_op + edge_acos_op
7576

77+
def call(self, graph_module):
78+
self._approximated = 0
79+
result = super().call(graph_module)
80+
if self._approximated:
81+
logger.info(
82+
"DecomposeAsinAndAcosPass: approximated %d asin/acos operator(s); "
83+
"small numerical errors may be introduced.",
84+
self._approximated,
85+
)
86+
return result
87+
7688
def _build_polynomial(
7789
self, coefficients: list[float], variable: torch.Tensor, meta: dict[str, str]
7890
) -> torch.Tensor:
@@ -124,9 +136,7 @@ def call_operator(self, op, args, kwargs, meta):
124136
# If quantized, node should be replace by table op
125137
return super().call_operator(op, args, kwargs, meta)
126138

127-
logging.info(
128-
f"Approximating {op}. This may introduce small numerical errors. For details, see {__file__}."
129-
)
139+
self._approximated += 1
130140
x = args[0]
131141
half = 0.5
132142
one = 1.0

‎backends/arm/_passes/decompose_atan_pass.py‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020

2121
edge_atan = exir_ops.edge.aten.atan.default # MI case
22+
logger = logging.getLogger(__name__)
2223

2324

2425
def _get_atan_ops(op):
@@ -51,6 +52,17 @@ class DecomposeAtanPass(ArmOpTargetedPass):
5152
}
5253
target_ops = (edge_atan,)
5354

55+
def call(self, graph_module):
56+
self._approximated = 0
57+
result = super().call(graph_module)
58+
if self._approximated:
59+
logger.info(
60+
"DecomposeAtanPass: approximated %d atan operator(s); "
61+
"small numerical errors may be introduced.",
62+
self._approximated,
63+
)
64+
return result
65+
5466
def _rational_approximation(self, z, ops, meta):
5567
"""Creates a (2,1) Padé approximation for atan(x) on [-1, 1]."""
5668

@@ -85,9 +97,7 @@ def call_operator(self, op, args, kwargs, meta):
8597
# If quantized, node should be replace by table op
8698
return super().call_operator(op, args, kwargs, meta)
8799

88-
logging.info(
89-
f"Approximating atan. This may introduce small numerical errors. For details, see {__file__}."
90-
)
100+
self._approximated += 1
91101

92102
ops = _get_atan_ops(op)
93103
(

‎backends/arm/_passes/decompose_log1p_pass.py‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
from executorch.exir.pass_base import ExportPass
1818

1919

20+
logger = logging.getLogger(__name__)
21+
22+
2023
class DecomposeLog1pPass(ArmOpTargetedPass):
2124
"""Decompose log1p into a small polynomial with a log fallback for larger
2225
inputs.
@@ -34,6 +37,17 @@ class DecomposeLog1pPass(ArmOpTargetedPass):
3437
}
3538
target_ops = _supported_ops
3639

40+
def call(self, graph_module):
41+
self._decomposed = 0
42+
result = super().call(graph_module)
43+
if self._decomposed:
44+
logger.info(
45+
"DecomposeLog1pPass: decomposed %d log1p operator(s) via "
46+
"polynomial and log branches.",
47+
self._decomposed,
48+
)
49+
return result
50+
3751
def _poly(self, x, meta):
3852
# 6-term Taylor: x - x^2/2 + x^3/3 - x^4/4 + x^5/5 - x^6/6
3953
op_mul = exir_ops.edge.aten.mul.Tensor
@@ -71,7 +85,7 @@ def call_operator(self, op, args, kwargs, meta):
7185
# Quantized log1p should be handled by LUT/table instead of decomposition.
7286
return super().call_operator(op, args, kwargs, meta)
7387

74-
logging.info("Decomposing log1p via polynomial + log branch for FP profile.")
88+
self._decomposed += 1
7589

7690
x = args[0]
7791
approx = self._poly(x, meta)

‎backends/arm/_passes/fuse_constant_ops_pass.py‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,14 @@ def maybe_delete(self, input_nodes_to_maybe_delete):
219219
if len(input_node.users) == 0:
220220
self._delete_constant_placeholder(input_node)
221221

222+
@staticmethod
223+
def _log_summary(fused: int) -> None:
224+
if fused:
225+
logger.debug("FuseConstantArgsPass: fused %d constant operator(s).", fused)
226+
222227
def call(self, graph_module):
223228
modified = False
229+
fused = 0
224230
input_nodes_to_maybe_delete = set()
225231
for node in graph_module.graph.nodes:
226232
if node.op != "call_function":
@@ -254,11 +260,8 @@ def call(self, graph_module):
254260
try:
255261
did_fuse = self._fuse_nodes(node)
256262
if did_fuse:
257-
logger.debug(
258-
f"Fused constant op: {node.name} with placeholder inputs:"
259-
f"{[input_node.name for input_node in input_nodes]}"
260-
)
261263
modified |= did_fuse
264+
fused += 1
262265
input_nodes_to_maybe_delete.update(input_nodes)
263266
except Exception as e:
264267
logger.warning(
@@ -270,6 +273,8 @@ def call(self, graph_module):
270273
self.maybe_delete(input_nodes_to_maybe_delete)
271274
graph_module = super().call(graph_module).graph_module
272275

276+
self._log_summary(fused)
277+
273278
return PassResult(graph_module, modified)
274279

275280

‎backends/arm/_passes/insert_int32_casts_after_int64_placeholders.py‎

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,12 @@ def _insert_placeholder_i64_to_i32_casts(self, graph_module: torch.fx.GraphModul
110110
users = [user for user in node.users if user != cast_after]
111111
for user in users:
112112
user.replace_input_with(node, cast_after)
113-
logger.warning(
114-
f"Inserting a casting node {cast_after.name} after {node.name} to cast int64 placeholder"
115-
f" to int32 for {node.name} defined in {node.meta.get('stack_trace','[no stack trace found]')}"
116-
)
113+
self._placeholder_casts_inserted += 1
117114
modified = True
118115
return modified
119116

120117
def call(self, graph_module: torch.fx.GraphModule):
118+
self._placeholder_casts_inserted = 0
121119
modified = False
122120
modified |= self._insert_placeholder_i64_to_i32_casts(graph_module)
123121
modified |= self._insert_callsite_i32_to_i64_casts(graph_module)
@@ -126,4 +124,10 @@ def call(self, graph_module: torch.fx.GraphModule):
126124
graph_module.graph.eliminate_dead_code()
127125
graph_module.recompile()
128126
graph_module = super().call(graph_module).graph_module
127+
if self._placeholder_casts_inserted:
128+
logger.warning(
129+
"InsertInt32CastsAfterInt64PlaceholdersPass: inserted %d "
130+
"int64-to-int32 placeholder cast(s).",
131+
self._placeholder_casts_inserted,
132+
)
129133
return PassResult(graph_module, modified)

0 commit comments

Comments
 (0)