CoolFace
Modelpublic

togethercomputer/StripedHyena-Nous-7B

sourceHugging Faceapache-2.0updated 3y agoView on Hugging Face
145likes335downloads
engine.py347 linesDownload Raw Back to root
1# Copyright (c) Together2# This software is distributed under the terms of the Apache License, Version 2.03# Author: Michael Poli4 5import torch6import torch.nn as nn7import torch.nn.functional as F8 9try:10    import conv1d_cpp11except:12    pass13from .utils import column_split14 15 16def canonicalize_modal_system(poles, residues):17    """Canonicalize a modal system.18 19    Args:20        poles (Tensor): The poles of the system.21        residues (Tensor): The residues of the system.22 23    Returns:24        Tuple[Tensor, Tensor]: The canonicalized poles and residues.25    """26    raise NotImplementedError27 28 29IIR_PREFILL_MODES = [30    "recurrence",31    "modal-fft",32    "hybrid-modal-recurrence",33    "modal-scan",34    "canonical-fft",35    "iir-fir-caching",36]37 38 39class HyenaInferenceEngine:40    def __init__(41        self, fir_fn=None, fftconv_fn=None, iir_prefill_style="modal-fft", layer_idx=None42    ) -> None:43        self.fir_fn = fir_fn44        self.fftconv_fn = fftconv_fn45        assert (46            iir_prefill_style in IIR_PREFILL_MODES47        ), f"iir_prefill_style must be one of {IIR_PREFILL_MODES}"48        self.iir_prefill_style = iir_prefill_style49        self.layer_idx = layer_idx50        self.low_mem_mode = False51 52    def parallel_fir(53        self,54        fir_fn,55        u,56        weight,57        bias,58        L,59        fir_length=3,60        inference_params=None,61        prefill_mode=None,62        padding_mask=None,63    ):64        """Compute the output state of the long convolutional filter."""65        # prepare input layout, dimensions and dispatch to fir kernel66        if fir_fn != torch.nn.functional.conv1d:67            z_pre = fir_fn(u)[:, :L]  # B, L, D68            z_pre = z_pre.permute(0, 2, 1)69        else:70            u = u.permute(0, 2, 1)  # B, D, L71            z_pre = fir_fn(72                u,73                weight,74                bias,75                stride=1,76                padding=fir_length - 1,77                groups=u.shape[1],78            )[..., :L]79 80        # handle padding post fir, the only place with biases81        if type(padding_mask) == torch.Tensor:82            z_pre = z_pre * padding_mask[:, None]83 84        if inference_params is not None:85            # handle seqlen last and dim last cases for `u`86            if fir_fn != torch.nn.functional.conv1d:87                fir_state = u[:, -fir_length + 1 :].permute(0, 2, 1)88            else:89                fir_state = u[..., -fir_length + 1 :]90        else:91            fir_state = None92 93        return z_pre, fir_state94 95    def parallel_iir(96        self,97        z_pre,98        h,99        D,100        L,101        poles,102        t,103        dims,104        layer_idx,105        inference_params=None,106        prefill_style="fft",107        fftconv_fn=None,108        padding_mask=None,109        use_flashfft=False,110        column_split_hyena=False,111        long_fir_threshold=None,112    ):113        """Compute the output state of the short convolutional filter."""114        fft_size = 2 * L115        hidden_size, num_attention_heads, hidden_size_per_attention_head, _, _ = dims116        # Compatibility with training infra that column splits the projections117        if column_split_hyena:118            z = z_pre.reshape(119                z_pre.shape[0],120                num_attention_heads,121                3 * hidden_size_per_attention_head,122                z_pre.shape[2],123            )124            x2, x1, v = (125                z[:, :, :hidden_size_per_attention_head],126                z[127                    :,128                    :,129                    hidden_size_per_attention_head : 2 * hidden_size_per_attention_head,130                ],131                z[:, :, 2 * hidden_size_per_attention_head :],132            )133            x2, x1, v = (134                x2.reshape(x2.shape[0], -1, x2.shape[-1]),135                x1.reshape(x1.shape[0], -1, x1.shape[-1]),136                v.reshape(v.shape[0], -1, v.shape[-1]),137            )138        else:139            x2, x1, v = z_pre.split([hidden_size, hidden_size, hidden_size], dim=1)140 141        x1v = x1 * v142 143        if use_flashfft and (L % 2) == 0:  # only works with even L144            y = fftconv_fn(145                x1v.to(dtype=torch.bfloat16).contiguous(),146                h.to(dtype=torch.float32),147            )148            X_s = None149 150        elif long_fir_threshold is None:151            H = torch.fft.rfft(h.to(dtype=torch.float32), n=fft_size) / fft_size152            X_s = torch.fft.fft(x1v.to(dtype=torch.float32), n=fft_size)153            X = X_s[..., : H.shape[-1]]154            if len(z_pre.shape) > 3:155                H = H.unsqueeze(1)156            y = torch.fft.irfft(X * H, n=fft_size, norm="forward")[..., :L]157        else:158            assert h.shape[0] == 1, "batch size must be 1 for long_fir_threshold"159            h = h[0][:, None]  # rearrange to d, 1, l for depthwise conv1d160            h = h[..., :long_fir_threshold]161            y = F.conv1d(162                x1v,163                h.to(dtype=x1v.dtype),164                stride=1,165                groups=x1v.shape[1],166                padding=h.shape[-1] - 1,167            )[..., :L]168 169        y = y.to(dtype=x1v.dtype)170        y = (y + x1v * D.unsqueeze(-1)) * x2171        if inference_params is not None:172            if prefill_style == "fft":173                self.prefill_via_modal_fft(174                    inference_params=inference_params,175                    x1v=x1v,176                    X_s=X_s,177                    L=L,178                    t=t,179                    poles=poles,180                    dims=dims,181                    layer_idx=layer_idx,182                    use_flashfft=use_flashfft,183                )184 185            elif prefill_style == "recurrence":186                self.prefill_via_direct_recurrence(187                    inference_params=inference_params,188                    x1v=x1v,189                    L=L,190                    poles=poles,191                )192 193            else:194                raise NotImplementedError195            if self.low_mem_mode:196                del z_pre, x2, x1, v, x1v, h197                torch.cuda.empty_cache()198 199        return y.permute(0, 2, 1)200 201    def step_fir(self, u, fir_state, weight, bias=None):202        """Step the FIR filter.203 204        Note:205        `fir_state` contains the last `short_filter_length - 1` elements of `u`: `u_(L-2), u_{L-1), ...`206        We assume dimensions of `short_filter_weight` to be `[d, 1, short_filter_len]` (SISO / multi SISO layout).207        """208        h0, h = weight[..., 0, -1], weight[..., 0, :-1]209        h0, h = h0[None], h[None]210        y = h0 * u + torch.sum(fir_state * h, dim=-1) + bias211 212        # update213        fir_state = torch.roll(fir_state, -1, dims=2)214        fir_state[..., -1] = u215        return y, fir_state216 217    def step_iir(self, x2, x1, v, D, residues, poles, iir_state, iir_groups=1):218        x1v = x1 * v219 220        residues, poles = (221            torch.view_as_complex(residues.to(torch.float32)),222            torch.view_as_complex(poles.to(torch.float32)),223        )224        # squeeze the dummy seqlen dimension225        # D, state_dim, 1 -> 1, D, state_dim226        residues, poles = residues[..., 0][None], poles[..., 0][None]227        iir_state = poles * iir_state + x1v[..., None]228 229        res_state = torch.sum(residues * iir_state, dim=-1).real230 231        if iir_groups > 1:232            raise NotImplementedError233        y = x2 * (res_state + D * x1v)234 235        return y, iir_state236 237    def prefill_via_fir_caching(self, u, inference_params, L, *args, **kwargs):238        """Turns the IIR filter into a FIR and uses a cache for decoding."""239        raise NotImplementedError(":)")240 241    def prefill_via_direct_recurrence(self, inference_params, x1v, L, poles, *args, **kwargs):242        """243        Compute the IIR state via explicit SSM recurrence (modal form)244        """245        x1v_ = x1v[..., None, None]  # b, d, l, sdim, reim246        x1v_ = x1v_.repeat(1, 1, 1, 1, 2)  # b, d, l, sdim, reim247 248        state = x1v_[:, :, 0]249        poles = poles[:, :, 0].to(dtype=torch.float32)250 251        for i in range(L):252            state = poles * state + x1v_[:, :, i]253        inference_params.state_dict[self.layer_idx] = torch.view_as_complex(254            state.to(dtype=torch.float32)255        )256 257    def prefill_via_hybrid_recurrence(258        self, inference_params, u, log_poles, x1v_f_a, L, *args, **kwargs259    ):260        """261        Compute the IIR state via hybrid recurrence-convolution over blocks262        """263        raise NotImplementedError(":)")264 265    def prefill_via_scan(self, u, inference_params=None, *args, **kwargs):266        raise NotImplementedError267 268    def prefill_via_canonical_fft(self, u, inference_params=None, *args, **kwargs):269        """270        Compute the IIR state via a single FFT with the denominator of the SSM in companion form.271 272        This is the most memory efficient "parallelized" prefilling method for Hyena.273 274        From: https://arxiv.org/abs/2310.18780275        """276        raise NotImplementedError(":)")277 278    def prefill_via_modal_fft(279        self,280        inference_params,281        x1v,282        L,283        poles,284        t,285        dims,286        layer_idx,287        X_s=None,288        use_flashfft=False,289        state_dtype=torch.complex64,290        *args,291        **kwargs,292    ):293        """294        Compute the IIR state via a single FFT, using the poles of the SSM in modal form.295        """296        # When the model has a long convolution derived from a SSM in modal form and prefill_style is "fft",297        # we split the filter into poles and residues and reuse FFT computation on the input.298        # This optimization is currently not supported when using flashfftconv.299        hidden_size, _, _, state_size, hyena_filter_groups = dims300 301        if use_flashfft:302            # using real states303            poles = poles.squeeze().reshape(poles.shape[0], -1)[..., None]304 305            state_s = poles**t306            if hyena_filter_groups > 1:307                raise NotImplementedError308 309            x1v = x1v[:, :, None].repeat(1, 1, 2 * state_size, 1)310            x1v = x1v.reshape(x1v.shape[0], -1, x1v.shape[-1])311            state_s = state_s[None]312 313            state = self.fftconv_fn(314                x1v.contiguous(),315                state_s.to(dtype=torch.float32),316            )317            state = state[..., L - 1].reshape(x1v.shape[0], hidden_size, state_size, 2)318            state = torch.view_as_complex(state.contiguous())319            inference_params.state_dict[self.layer_idx] = state.to(dtype=state_dtype)320        else:321            assert X_s is not None322            bs = x1v.shape[0]323            fft_size = 2 * L324            poles = torch.view_as_complex(poles.to(torch.float32))325            state_s = poles**t326            state_S = torch.fft.fft(state_s, n=fft_size).repeat(327                bs, 1, 1, 1328            )  # B, D, state_dim, 2 * L329            if hyena_filter_groups > 1:330                state_S = state_S.repeat_interleave(hidden_size // hyena_filter_groups, 1)331            state = torch.fft.ifft(X_s[..., None, :] * state_S, n=fft_size)332            inference_params.state_dict[layer_idx] = state[..., L - 1].to(dtype=state_dtype)333 334    def _compute_state(self, log_poles, u, t, L, *args, **kwargs):335        """336        Compute the IIR state given an input `u` and log_poles of the modal system.337        """338        bs = u.shape[0]339        fft_size = 2 * L340        U = torch.fft.rfft(u.to(torch.float32), n=fft_size)341        fft_size = 2 * L342        x = (log_poles * t).exp()343        # [batch, hidden_size, state_dim, 2 * seqlen]344        X = torch.fft.fft(x, n=fft_size).repeat(bs, 1, 1, 1)345        state = torch.fft.ifft(U[..., None, :] * X, n=fft_size)[..., :L]346        return state347