|
18 | 18 |
|
19 | 19 | import dataclasses |
20 | 20 | import functools |
| 21 | +import sys |
21 | 22 | import typing |
22 | 23 | from typing import Any, Callable, ClassVar, Generic, Iterator, Optional, Set, Tuple, Type, TypeVar, Union |
23 | 24 |
|
@@ -1120,14 +1121,7 @@ def full_shape(self) -> DcOrArrayT: |
1120 | 1121 | @functools.cached_property |
1121 | 1122 | def inner_shape(self) -> Shape: |
1122 | 1123 | """Returns the the static shape resolved for the current value.""" |
1123 | | - # torch.func.vmap calls `tree_unflatten([0] * num_leaves)` internally, |
1124 | | - # messing up shape inference. |
1125 | | - if ( |
1126 | | - enp.lazy.has_torch |
1127 | | - and isinstance(self.value, int) |
1128 | | - and self.value == 0 |
1129 | | - ): |
1130 | | - return () |
| 1124 | + |
1131 | 1125 | if not self.inner_shape_non_static: |
1132 | 1126 | return () |
1133 | 1127 | static_shape = self.full_shape[-len(self.inner_shape_non_static) :] |
@@ -1167,6 +1161,14 @@ def is_value_missing(self) -> bool: |
1167 | 1161 | elif enp.array_spec.is_fake_array(self.value): |
1168 | 1162 | # `etree.spec_like`, Flax summary, ShapeDtypeStruct, ... compatibility |
1169 | 1163 | return True |
| 1164 | + # torch.func.vmap calls `tree_unflatten([0] * num_leaves)` internally. |
| 1165 | + elif ( |
| 1166 | + enp.lazy.has_torch |
| 1167 | + and isinstance(self.value, int) |
| 1168 | + and self.value == 0 |
| 1169 | + and _is_called_inside_torch_vmap() |
| 1170 | + ): |
| 1171 | + return True |
1170 | 1172 | return False |
1171 | 1173 |
|
1172 | 1174 | @property |
@@ -1194,6 +1196,22 @@ def broadcast_to(self, shape: Shape) -> DcOrArrayT: |
1194 | 1196 | return self.xnp.broadcast_to(self.value, final_shape) |
1195 | 1197 |
|
1196 | 1198 |
|
| 1199 | +def _is_called_inside_torch_vmap() -> bool: |
| 1200 | + """Returns `True` if the current call is inside a `torch.func.vmap`.""" |
| 1201 | + frame = sys._getframe(1) # pylint: disable=protected-access |
| 1202 | + |
| 1203 | + while frame: |
| 1204 | + code = frame.f_code |
| 1205 | + if ( |
| 1206 | + code.co_name == '_broadcast_to_and_flatten' |
| 1207 | + and code.co_filename.endswith('torch/utils/_pytree.py') |
| 1208 | + ): |
| 1209 | + return True |
| 1210 | + frame = frame.f_back |
| 1211 | + |
| 1212 | + return False |
| 1213 | + |
| 1214 | + |
1197 | 1215 | def _make_field_metadata( |
1198 | 1216 | field: dataclasses.Field[Any], |
1199 | 1217 | hints: dict[str, TypeAlias], |
|
0 commit comments