MCPcopy Create free account
hub / github.com/pytorch/executorch / PythonTensor

Class PythonTensor

exir/tracer.py:227–383  ·  view source on GitHub ↗

A wrapper tensor subclass used in the DispatchTracer to keep track of proxies to construct the FX graph. Wrapping something in PythonTensor implicitly detaches gradients. If something required grad, we will collect it as if it were a leaf. A consequence of detaching in this w

Source from the content-addressed store, hash-verified

225
226
227class PythonTensor(torch.Tensor):
228 """
229 A wrapper tensor subclass used in the DispatchTracer to keep track of
230 proxies to construct the FX graph.
231
232 Wrapping something in PythonTensor implicitly detaches gradients. If
233 something required grad, we will collect it as if it were a leaf. A
234 consequence of detaching in this way is you need to maintain a parameter
235 cache when translating tensors into PythonTensor, so you don't create
236 multiple copies of a gradient (they are aliased, but they would count as
237 independent leaves). An alternate strategy would be to avoid implicitly
238 detaching and instead "catch" gradients as they exit the PythonTensor
239 boundary.
240 """
241
242 __slots__ = ["proxy", "is_immutable"]
243
244 @staticmethod
245 def __new__(
246 cls, elem: torch.Tensor, proxy: torch.fx.Proxy, is_immutable: bool = False
247 ) -> torch.Tensor:
248 # assert not elem.requires_grad or not torch.is_grad_enabled()
249
250 r = torch.Tensor._make_subclass(cls, elem, elem.requires_grad)
251 assert isinstance(r, PythonTensor)
252 r.is_immutable: bool = is_immutable
253 r.update_proxy(proxy)
254 return r
255
256 def update_proxy(self, proxy: torch.fx.Proxy) -> None:
257 self.proxy = proxy
258
259 def __repr__(self, *, tensor_contents: None = None) -> str:
260 with no_dispatch():
261 return f"PythonTensor({self.as_subclass(torch.Tensor)})"
262
263 @classmethod
264 def __torch_function__(
265 cls,
266 # pyre-ignore: Missing parameter annotation [2]
267 func,
268 # pyre-ignore: Missing parameter annotation [2]
269 types,
270 args: Tuple[Value, ...] = (),
271 kwargs: Optional[Dict[str, Value]] = None,
272 ) -> Value:
273 if kwargs is None:
274 kwargs = {}
275 if torch.is_inference_mode_enabled():
276 if func is torch.nn.functional.layer_norm:
277 args, kwargs = normalize_function(func, args, kwargs) # pyre-fixme[23]
278 input, normalized_shape = args
279 normalized_shape = list(normalized_shape)
280 return cls.__torch_dispatch__(
281 torch.ops.aten.layer_norm.default,
282 types,
283 (input, normalized_shape),
284 kwargs,

Callers 4

shapeFunction · 0.90
wrap_with_proxyMethod · 0.85
_module_getattrMethod · 0.85
wrapMethod · 0.85

Calls

no outgoing calls

Tested by

no test coverage detected