@@ -56,11 +56,23 @@ def init_to_zero(names):
5656 return lambda nargs : [nargs [name ].zero_ () for name in names if nargs [name ] is not None ]
5757
5858
59- def rearrange_and_update_stride (tensor , pattern = None , dim = 2 ):
60- # ensure tensor.stride(dim) is a multiple of eight after rearranging according to pattern,
61- # if not call contiguous(), rearrange only if pattern is not None
62- tensor_rearranged = rearrange (tensor , pattern ) if pattern is not None else tensor
63- return tensor_rearranged .contiguous () if tensor_rearranged .stride (dim ) % 8 != 0 else tensor_rearranged
59+ def ensure_stride (inp ):
60+ """
61+ Return inp, while ensuring that stride(1) of the returned tensor is a multiple of 8.
62+
63+ The inp tensor is of shape [batch, length, channels], where channels is assumed, and tested, to be
64+ a multiple of 8. If it is contiguous, inp will have strides [length*channels, channels, 1]. The
65+ output of this function will be rearranged to shape [batch, channels, length] before being passed to
66+ causal_conv1d. That rearranged tensor will have strides [length*channels, 1, channels].
67+ causal_conv1d handles this stride configuration (which it calls channels_last) directly and
68+ efficiently, after first recognizing it (when stride[1]==1 and stride[2]>1). causal_conv1d cannot
69+ operate on a channels_last tensor for which stride[2] is not a multiple of 8, and in that case will
70+ raise an exception. This function prevents the aforementioned exception by returning a tensor with
71+ stride(1) equal to channels, by making the returned tensor contiguous, if inp.stride(1) is not
72+ already a multiple of 8.
73+ """
74+ assert inp .shape [2 ] % 8 == 0 , "Number of convolution channels is required to be a multiple of 8."
75+ return inp if inp .stride (1 ) % 8 == 0 else inp .contiguous ()
6476
6577
6678@triton .autotune (
@@ -826,8 +838,8 @@ def forward(ctx, zxbcdt, conv1d_weight, conv1d_bias, dt_bias, A, D, chunk_size,
826838 zx0 , z , xBC , dt = torch .split (zxbcdt , [2 * d_nonssm , dim , dim + ngroups * dstate * 2 , nheads ], dim = - 1 )
827839 seq_idx = seq_idx .contiguous () if seq_idx is not None else None
828840 xBC_conv = rearrange (
829- causal_conv1d_fwd_function (rearrange_and_update_stride ( xBC , "b s d -> b d s" ),
830- conv1d_weight , conv1d_bias , seq_idx , None , None , activation in ["silu" , "swish" ]),
841+ causal_conv1d_fwd_function (rearrange ( ensure_stride ( xBC ) , "b s d -> b d s" ),
842+ conv1d_weight , conv1d_bias , seq_idx , None , None , activation in ["silu" , "swish" ]),
831843 "b d s -> b s d"
832844 )
833845 x , B , C = torch .split (xBC_conv , [dim , ngroups * dstate , ngroups * dstate ], dim = - 1 )
@@ -900,8 +912,8 @@ def backward(ctx, dout, *args):
900912 zx0 , z , xBC , dt = torch .split (zxbcdt , [2 * d_nonssm , dim , dim + 2 * ctx .ngroups * dstate , nheads ], dim = - 1 )
901913 # Recompute x, B, C
902914 xBC_conv = rearrange (
903- causal_conv1d_fwd_function (rearrange_and_update_stride ( xBC , "b s d -> b d s" ),
904- conv1d_weight , conv1d_bias , seq_idx , None , None , ctx .activation in ["silu" , "swish" ]),
915+ causal_conv1d_fwd_function (rearrange ( ensure_stride ( xBC ) , "b s d -> b d s" ),
916+ conv1d_weight , conv1d_bias , seq_idx , None , None , ctx .activation in ["silu" , "swish" ]),
905917 "b d s -> b s d"
906918 )
907919 x , B , C = torch .split (xBC_conv , [dim , ctx .ngroups * dstate , ctx .ngroups * dstate ], dim = - 1 )
@@ -949,16 +961,17 @@ def backward(ctx, dout, *args):
949961 doutproj_bias = dout_og .sum (dim = (0 , 1 )) if outproj_bias is not None else None
950962 else :
951963 doutproj_weight , doutproj_bias = None , None
952- dxBC_given = rearrange (dxBC_given , "b s d -> b d s" )
953964 dxBC_given_update , dweight , dbias , * _ = causal_conv1d_bwd_function (
954- rearrange_and_update_stride (xBC , "b s d -> b d s" ), conv1d_weight , conv1d_bias ,
955- rearrange (dxBC , "b s d -> b d s" ), seq_idx , None , None , rearrange_and_update_stride (dxBC_given ), False , ctx .activation in ["silu" , "swish" ]
965+ rearrange (ensure_stride (xBC ), "b s d -> b d s" ), conv1d_weight , conv1d_bias ,
966+ # It might be okay to not run ensure_stride on dxBC, but we're not sure. So playing safe here.
967+ rearrange (ensure_stride (dxBC ), "b s d -> b d s" ), seq_idx , None , None ,
968+ rearrange (ensure_stride (dxBC_given ), "b s d -> b d s" ), False , ctx .activation in ["silu" , "swish" ]
956969 )
970+ dxBC_given_update = rearrange (dxBC_given_update , "b d s -> b s d" )
957971 if dxBC_given .stride () != dxBC_given_update .stride ():
958972 dxBC_given .copy_ (dxBC_given_update )
959973 else :
960974 dxBC_given = dxBC_given_update
961- dxBC_given = rearrange (dxBC_given , "b d s -> b s d" )
962975 return dzxbcdt , dweight , dbias , ddt_bias , dA , dD , None , dinitial_states , None , None , None , None , drmsnorm_weight , None , doutproj_weight , doutproj_bias , None , None , None
963976
964977
0 commit comments