sanskar753 commited on
Commit
90c3df4
·
verified ·
1 Parent(s): 7fabcdc

Upload qandc/cache.py

Browse files
Files changed (1) hide show
  1. qandc/cache.py +58 -0
qandc/cache.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Feature Caching for DiT models (FORA-style).
3
+ Caches self-attention and MLP outputs, reusing for N-1 steps after each full computation.
4
+ """
5
+ import torch
6
+ import torch.nn as nn
7
+
8
+ class CachedDiTBlock(nn.Module):
9
+ """Wraps a DiT transformer block with static feature caching."""
10
+ def __init__(self, block, cache_interval=2):
11
+ super().__init__()
12
+ self.block = block
13
+ self.cache_interval = cache_interval
14
+ self.cached_output = None
15
+ self.step_count = 0
16
+ self.caching_enabled = True
17
+
18
+ def __getattr__(self, name):
19
+ """Delegate attribute access to the wrapped block for transparency."""
20
+ try:
21
+ return super().__getattr__(name)
22
+ except AttributeError:
23
+ return getattr(self.block, name)
24
+
25
+ def reset_cache(self):
26
+ self.cached_output = None
27
+ self.step_count = 0
28
+
29
+ def forward(self, hidden_states, *args, **kwargs):
30
+ if not self.caching_enabled:
31
+ return self.block(hidden_states, *args, **kwargs)
32
+ if self.step_count % self.cache_interval == 0:
33
+ output = self.block(hidden_states, *args, **kwargs)
34
+ if isinstance(output, tuple):
35
+ self.cached_output = (output[0] - hidden_states).detach()
36
+ else:
37
+ self.cached_output = (output - hidden_states).detach()
38
+ self.step_count += 1
39
+ return output
40
+ else:
41
+ self.step_count += 1
42
+ if isinstance(self.cached_output, tuple):
43
+ return (hidden_states + self.cached_output[0],) + self.cached_output[1:]
44
+ else:
45
+ return hidden_states + self.cached_output
46
+
47
+ def apply_cache_to_dit(transformer, cache_interval=2):
48
+ if hasattr(transformer, 'transformer_blocks'):
49
+ blocks = transformer.transformer_blocks
50
+ for i in range(len(blocks)):
51
+ blocks[i] = CachedDiTBlock(blocks[i], cache_interval=cache_interval)
52
+ print(f"Applied cache (interval={cache_interval}) to {len(blocks)} transformer blocks")
53
+ return transformer
54
+
55
+ def reset_all_caches(transformer):
56
+ for module in transformer.modules():
57
+ if isinstance(module, CachedDiTBlock):
58
+ module.reset_cache()