Forward pass with per-token early exit via frozen-token approach. Tokens that converge at a checkpoint get their normed hidden state saved. They continue through the model (for attention) but their contribution to the final output comes from the exit point, not the last laye
(
self,
input_ids: torch.Tensor,
attention_mask: Optional[torch.Tensor] = None,
**kwargs,
)
| 133 | |
| 134 | @torch.no_grad() |
| 135 | def forward( |
| 136 | self, |
| 137 | input_ids: torch.Tensor, |
| 138 | attention_mask: Optional[torch.Tensor] = None, |
| 139 | **kwargs, |
| 140 | ) -> torch.Tensor: |
| 141 | """Forward pass with per-token early exit via frozen-token approach. |
| 142 | |
| 143 | Tokens that converge at a checkpoint get their normed hidden state saved. |
| 144 | They continue through the model (for attention) but their contribution to |
| 145 | the final output comes from the exit point, not the last layer. |
| 146 | """ |
| 147 | B, S = input_ids.shape |
| 148 | device = input_ids.device |
| 149 | |
| 150 | # Run full model forward, collecting all layer hidden states |
| 151 | model_output = self.model( |
| 152 | input_ids, |
| 153 | attention_mask=attention_mask, |
| 154 | output_hidden_states=True, |
| 155 | return_dict=True, |
| 156 | ) |
| 157 | |
| 158 | # hidden_states: [embedding, layer_0, layer_1, ..., layer_N] |
| 159 | all_hidden = model_output.hidden_states |
| 160 | D = all_hidden[-1].shape[-1] |
| 161 | dtype = all_hidden[-1].dtype |
| 162 | |
| 163 | output_buffer = torch.zeros(B, S, D, device=device, dtype=dtype) |
| 164 | exited_mask = torch.zeros(B, S, dtype=torch.bool, device=device) |
| 165 | stats = ExitStats(total_tokens=B * S) |
| 166 | |
| 167 | # Check routers at each checkpoint layer (post-hoc, using saved hidden states) |
| 168 | for layer_idx in sorted(self.routers.keys()): |
| 169 | if layer_idx < self.config.min_layers: |
| 170 | continue |
| 171 | |
| 172 | hidden = all_hidden[layer_idx + 1] # +1 because index 0 is embeddings |
| 173 | scores = self._score_router(hidden, layer_idx) # [B, S] |
| 174 | new_exits = (scores > self.config.exit_threshold) & (~exited_mask) |
| 175 | |
| 176 | if new_exits.any(): |
| 177 | normed = self._final_norm(hidden.float()).to(dtype) |
| 178 | output_buffer[new_exits] = normed[new_exits] |
| 179 | exited_mask = exited_mask | new_exits |
| 180 | stats.exits_per_layer[layer_idx] = new_exits.sum().item() |
| 181 | |
| 182 | # Remaining tokens use the final hidden state |
| 183 | remaining_mask = ~exited_mask |
| 184 | if remaining_mask.any(): |
| 185 | final_hidden = all_hidden[-1] |
| 186 | normed = self._final_norm(final_hidden.float()).to(dtype) |
| 187 | output_buffer[remaining_mask] = normed[remaining_mask] |
| 188 | stats.remaining_tokens = remaining_mask.sum().item() |
| 189 | |
| 190 | self.last_stats = stats |
| 191 | logits = self._lm_head(output_buffer) |
| 192 | return logits |
nothing calls this directly
no test coverage detected