Aurelien-Lac joe32140 commited on
Commit
64154d2
·
1 Parent(s): bee2310

fuse_projections: view a group already in one storage instead of copying it (#3)

Browse files

- fuse_projections: view a group already in one storage instead of copying it (33b2fffb16d2e24874a7dafee0c1d4b16fe975ab)


Co-authored-by: Chao-Chun (Joe) Hsu <joe32140@users.noreply.huggingface.co>

Files changed (1) hide show
  1. lfm3.py +15 -1
lfm3.py CHANGED
@@ -135,12 +135,26 @@ def fuse_projections(model) -> None:
135
  names = SHARED_INPUT.get(type(m).__name__, ())
136
  linears = [getattr(m, n, None) for n in names]
137
  if names and all(type(lin) is torch.nn.Linear and lin.bias is None for lin in linears):
138
- m.fused = Fused(torch.cat([lin.weight for lin in linears]), names, [lin.out_features for lin in linears])
139
  for i, name in enumerate(names):
140
  setattr(m, name, Part(m.fused, i))
141
  m.register_state_dict_post_hook(_unfused)
142
 
143
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  def _unfused(module, state_dict, prefix, local_metadata) -> None:
145
  fused = module.fused
146
  weight = state_dict.pop(prefix + "fused.weight")
 
135
  names = SHARED_INPUT.get(type(m).__name__, ())
136
  linears = [getattr(m, n, None) for n in names]
137
  if names and all(type(lin) is torch.nn.Linear and lin.bias is None for lin in linears):
138
+ m.fused = Fused(_stacked([lin.weight for lin in linears]), names, [lin.out_features for lin in linears])
139
  for i, name in enumerate(names):
140
  setattr(m, name, Part(m.fused, i))
141
  m.register_state_dict_post_hook(_unfused)
142
 
143
 
144
+ def _stacked(weights: list[torch.Tensor]) -> torch.Tensor:
145
+ """`weights` stacked by rows: a view when they already sit back to back in one storage, in this order, else a
146
+ copy. A freshly loaded model's linears each own their storage, so this copies and the old weights are freed.
147
+ Linears that are slices of one merged tensor something else keeps would otherwise be held twice (d1-2B: 1.5 GiB)."""
148
+ first = weights[0].detach()
149
+ storage, offset = first.untyped_storage().data_ptr(), first.storage_offset()
150
+ for w in weights:
151
+ if (w.untyped_storage().data_ptr() != storage or w.storage_offset() != offset or not w.is_contiguous()
152
+ or w.dtype != first.dtype or w.shape[1:] != first.shape[1:]):
153
+ return torch.cat(weights)
154
+ offset += w.numel()
155
+ return first.as_strided((sum(w.shape[0] for w in weights), *first.shape[1:]), first.stride())
156
+
157
+
158
  def _unfused(module, state_dict, prefix, local_metadata) -> None:
159
  fused = module.fused
160
  weight = state_dict.pop(prefix + "fused.weight")