set_skip_existing#
- class tensordict.nn.set_skip_existing(mode: bool | list[NestedKey] | None = True, in_key_attr='in_keys', out_key_attr='out_keys', *, thread_local: bool = False)#
Bases:
_DecoratorContextManagerMakes modules skip their computation when their outputs are already in the tensordict.
As a context manager, it sets the value that
skip_existing()returns inside the block.TensorDictModule,TensorDictSequentialand the probabilistic modules read that value: when it is on, a module whoseout_keysare all in the input returns the input without running. A module whosein_keysandout_keysshare a key always runs.As a decorator of a method
forward(self, tensordict, ...), it applies the same check before the method runs, withmodeas the value.- Parameters:
mode (bool, list of NestedKey, or None, optional) –
the value of
skip_existing().True: a module is skipped if all itsout_keysare in the input.False: no module is skipped.A list of keys: only the modules whose
out_keysare all in the list can be skipped.None: for a decorator only; the method follows the value of the enclosing block (see the third example). As a context manager,Noneraises aRuntimeError.
Defaults to
True.in_key_attr (str, optional) – for a decorator, the name of the attribute of the module that holds its input keys. Defaults to
"in_keys".out_key_attr (str, optional) – for a decorator, the name of the attribute of the module that holds its output keys. Defaults to
"out_keys".
- Keyword Arguments:
thread_local (bool, optional) – if
True, the mode applies to the calling thread only, and blocks that other threads enter do not change it. Inside the block, blocks without this flag that the same thread enters stay in that thread too. Threads started inside the block see the process-wide mode. IfFalse, the mode applies to the whole process. Defaults toFalse.- Raises:
RuntimeError – if a block with a mode other than
FalseorNoneis entered undertorch.compile().
Examples
>>> import torch >>> from tensordict import TensorDict >>> from tensordict.nn import set_skip_existing, skip_existing, TensorDictModule >>> module = TensorDictModule(lambda x: x + 1, in_keys=["x"], out_keys=["y"]) >>> td = TensorDict(x=torch.zeros(()), y=torch.zeros(())) >>> with set_skip_existing(): ... print(skip_existing()) ... print(module(td)["y"]) # "y" exists: the module does not run True tensor(0.) >>> module(td)["y"] tensor(1.)
As a decorator, it skips the method when the outputs exist:
>>> from tensordict.nn import TensorDictModuleBase >>> class MyModule(TensorDictModuleBase): ... in_keys = [] ... out_keys = ["out"] ... @set_skip_existing() ... def forward(self, tensordict): ... print("hello") ... tensordict.set("out", torch.zeros(())) ... return tensordict >>> module = MyModule() >>> _ = module(TensorDict({"out": torch.zeros(())})) # does not print anything >>> _ = module(TensorDict()) hello
With
mode=None, the decorated method runs unless the caller opens aset_skip_existingblock:>>> class MyModule(TensorDictModuleBase): ... in_keys = [] ... out_keys = ["out"] ... @set_skip_existing(None) ... def forward(self, tensordict): ... print("hello") ... tensordict.set("out", torch.zeros(())) ... return tensordict >>> module = MyModule() >>> _ = module(TensorDict({"out": torch.zeros(())})) hello >>> with set_skip_existing(True): ... _ = module(TensorDict({"out": torch.zeros(())})) # does not print anything
A module whose input is also an output always runs:
>>> class MyModule(TensorDictModuleBase): ... in_keys = ["out"] ... out_keys = ["out"] ... @set_skip_existing() ... def forward(self, tensordict): ... print("calling the method!") ... return tensordict ... >>> _ = MyModule()(TensorDict({"out": torch.zeros(())})) calling the method!