| 1316 | |
| 1317 | |
| 1318 | class FakeTensorMode(TorchDispatchMode): |
| 1319 | def __init__( |
| 1320 | self, |
| 1321 | *, |
| 1322 | allow_fallback_kernels=True, |
| 1323 | allow_non_fake_inputs=False, |
| 1324 | shape_env=None, |
| 1325 | static_shapes=None, |
| 1326 | ): |
| 1327 | log.debug("create_mode 0x%x", id(self)) |
| 1328 | self.allow_fallback_kernels = allow_fallback_kernels |
| 1329 | self.fake_tensor_converter = FakeTensorConverter() |
| 1330 | if static_shapes is not None: |
| 1331 | self.static_shapes = static_shapes |
| 1332 | else: |
| 1333 | self.static_shapes = shape_env is None |
| 1334 | |
| 1335 | import torch._functorch.config |
| 1336 | |
| 1337 | self.allow_meta = torch._functorch.config.fake_tensor_allow_meta |
| 1338 | |
| 1339 | # A flag that controls, whether we want to invoke ops on mix of |
| 1340 | # real weights/global variables and fake inputs |
| 1341 | self.allow_non_fake_inputs = allow_non_fake_inputs |
| 1342 | |
| 1343 | # [in_kernel_invocation] |
| 1344 | # when FakeTensor is invoked in user code, .device should return |
| 1345 | # the fake_device of the tensor so that code such as as `if x.is_cuda` |
| 1346 | # or torch.zeros([10, 10], device=x.device) continues to execute as if |
| 1347 | # the FakeTensor were real. However, within kernel execution, we return |
| 1348 | # the `Meta` device because all computation within the kernels should |
| 1349 | # behave as if the Tensors are on meta devices. Kernels should allocate |
| 1350 | # new tensors on meta devices, and checks like `is_meta` should return true. |
| 1351 | # within python refs, we always return the real device by defining |
| 1352 | # the device property |
| 1353 | self.in_kernel_invocation = False |
| 1354 | |
| 1355 | # True if we enter'ed and actually enabled fake tensor mode, |
| 1356 | # false if it was a no-op. Not thread safe but neither is |
| 1357 | # in_kernel_invocation |
| 1358 | # If another fake mode was already active when we enter, we also stash it here. |
| 1359 | # That way when we exit, we know to re-enable the previous fake mode. |
| 1360 | self.enter_stack: List[Tuple[bool, Optional[FakeTensorMode]]] = [] |
| 1361 | |
| 1362 | self.shape_env = shape_env |
| 1363 | |
| 1364 | self.stack = "".join(traceback.format_stack()) |
| 1365 | |
| 1366 | # Indicates to our torch_dispatch dispatching infra that |
| 1367 | # this is an "infra" mode with lower dispatching precedence. |
| 1368 | self._mode_key = torch._C._TorchDispatchModeKey.FAKE |
| 1369 | |
| 1370 | # Typically, there is only one fake tensor mode and you test for it by |
| 1371 | # doing an isinstance test. However, in some situations, there might be |
| 1372 | # TWO fake tensor modes. The canonical example of this is exporting |
| 1373 | # a fake model: there is an outer fake mode created by the user, and |
| 1374 | # an inner fake mode created by Dynamo. The two phase process is required |
| 1375 | # because the outer fake mode typically won't have a ShapeEnv, even if |
no outgoing calls
searching dependent graphs…