|
11 | 11 | from tdhook.modules import get_best_device |
12 | 12 | from tdhook.runtime import HookProgram, HookSpec |
13 | 13 | from tdhook.targets import Target |
| 14 | +from tdhook.workflow import Workflow |
14 | 15 |
|
15 | 16 |
|
16 | 17 | class TestActivationCaching: |
@@ -48,6 +49,38 @@ def test_tensordict_execution_publishes_a_native_cache_output(self, default_test |
48 | 49 | assert hooked_module.out_keys == ["output", ("activations", "cache")] |
49 | 50 | assert result["activations", "cache"]["linear2"].shape == (2, 20) |
50 | 51 |
|
| 52 | + @pytest.mark.parametrize("run_in_workflow", [False, True]) |
| 53 | + def test_cache_publication_preserves_the_callers_model_contract(self, run_in_workflow): |
| 54 | + raw_model = torch.nn.Sequential(torch.nn.Linear(3, 4)) |
| 55 | + input_key = ("inputs", "value") |
| 56 | + output_key = ("predictions", "value") |
| 57 | + cache_key = ("activations", "hidden") |
| 58 | + model = TensorDictModule(raw_model, in_keys=[input_key], out_keys=[output_key]) |
| 59 | + method = ActivationCaching(r"module\.0$", cache_key=cache_key) |
| 60 | + inputs = torch.randn(2, 3) |
| 61 | + expected = raw_model(inputs) |
| 62 | + |
| 63 | + for _ in range(2): |
| 64 | + data = TensorDict({input_key: inputs}, batch_size=[2]) |
| 65 | + if run_in_workflow: |
| 66 | + result = Workflow(method)(model, data) |
| 67 | + else: |
| 68 | + context = method.prepare(model) |
| 69 | + assert model.out_keys == [output_key] |
| 70 | + assert context.module.out_keys == [output_key, cache_key] |
| 71 | + with context as hooked_module: |
| 72 | + result = hooked_module(data) |
| 73 | + |
| 74 | + assert model.in_keys == [input_key] |
| 75 | + assert model.out_keys == [output_key] |
| 76 | + assert model.out_keys_source == [output_key] |
| 77 | + torch.testing.assert_close(result[output_key], expected) |
| 78 | + torch.testing.assert_close(result[cache_key]["module.0"], expected) |
| 79 | + |
| 80 | + plain_result = model(TensorDict({input_key: inputs}, batch_size=[2])) |
| 81 | + torch.testing.assert_close(plain_result[output_key], expected) |
| 82 | + assert cache_key not in plain_result.keys(include_nested=True) |
| 83 | + |
51 | 84 | def test_target_selection_is_cached_and_reported(self, default_test_model): |
52 | 85 | target = Target("linear2", "activation", -1, (0, 2)) |
53 | 86 |
|
|
0 commit comments