@@ -98,6 +98,7 @@ def __init__(
9898 hyena_omega_0 : float = 10.0 ,
9999 hyena_l_cache : int = 32 ,
100100 hyena_short_conv_fft_chunks : int = 0 ,
101+ use_flash_attention : bool = False ,
101102 ) -> None :
102103 """
103104 Args:
@@ -149,6 +150,7 @@ def __init__(
149150 hyena_omega_0: SIREN frequency. Default 10.0 (stable).
150151 hyena_l_cache: SIREN coordinate-grid cache size per spatial dim.
151152 hyena_short_conv_fft_chunks: channel chunk size for the FFT short conv (0 = no chunking).
153+ use_flash_attention: use flash attention (scaled dot product attention) at inference.
152154
153155 Examples::
154156
@@ -224,6 +226,7 @@ def __init__(
224226 hyena_omega_0 = hyena_omega_0 ,
225227 hyena_l_cache = hyena_l_cache ,
226228 hyena_short_conv_fft_chunks = hyena_short_conv_fft_chunks ,
229+ use_flash_attention = use_flash_attention ,
227230 )
228231
229232 self .encoder1 = UnetrBasicBlock (
@@ -513,6 +516,7 @@ def __init__(
513516 qkv_bias : bool = False ,
514517 attn_drop : float = 0.0 ,
515518 proj_drop : float = 0.0 ,
519+ use_flash_attention : bool = False ,
516520 ) -> None :
517521 """
518522 Args:
@@ -522,12 +526,17 @@ def __init__(
522526 qkv_bias: add a learnable bias to query, key, value.
523527 attn_drop: attention dropout rate.
524528 proj_drop: dropout rate of output.
529+ use_flash_attention: if True, use ``torch.nn.functional.scaled_dot_product_attention`` for the
530+ windowed attention. Equivalent to the default path but faster at inference; only used when
531+ autograd is disabled (e.g. under ``torch.no_grad()`` or ``torch.inference_mode()``, not
532+ ``eval()`` alone) and the module is not scripted.
525533 """
526534
527535 super ().__init__ ()
528536 self .dim = dim
529537 self .window_size = window_size
530538 self .num_heads = num_heads
539+ self .use_flash_attention = use_flash_attention
531540 head_dim = dim // num_heads
532541 self .scale = head_dim ** - 0.5
533542 mesh_args = torch .meshgrid .__kwdefaults__
@@ -584,12 +593,26 @@ def forward(self, x, mask):
584593 b , n , c = x .shape
585594 qkv = self .qkv (x ).reshape (b , n , 3 , self .num_heads , c // self .num_heads ).permute (2 , 0 , 3 , 1 , 4 )
586595 q , k , v = qkv [0 ], qkv [1 ], qkv [2 ]
587- q = q * self .scale
588- attn = q @ k .transpose (- 2 , - 1 )
589596 relative_position_bias = self .relative_position_bias_table [
590597 self .relative_position_index .clone ()[:n , :n ].reshape (- 1 ) # type: ignore[operator]
591598 ].reshape (n , n , - 1 )
592599 relative_position_bias = relative_position_bias .permute (2 , 0 , 1 ).contiguous ()
600+ if self .use_flash_attention and not torch .jit .is_scripting () and not torch .is_grad_enabled ():
601+ # additive bias combines the relative position bias and, for shifted windows, the attention mask
602+ if mask is not None :
603+ nw = mask .shape [0 ]
604+ bias = relative_position_bias .view (1 , 1 , self .num_heads , n , n ) + mask .reshape (1 , nw , 1 , n , n )
605+ bias = bias .expand (b // nw , nw , self .num_heads , n , n ).reshape (b , self .num_heads , n , n )
606+ else :
607+ bias = relative_position_bias .unsqueeze (0 )
608+ x = torch .nn .functional .scaled_dot_product_attention (
609+ q , k , v , attn_mask = bias .to (q .dtype ), dropout_p = 0.0 , scale = self .scale
610+ )
611+ x = x .transpose (1 , 2 ).reshape (b , n , c )
612+ return self .proj_drop (self .proj (x ))
613+
614+ q = q * self .scale
615+ attn = q @ k .transpose (- 2 , - 1 )
593616 attn = attn + relative_position_bias .unsqueeze (0 )
594617 if mask is not None :
595618 nw = mask .shape [0 ]
@@ -628,6 +651,7 @@ def __init__(
628651 act_layer : str = "GELU" ,
629652 norm_layer : type [LayerNorm ] = nn .LayerNorm ,
630653 use_checkpoint : bool = False ,
654+ use_flash_attention : bool = False ,
631655 ) -> None :
632656 """
633657 Args:
@@ -643,6 +667,7 @@ def __init__(
643667 act_layer: activation layer.
644668 norm_layer: normalization layer.
645669 use_checkpoint: use gradient checkpointing for reduced memory usage.
670+ use_flash_attention: use flash attention (scaled dot product attention) at inference.
646671 """
647672
648673 super ().__init__ ()
@@ -660,6 +685,7 @@ def __init__(
660685 qkv_bias = qkv_bias ,
661686 attn_drop = attn_drop ,
662687 proj_drop = drop ,
688+ use_flash_attention = use_flash_attention ,
663689 )
664690
665691 self .drop_path = DropPath (drop_path ) if drop_path > 0.0 else nn .Identity ()
@@ -924,6 +950,7 @@ def __init__(
924950 hyena_omega_0 : float = 10.0 ,
925951 hyena_l_cache : int = 32 ,
926952 hyena_short_conv_fft_chunks : int = 0 ,
953+ use_flash_attention : bool = False ,
927954 ) -> None :
928955 """
929956 Args:
@@ -946,6 +973,7 @@ def __init__(
946973 hyena_use_chunked_fft, hyena_use_fft_short_conv, hyena_omega_0, hyena_l_cache,
947974 hyena_short_conv_fft_chunks: forwarded to :class:`HyenaTransformerBlock`. See its
948975 docstring for semantics.
976+ use_flash_attention: use flash attention (scaled dot product attention) at inference.
949977 """
950978
951979 super ().__init__ ()
@@ -996,6 +1024,7 @@ def __init__(
9961024 drop_path = drop_path [i ] if isinstance (drop_path , list ) else drop_path ,
9971025 norm_layer = norm_layer ,
9981026 use_checkpoint = use_checkpoint ,
1027+ use_flash_attention = use_flash_attention ,
9991028 )
10001029 for i in range (depth )
10011030 ]
@@ -1079,6 +1108,7 @@ def __init__(
10791108 hyena_omega_0 : float = 10.0 ,
10801109 hyena_l_cache : int = 32 ,
10811110 hyena_short_conv_fft_chunks : int = 0 ,
1111+ use_flash_attention : bool = False ,
10821112 ) -> None :
10831113 """
10841114 Args:
@@ -1112,6 +1142,7 @@ def __init__(
11121142 hyena_use_chunked_fft, hyena_use_fft_short_conv, hyena_omega_0, hyena_l_cache,
11131143 hyena_short_conv_fft_chunks: HyenaND configuration. See
11141144 :class:`monai.networks.blocks.HyenaTransformerBlock` for semantics.
1145+ use_flash_attention: use flash attention (scaled dot product attention) at inference.
11151146 """
11161147
11171148 super ().__init__ ()
@@ -1193,6 +1224,7 @@ def __init__(
11931224 hyena_omega_0 = hyena_omega_0 ,
11941225 hyena_l_cache = hyena_l_cache ,
11951226 hyena_short_conv_fft_chunks = hyena_short_conv_fft_chunks ,
1227+ use_flash_attention = use_flash_attention ,
11961228 )
11971229 if i_layer == 0 :
11981230 self .layers1 .append (layer )
0 commit comments