---
title: nabla
---

<div class="python-reference">
<a id="fastvideo.attention.backends.nabla-classes"></a>
<a id="fastvideo.attention.backends.nabla"></a>
<p>NABLA block-sparse flex-attention backend (Kandinsky5 "nabla" checkpoints).</p>
<p>The block mask is data-dependent: nablaT_v2 mean-pools 64-token blocks of the
fractal-ordered sequence, thresholds the softmaxed block map, and ORs it with a
precomputed spatio-temporal-window (STA) mask carried on the attention
metadata. The mask spans the full sequence, so this backend does not support
sequence parallelism — use it via LocalAttention only.</p>
<h2 id="fastvideo.attention.backends.nabla.AttentionBackend"><code>fastvideo.attention.backends.nabla.AttentionBackend</code></h2>
<pre class="doc-signature"><code>AttentionBackend()</code></pre>
<p>Abstract class for attention backends.</p>
<h3 id="fastvideo.attention.backends.nabla.AttentionBackend.get_name"><code>fastvideo.attention.backends.nabla.AttentionBackend.get_name</code></h3>
<pre class="doc-signature"><code>get_name() -&gt; str</code></pre>

<h3 id="fastvideo.attention.backends.nabla.AttentionBackend.get_impl_cls"><code>fastvideo.attention.backends.nabla.AttentionBackend.get_impl_cls</code></h3>
<pre class="doc-signature"><code>get_impl_cls() -&gt; type&#91;AttentionImpl&#93;</code></pre>

<h3 id="fastvideo.attention.backends.nabla.AttentionBackend.get_metadata_cls"><code>fastvideo.attention.backends.nabla.AttentionBackend.get_metadata_cls</code></h3>
<pre class="doc-signature"><code>get_metadata_cls() -&gt; type&#91;AttentionMetadata&#93;</code></pre>

<h3 id="fastvideo.attention.backends.nabla.AttentionBackend.get_builder_cls"><code>fastvideo.attention.backends.nabla.AttentionBackend.get_builder_cls</code></h3>
<pre class="doc-signature"><code>get_builder_cls() -&gt; type&#91;AttentionMetadataBuilder&#93;</code></pre>

<h2 id="fastvideo.attention.backends.nabla.AttentionImpl"><code>fastvideo.attention.backends.nabla.AttentionImpl</code></h2>
<pre class="doc-signature"><code>AttentionImpl(num_heads: int, head_size: int, softmax_scale: float, causal: bool = False, num_kv_heads: int | None = None, prefix: str = &#x27;&#x27;, **extra_impl_args)</code></pre>


<h3 id="fastvideo.attention.backends.nabla.AttentionImpl.preprocess_qkv"><code>fastvideo.attention.backends.nabla.AttentionImpl.preprocess_qkv</code></h3>
<pre class="doc-signature"><code>preprocess_qkv(qkv: torch.Tensor, attn_metadata: T) -&gt; torch.Tensor</code></pre>
<p>Preprocess QKV tensor before performing attention operation.</p>
<p>Default implementation returns the tensor unchanged.
Subclasses can override this to implement custom preprocessing
like reshaping, tiling, scaling, or other transformations.</p>
<p>Called AFTER all_to_all for distributed attention</p>
<h4>Parameters</h4>
<dl>
<dt><code>qkv: torch.Tensor</code></dt><dd><p>The query-key-value tensor</p></dd>
<dt><code>attn_metadata: T</code></dt><dd><p>Metadata for the attention operation</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>Processed QKV tensor</p></dd>
</dl>
<h3 id="fastvideo.attention.backends.nabla.AttentionImpl.postprocess_output"><code>fastvideo.attention.backends.nabla.AttentionImpl.postprocess_output</code></h3>
<pre class="doc-signature"><code>postprocess_output(output: torch.Tensor, attn_metadata: T) -&gt; torch.Tensor</code></pre>
<p>Postprocess the output tensor after the attention operation.</p>
<p>Default implementation returns the tensor unchanged.
Subclasses can override this to implement custom postprocessing
like untiling, scaling, or other transformations.</p>
<p>Called BEFORE all_to_all for distributed attention</p>
<h4>Parameters</h4>
<dl>
<dt><code>output: torch.Tensor</code></dt><dd><p>The output tensor from the attention operation</p></dd>
<dt><code>attn_metadata: T</code></dt><dd><p>Metadata for the attention operation</p></dd>
</dl>
<h4>Returns</h4>
<dl>
<dt><code>torch.Tensor</code></dt><dd><p>Postprocessed output tensor</p></dd>
</dl>
<h3 id="fastvideo.attention.backends.nabla.AttentionImpl.forward"><code>fastvideo.attention.backends.nabla.AttentionImpl.forward</code></h3>
<pre class="doc-signature"><code>forward(query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, attn_metadata: T) -&gt; torch.Tensor</code></pre>

<h2 id="fastvideo.attention.backends.nabla.AttentionMetadata"><code>fastvideo.attention.backends.nabla.AttentionMetadata</code></h2>
<pre class="doc-signature"><code>AttentionMetadata(current_timestep: int, *, VSA_sparsity: float = 0.0)</code></pre>
<p>Attention metadata for prefill and decode batched together.</p>

<h3 id="fastvideo.attention.backends.nabla.AttentionMetadata.asdict_zerocopy"><code>fastvideo.attention.backends.nabla.AttentionMetadata.asdict_zerocopy</code></h3>
<pre class="doc-signature"><code>asdict_zerocopy(skip_fields: set&#91;str&#93; | None = None) -&gt; dict&#91;str, Any&#93;</code></pre>
<p>Similar to dataclasses.asdict, but avoids deepcopying.</p>
<h2 id="fastvideo.attention.backends.nabla.AttentionMetadataBuilder"><code>fastvideo.attention.backends.nabla.AttentionMetadataBuilder</code></h2>
<pre class="doc-signature"><code>AttentionMetadataBuilder()</code></pre>
<p>Abstract class for attention metadata builders.</p>
<p>Create the builder, remember some configuration and parameters.</p>
<h3 id="fastvideo.attention.backends.nabla.AttentionMetadataBuilder.prepare"><code>fastvideo.attention.backends.nabla.AttentionMetadataBuilder.prepare</code></h3>
<pre class="doc-signature"><code>prepare() -&gt; None</code></pre>
<p>Prepare for one batch.</p>
<h3 id="fastvideo.attention.backends.nabla.AttentionMetadataBuilder.build"><code>fastvideo.attention.backends.nabla.AttentionMetadataBuilder.build</code></h3>
<pre class="doc-signature"><code>build(**kwargs: Any) -&gt; AttentionMetadata</code></pre>
<p>Build attention metadata with on-device tensors.</p>
<h2 id="fastvideo.attention.backends.nabla.nablaT_v2"><code>fastvideo.attention.backends.nabla.nablaT_v2</code></h2>
<pre class="doc-signature"><code>nablaT_v2(q: torch.Tensor, k: torch.Tensor, sta: torch.Tensor, thr: float = 0.9) -&gt; BlockMask</code></pre>

<details><summary>Source</summary><pre><code>def nablaT_v2(
    q: torch.Tensor,
    k: torch.Tensor,
    sta: torch.Tensor,
    thr: float = 0.9,
) -&gt; &quot;BlockMask&quot;:
    q = q.transpose(1, 2).contiguous()
    k = k.transpose(1, 2).contiguous()

    # Map estimation
    B, h, S, D = q.shape
    s1 = S // 64
    qa = q.reshape(B, h, s1, 64, D).mean(-2)
    ka = k.reshape(B, h, s1, 64, D).mean(-2).transpose(-2, -1)
    map = qa @ ka

    map = torch.softmax(map / math.sqrt(D), dim=-1)
    # Map binarization
    vals, inds = map.sort(-1)
    cvals = vals.cumsum_(-1)
    mask = (cvals &gt;= 1 - thr).int()
    mask = mask.gather(-1, inds.argsort(-1))

    mask = torch.logical_or(mask, sta)

    # BlockMask creation
    kv_nb = mask.sum(-1).to(torch.int32)
    kv_inds = mask.argsort(dim=-1, descending=True).to(torch.int32)
    return BlockMask.from_kv_blocks(torch.zeros_like(kv_nb), kv_inds, kv_nb, kv_inds, BLOCK_SIZE=64, mask_mod=None)</code></pre></details>
<h2 id="fastvideo.attention.backends.nabla.NablaAttentionBackend"><code>fastvideo.attention.backends.nabla.NablaAttentionBackend</code></h2>
<pre class="doc-signature"><code>NablaAttentionBackend()</code></pre>

<details><summary>Source</summary><pre><code>class NablaAttentionBackend(AttentionBackend):

    @staticmethod
    def get_name() -&gt; str:
        return &quot;NABLA_ATTN&quot;

    @staticmethod
    def get_impl_cls() -&gt; type&#91;&quot;NablaAttentionImpl&quot;&#93;:
        return NablaAttentionImpl

    @staticmethod
    def get_metadata_cls() -&gt; type&#91;&quot;NablaAttentionMetadata&quot;&#93;:
        return NablaAttentionMetadata

    @staticmethod
    def get_builder_cls() -&gt; type&#91;&quot;NablaAttentionMetadataBuilder&quot;&#93;:
        return NablaAttentionMetadataBuilder</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionBackend.get_name"><code>fastvideo.attention.backends.nabla.NablaAttentionBackend.get_name</code></h3>
<pre class="doc-signature"><code>get_name() -&gt; str</code></pre>

<details><summary>Source</summary><pre><code>@staticmethod
def get_name() -&gt; str:
    return &quot;NABLA_ATTN&quot;</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionBackend.get_impl_cls"><code>fastvideo.attention.backends.nabla.NablaAttentionBackend.get_impl_cls</code></h3>
<pre class="doc-signature"><code>get_impl_cls() -&gt; type&#91;NablaAttentionImpl&#93;</code></pre>

<details><summary>Source</summary><pre><code>@staticmethod
def get_impl_cls() -&gt; type&#91;&quot;NablaAttentionImpl&quot;&#93;:
    return NablaAttentionImpl</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionBackend.get_metadata_cls"><code>fastvideo.attention.backends.nabla.NablaAttentionBackend.get_metadata_cls</code></h3>
<pre class="doc-signature"><code>get_metadata_cls() -&gt; type&#91;NablaAttentionMetadata&#93;</code></pre>

<details><summary>Source</summary><pre><code>@staticmethod
def get_metadata_cls() -&gt; type&#91;&quot;NablaAttentionMetadata&quot;&#93;:
    return NablaAttentionMetadata</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionBackend.get_builder_cls"><code>fastvideo.attention.backends.nabla.NablaAttentionBackend.get_builder_cls</code></h3>
<pre class="doc-signature"><code>get_builder_cls() -&gt; type&#91;NablaAttentionMetadataBuilder&#93;</code></pre>

<details><summary>Source</summary><pre><code>@staticmethod
def get_builder_cls() -&gt; type&#91;&quot;NablaAttentionMetadataBuilder&quot;&#93;:
    return NablaAttentionMetadataBuilder</code></pre></details>
<h2 id="fastvideo.attention.backends.nabla.NablaAttentionMetadata"><code>fastvideo.attention.backends.nabla.NablaAttentionMetadata</code></h2>
<pre class="doc-signature"><code>NablaAttentionMetadata(current_timestep: int, sta_mask: torch.Tensor = None, P: float = 0.9, visual_shape: tuple&#91;int, int, int&#93; = (0, 0, 0), *, VSA_sparsity: float = 0.0)</code></pre>


<details><summary>Source</summary><pre><code>@dataclass
class NablaAttentionMetadata(AttentionMetadata):
    # Block-level STA window mask &#91;1, 1, S/64, S/64&#93;, precomputed once per run.
    sta_mask: torch.Tensor = None  # type: ignore&#91;assignment&#93;
    # Cumulative-probability threshold for block-map binarization.
    P: float = 0.9
    visual_shape: tuple&#91;int, int, int&#93; = (0, 0, 0)</code></pre></details>
<h2 id="fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder"><code>fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder</code></h2>
<pre class="doc-signature"><code>NablaAttentionMetadataBuilder()</code></pre>


<details><summary>Source</summary><pre><code>class NablaAttentionMetadataBuilder(AttentionMetadataBuilder):

    def __init__(self) -&gt; None:
        pass

    def prepare(self) -&gt; None:
        pass

    def build(
        self,
        current_timestep: int,
        sta_mask: torch.Tensor,
        P: float,
        visual_shape: tuple&#91;int, int, int&#93;,
        **kwargs: Any,
    ) -&gt; NablaAttentionMetadata:
        return NablaAttentionMetadata(
            current_timestep=current_timestep,
            sta_mask=sta_mask,
            P=P,
            visual_shape=visual_shape,
        )</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder.prepare"><code>fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder.prepare</code></h3>
<pre class="doc-signature"><code>prepare() -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def prepare(self) -&gt; None:
    pass</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder.build"><code>fastvideo.attention.backends.nabla.NablaAttentionMetadataBuilder.build</code></h3>
<pre class="doc-signature"><code>build(current_timestep: int, sta_mask: torch.Tensor, P: float, visual_shape: tuple&#91;int, int, int&#93;, **kwargs: Any) -&gt; NablaAttentionMetadata</code></pre>

<details><summary>Source</summary><pre><code>def build(
    self,
    current_timestep: int,
    sta_mask: torch.Tensor,
    P: float,
    visual_shape: tuple&#91;int, int, int&#93;,
    **kwargs: Any,
) -&gt; NablaAttentionMetadata:
    return NablaAttentionMetadata(
        current_timestep=current_timestep,
        sta_mask=sta_mask,
        P=P,
        visual_shape=visual_shape,
    )</code></pre></details>
<h2 id="fastvideo.attention.backends.nabla.NablaAttentionImpl"><code>fastvideo.attention.backends.nabla.NablaAttentionImpl</code></h2>
<pre class="doc-signature"><code>NablaAttentionImpl(num_heads: int, head_size: int, softmax_scale: float, causal: bool = False, num_kv_heads: int | None = None, prefix: str = &#x27;&#x27;, **extra_impl_args)</code></pre>


<details><summary>Source</summary><pre><code>class NablaAttentionImpl(AttentionImpl):

    def __init__(
        self,
        num_heads: int,
        head_size: int,
        softmax_scale: float,
        causal: bool = False,
        num_kv_heads: int | None = None,
        prefix: str = &quot;&quot;,
        **extra_impl_args,
    ) -&gt; None:
        if not CAN_USE_FLEX_ATTN:
            raise RuntimeError(&quot;NABLA attention requires torch.nn.attention.flex_attention, &quot;
                               &quot;which is unavailable in this PyTorch build.&quot;)
        if causal:
            raise ValueError(&quot;NABLA attention does not support causal masking.&quot;)

    def forward(
        self,
        query: torch.Tensor,
        key: torch.Tensor,
        value: torch.Tensor,
        attn_metadata: NablaAttentionMetadata,
    ) -&gt; torch.Tensor:
        # q/k/v: &#91;B, S, heads, head_dim&#93;, fractal-ordered by the model; S % 64 == 0.
        block_mask = nablaT_v2(query, key, attn_metadata.sta_mask, thr=attn_metadata.P)
        return flex_attention(
            query=query.transpose(1, 2),
            key=key.transpose(1, 2),
            value=value.transpose(1, 2),
            block_mask=block_mask,
        ).transpose(1, 2)</code></pre></details>
<h3 id="fastvideo.attention.backends.nabla.NablaAttentionImpl.forward"><code>fastvideo.attention.backends.nabla.NablaAttentionImpl.forward</code></h3>
<pre class="doc-signature"><code>forward(query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, attn_metadata: NablaAttentionMetadata) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def forward(
    self,
    query: torch.Tensor,
    key: torch.Tensor,
    value: torch.Tensor,
    attn_metadata: NablaAttentionMetadata,
) -&gt; torch.Tensor:
    # q/k/v: &#91;B, S, heads, head_dim&#93;, fractal-ordered by the model; S % 64 == 0.
    block_mask = nablaT_v2(query, key, attn_metadata.sta_mask, thr=attn_metadata.P)
    return flex_attention(
        query=query.transpose(1, 2),
        key=key.transpose(1, 2),
        value=value.transpose(1, 2),
        block_mask=block_mask,
    ).transpose(1, 2)</code></pre></details>
</div>
