---
title: nvfp4_qat_config
---

<div class="python-reference">
<a id="fastvideo.layers.quantization.nvfp4_qat_config-classes"></a>
<a id="fastvideo.layers.quantization.nvfp4_qat_config-functions"></a>
<a id="fastvideo.layers.quantization.nvfp4_qat_config"></a>
<p>NVFP4 quantization-aware (QAD) linear method, inference path.</p>
<p>Quantizes every targeted linear's weight to NVFP4 once at load time and
runs each forward as a registered flashinfer-backed FP4 matmul. The
original fp16/bf16 weight is <em>popped</em> immediately after quantization so
the half-precision copy does not keep occupying GPU memory — that's
what lets a Wan-2.1 pipeline stay fully resident on a single GPU
without any CPU offloading.</p>
<p>The quantize / matmul custom ops are owned by
:mod:<code>fastvideo.layers.quantization.nvfp4_config</code> and registered under
the <code>fastvideo_fp4::</code> namespace. We reuse them here for two reasons:</p>
<ol>
<li>Re-registering the same op name in a second module would raise.</li>
<li>The registered ops have <code>register_fake</code> shape/dtype kernels, which
   is what makes the inference pipeline's per-block <code>torch.compile</code>
   trace through without graph breaks. Calling raw flashinfer functions
   (the old behavior of this file, plus a <code>@torch.compile</code> on
   <code>apply</code>) graph-breaks at every quantize and every matmul.</li>
</ol>
<p>For QAT <em>training</em>, see <code>nvfp4_qat_train_config</code> which keeps the
weight trainable and fake-quantizes on the fly via a straight-through
estimator.</p>
<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig</code></h2>
<pre class="doc-signature"><code>QuantizationConfig()</code></pre>
<p>Base class for quantization configs.</p>

<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_name"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_name</code></h3>
<pre class="doc-signature"><code>get_name() -&gt; QuantizationMethods</code></pre>
<p>Name of the quantization method.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_supported_act_dtypes"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_supported_act_dtypes</code></h3>
<pre class="doc-signature"><code>get_supported_act_dtypes() -&gt; list&#91;torch.dtype&#93;</code></pre>
<p>List of supported activation dtypes.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_min_capability"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_min_capability</code></h3>
<pre class="doc-signature"><code>get_min_capability() -&gt; int</code></pre>
<p>Minimum GPU capability to support the quantization method.</p>
<p>E.g., 70 for Volta, 75 for Turing, 80 for Ampere.
This requirement is due to the custom CUDA kernels used by the
quantization method.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_config_filenames"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_config_filenames</code></h3>
<pre class="doc-signature"><code>get_config_filenames() -&gt; list&#91;str&#93;</code></pre>
<p>List of filenames to search for in the model directory.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.from_config"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.from_config</code></h3>
<pre class="doc-signature"><code>from_config(config: dict&#91;str, Any&#93;) -&gt; QuantizationConfig</code></pre>
<p>Create a config class from the model's quantization config.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.override_quantization_method"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.override_quantization_method</code></h3>
<pre class="doc-signature"><code>override_quantization_method(hf_quant_cfg, user_quant) -&gt; QuantizationMethods | None</code></pre>
<p>Detects if this quantization method can support a given checkpoint
format by overriding the user specified quantization method -- 
this method should only be overwritten by subclasses in exceptional 
circumstances</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_from_keys"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_from_keys</code></h3>
<pre class="doc-signature"><code>get_from_keys(config: dict&#91;str, Any&#93;, keys: list&#91;str&#93;) -&gt; Any</code></pre>
<p>Get a value from the model's quantization config.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_from_keys_or"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_from_keys_or</code></h3>
<pre class="doc-signature"><code>get_from_keys_or(config: dict&#91;str, Any&#93;, keys: list&#91;str&#93;, default: Any) -&gt; Any</code></pre>
<p>Get a optional value from the model's quantization config.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_quant_method"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_quant_method</code></h3>
<pre class="doc-signature"><code>get_quant_method(layer: torch.nn.Module, prefix: str) -&gt; QuantizeMethodBase | None</code></pre>
<p>Get the quantize method to use for the quantized layer.</p>
<h4>Parameters</h4>
<dl>
<dt><code>layer: torch.nn.Module</code></dt><dd><p>The layer for the quant method.</p></dd>
<dt><code>prefix: str</code></dt><dd><p>The full name of the layer in the state dict</p></dd>
</dl>
<p>Returns:
    The quantize method. None if the given layer doesn't support quant
    method.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.validate_runtime"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.validate_runtime</code></h3>
<pre class="doc-signature"><code>validate_runtime(device: torch.device) -&gt; None</code></pre>
<p>Fail fast on a device the scheme cannot execute on.</p>
<p>Called once by loaders that select a serialized checkpoint scheme,
before any weight is read. The default accepts every device; schemes
with kernel or capability requirements override it.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_cache_scale"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizationConfig.get_cache_scale</code></h3>
<pre class="doc-signature"><code>get_cache_scale(name: str) -&gt; str | None</code></pre>

<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase</code></h2>
<pre class="doc-signature"><code>QuantizeMethodBase()</code></pre>
<p>Base class for different quantized methods.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.create_weights"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.create_weights</code></h3>
<pre class="doc-signature"><code>create_weights(layer: torch.nn.Module, *weight_args, **extra_weight_attrs)</code></pre>
<p>Create weights for a layer.</p>
<p>The weights will be set as attributes of the layer.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.apply"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.apply</code></h3>
<pre class="doc-signature"><code>apply(layer: torch.nn.Module, *args, **kwargs) -&gt; torch.Tensor</code></pre>
<p>Apply the weights in layer to the input tensor.</p>
<p>Expects create_weights to have been called before on the layer.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.embedding"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.embedding</code></h3>
<pre class="doc-signature"><code>embedding(layer: torch.nn.Module, *args, **kwargs) -&gt; torch.Tensor</code></pre>
<p>Gather embeddings in the layer based on indices in the input tensor.</p>
<p>Expects create_weights to have been called before on the layer.</p>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.process_weights_after_loading"><code>fastvideo.layers.quantization.nvfp4_qat_config.QuantizeMethodBase.process_weights_after_loading</code></h3>
<pre class="doc-signature"><code>process_weights_after_loading(layer: nn.Module) -&gt; None</code></pre>
<p>Process the weight after loading.</p>
<p>This can be used for example, to transpose weights for computation.</p>
<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.set_weight_attrs"><code>fastvideo.layers.quantization.nvfp4_qat_config.set_weight_attrs</code></h2>
<pre class="doc-signature"><code>set_weight_attrs(weight: torch.Tensor, weight_attrs: dict&#91;str, Any&#93; | None)</code></pre>
<p>Set attributes on a weight tensor.</p>
<p>This method is used to set attributes on a weight tensor. This method
will not overwrite existing attributes.</p>
<h3>Parameters</h3>
<dl>
<dt><code>weight: torch.Tensor</code></dt><dd><p>The weight tensor.</p></dd>
<dt><code>weight_attrs: dict[str, Any] | None</code></dt><dd><p>A dictionary of attributes to set on the weight tensor.</p></dd>
</dl>
<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod</code></h2>
<pre class="doc-signature"><code>NVFP4QATQuantizeMethod()</code></pre>
<p>Inference-only NVFP4 linear method with weight popping.</p>
<p>The dense <code>weight</code> parameter is materialized at load time only so
that :func:<code>convert_model_to_fp4</code> can read it once; the loader then
removes it via <code>mod._parameters.pop('weight')</code>. From that point
forward, <code>apply</code> reads only <code>_fp4_weight</code> / <code>_fp4_weight_scale</code>
/ <code>_weight_global_sf</code>.</p>

<details><summary>Source</summary><pre><code>class NVFP4QATQuantizeMethod(QuantizeMethodBase):
    &quot;&quot;&quot;Inference-only NVFP4 linear method with weight popping.

    The dense ``weight`` parameter is materialized at load time only so
    that :func:`convert_model_to_fp4` can read it once; the loader then
    removes it via ``mod._parameters.pop(&#x27;weight&#x27;)``. From that point
    forward, ``apply`` reads only ``_fp4_weight`` / ``_fp4_weight_scale``
    / ``_weight_global_sf``.
    &quot;&quot;&quot;

    def __init__(self) -&gt; None:
        super().__init__()
        self.weight_fp4 = None
        self.weight_scale = None
        # Static input global scale factor. Matches the FastVideo-Quantization
        # production path; recomputing it per-call via a ``.max()`` reduction
        # (the previous behavior) adds a sync point, costs a kernel launch,
        # and produces a data-dependent value that prevents CUDA-graph
        # capture under ``torch.compile(mode=&#x27;reduce-overhead&#x27;)``.
        self.x_global_sf = torch.tensor(1.0, device=&quot;cuda&quot;, dtype=torch.float32)

    def create_weights(self, layer: torch.nn.Module, input_size_per_partition: int, output_partition_sizes: list&#91;int&#93;,
                       input_size: int, output_size: int, params_dtype: torch.dtype, **extra_weight_attrs) -&gt; None:
        weight = Parameter(torch.empty(
            sum(output_partition_sizes),
            input_size_per_partition,
            dtype=params_dtype,
        ),
                           requires_grad=False)
        set_weight_attrs(weight, &#123;&quot;input_dim&quot;: 1, &quot;output_dim&quot;: 0&#125;)
        layer.register_parameter(&quot;weight&quot;, weight)
        set_weight_attrs(weight, extra_weight_attrs)

    def apply(self, layer: torch.nn.Module, x: torch.Tensor, bias: torch.Tensor | None = None) -&gt; torch.Tensor:
        # ``_fp4_weight`` carries the (out, in/2) packed fp4 weight, so its
        # row count is the output dim even after the dense weight is popped.
        out_dim = layer._fp4_weight.shape&#91;0&#93;
        original_shape = x.shape

        assert x.dtype in (torch.bfloat16, torch.float16), (f&quot;only allow bf16/fp16 inputs to fp4 linear, got &#123;x.dtype&#125;&quot;)
        x = x.view(-1, x.shape&#91;-1&#93;)
        x_global_sf = self.x_global_sf
        x_fp4, x_scale = _nvfp4_quantize(
            x,
            x_global_sf,
            sfLayout=_layout_128x4(),
            do_shuffle=False,
        )

        weight_fp4 = layer._fp4_weight
        weight_scale = layer._fp4_weight_scale
        weight_global_sf = layer._weight_global_sf

        out = _mm_fp4(
            x_fp4,
            weight_fp4.T,
            x_scale,
            weight_scale.T,
            1.0 / (x_global_sf * weight_global_sf),
            torch.bfloat16,
            None,
            backend=&quot;cutlass&quot;,
        )

        if bias is not None:
            out = out + bias
        out = out.view(*original_shape&#91;:-1&#93;, out_dim)
        return out</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod.create_weights"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod.create_weights</code></h3>
<pre class="doc-signature"><code>create_weights(layer: torch.nn.Module, input_size_per_partition: int, output_partition_sizes: list&#91;int&#93;, input_size: int, output_size: int, params_dtype: torch.dtype, **extra_weight_attrs) -&gt; None</code></pre>

<details><summary>Source</summary><pre><code>def create_weights(self, layer: torch.nn.Module, input_size_per_partition: int, output_partition_sizes: list&#91;int&#93;,
                   input_size: int, output_size: int, params_dtype: torch.dtype, **extra_weight_attrs) -&gt; None:
    weight = Parameter(torch.empty(
        sum(output_partition_sizes),
        input_size_per_partition,
        dtype=params_dtype,
    ),
                       requires_grad=False)
    set_weight_attrs(weight, &#123;&quot;input_dim&quot;: 1, &quot;output_dim&quot;: 0&#125;)
    layer.register_parameter(&quot;weight&quot;, weight)
    set_weight_attrs(weight, extra_weight_attrs)</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod.apply"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATQuantizeMethod.apply</code></h3>
<pre class="doc-signature"><code>apply(layer: torch.nn.Module, x: torch.Tensor, bias: torch.Tensor | None = None) -&gt; torch.Tensor</code></pre>

<details><summary>Source</summary><pre><code>def apply(self, layer: torch.nn.Module, x: torch.Tensor, bias: torch.Tensor | None = None) -&gt; torch.Tensor:
    # ``_fp4_weight`` carries the (out, in/2) packed fp4 weight, so its
    # row count is the output dim even after the dense weight is popped.
    out_dim = layer._fp4_weight.shape&#91;0&#93;
    original_shape = x.shape

    assert x.dtype in (torch.bfloat16, torch.float16), (f&quot;only allow bf16/fp16 inputs to fp4 linear, got &#123;x.dtype&#125;&quot;)
    x = x.view(-1, x.shape&#91;-1&#93;)
    x_global_sf = self.x_global_sf
    x_fp4, x_scale = _nvfp4_quantize(
        x,
        x_global_sf,
        sfLayout=_layout_128x4(),
        do_shuffle=False,
    )

    weight_fp4 = layer._fp4_weight
    weight_scale = layer._fp4_weight_scale
    weight_global_sf = layer._weight_global_sf

    out = _mm_fp4(
        x_fp4,
        weight_fp4.T,
        x_scale,
        weight_scale.T,
        1.0 / (x_global_sf * weight_global_sf),
        torch.bfloat16,
        None,
        backend=&quot;cutlass&quot;,
    )

    if bias is not None:
        out = out + bias
    out = out.view(*original_shape&#91;:-1&#93;, out_dim)
    return out</code></pre></details>
<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig</code></h2>
<pre class="doc-signature"><code>NVFP4QATConfig(target_layers: tuple&#91;str, ...&#93; | None = None)</code></pre>
<p>NVFP4 (Wan-style) linear quantization, inference.</p>
<h3>Parameters</h3>
<dl>
<dt><code>target_layers: tuple[str, ...] | None</code></dt><dd><p>Substrings matched against each linear layer's
prefix. A layer is quantized if any substring is contained in
its prefix. Defaults to the standard Wan attention + FFN
projections (:data:<code>DEFAULT_FP4_LAYERS</code>).</p></dd>
</dl>

<details><summary>Source</summary><pre><code>class NVFP4QATConfig(QuantizationConfig):
    &quot;&quot;&quot;NVFP4 (Wan-style) linear quantization, inference.

    Args:
        target_layers: Substrings matched against each linear layer&#x27;s
            prefix. A layer is quantized if any substring is contained in
            its prefix. Defaults to the standard Wan attention + FFN
            projections (:data:`DEFAULT_FP4_LAYERS`).
    &quot;&quot;&quot;

    def __init__(self, target_layers: tuple&#91;str, ...&#93; | None = None) -&gt; None:
        super().__init__()
        self.target_layers = (tuple(target_layers) if target_layers else DEFAULT_FP4_LAYERS)

    def get_name(self) -&gt; str:
        return &quot;nvfp4_qat&quot;

    def get_supported_act_dtypes(self) -&gt; list&#91;torch.dtype&#93;:
        return &#91;torch.bfloat16, torch.float16&#93;

    @classmethod
    def get_min_capability(cls) -&gt; int:
        return 100

    @staticmethod
    def get_config_filenames() -&gt; list&#91;str&#93;:
        return &#91;&#93;

    @classmethod
    def from_config(cls, config: dict&#91;str, Any&#93;) -&gt; NVFP4QATConfig:
        target_layers = config.get(&quot;target_layers&quot;)
        if target_layers is not None:
            target_layers = tuple(target_layers)
        return cls(target_layers=target_layers)

    def get_quant_method(self, layer: torch.nn.Module, prefix: str):
        from fastvideo.layers.linear import LinearBase
        if isinstance(layer, LinearBase) and any(name in prefix for name in self.target_layers):
            return NVFP4QATQuantizeMethod()
        return None</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_name"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_name</code></h3>
<pre class="doc-signature"><code>get_name() -&gt; str</code></pre>

<details><summary>Source</summary><pre><code>def get_name(self) -&gt; str:
    return &quot;nvfp4_qat&quot;</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_supported_act_dtypes"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_supported_act_dtypes</code></h3>
<pre class="doc-signature"><code>get_supported_act_dtypes() -&gt; list&#91;torch.dtype&#93;</code></pre>

<details><summary>Source</summary><pre><code>def get_supported_act_dtypes(self) -&gt; list&#91;torch.dtype&#93;:
    return &#91;torch.bfloat16, torch.float16&#93;</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_min_capability"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_min_capability</code></h3>
<pre class="doc-signature"><code>get_min_capability() -&gt; int</code></pre>

<details><summary>Source</summary><pre><code>@classmethod
def get_min_capability(cls) -&gt; int:
    return 100</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_config_filenames"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_config_filenames</code></h3>
<pre class="doc-signature"><code>get_config_filenames() -&gt; list&#91;str&#93;</code></pre>

<details><summary>Source</summary><pre><code>@staticmethod
def get_config_filenames() -&gt; list&#91;str&#93;:
    return &#91;&#93;</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.from_config"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.from_config</code></h3>
<pre class="doc-signature"><code>from_config(config: dict&#91;str, Any&#93;) -&gt; NVFP4QATConfig</code></pre>

<details><summary>Source</summary><pre><code>@classmethod
def from_config(cls, config: dict&#91;str, Any&#93;) -&gt; NVFP4QATConfig:
    target_layers = config.get(&quot;target_layers&quot;)
    if target_layers is not None:
        target_layers = tuple(target_layers)
    return cls(target_layers=target_layers)</code></pre></details>
<h3 id="fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_quant_method"><code>fastvideo.layers.quantization.nvfp4_qat_config.NVFP4QATConfig.get_quant_method</code></h3>
<pre class="doc-signature"><code>get_quant_method(layer: torch.nn.Module, prefix: str)</code></pre>

<details><summary>Source</summary><pre><code>def get_quant_method(self, layer: torch.nn.Module, prefix: str):
    from fastvideo.layers.linear import LinearBase
    if isinstance(layer, LinearBase) and any(name in prefix for name in self.target_layers):
        return NVFP4QATQuantizeMethod()
    return None</code></pre></details>
<h2 id="fastvideo.layers.quantization.nvfp4_qat_config.convert_model_to_fp4"><code>fastvideo.layers.quantization.nvfp4_qat_config.convert_model_to_fp4</code></h2>
<pre class="doc-signature"><code>convert_model_to_fp4(model: torch.nn.Module) -&gt; None</code></pre>
<p>Prequantize every FP4-tagged linear and drop its dense weight.</p>
<p>Walks the module tree, and for each layer whose <code>quant_method</code> is
an :class:<code>NVFP4QATQuantizeMethod</code>, computes the NVFP4 packed weight
/ scale / global-scale buffers, then pops the original fp16/bf16
<code>weight</code> parameter so it no longer occupies GPU memory.</p>
<details><summary>Source</summary><pre><code>def convert_model_to_fp4(model: torch.nn.Module) -&gt; None:
    &quot;&quot;&quot;Prequantize every FP4-tagged linear and drop its dense weight.

    Walks the module tree, and for each layer whose ``quant_method`` is
    an :class:`NVFP4QATQuantizeMethod`, computes the NVFP4 packed weight
    / scale / global-scale buffers, then pops the original fp16/bf16
    ``weight`` parameter so it no longer occupies GPU memory.
    &quot;&quot;&quot;
    SfLayout, _, _ = _require_flashinfer()
    from torch.distributed.tensor import DTensor  # type: ignore

    with torch.no_grad():
        for mod in model.modules():
            qm = getattr(mod, &quot;quant_method&quot;, None)
            if not isinstance(qm, NVFP4QATQuantizeMethod):
                continue

            weight = getattr(mod, &quot;weight&quot;, None)
            if weight is None:
                continue

            weight_local = weight.to_local() if isinstance(weight, DTensor) else weight  # type: ignore&#91;arg-type&#93;

            # Only the reduced scalar needs fp32; avoid a full fp32 copy.
            weight_absmax = (weight_local.detach().abs().nan_to_num().amax().to(dtype=torch.float32))
            weight_global_sf = (448 * 6) / weight_absmax
            fp4_w, fp4_s = _nvfp4_quantize(
                weight_local,
                weight_global_sf,
                sfLayout=SfLayout.layout_128x4,
                do_shuffle=False,
            )
            mod.register_buffer(&quot;_fp4_weight&quot;, fp4_w, persistent=False)
            mod.register_buffer(&quot;_fp4_weight_scale&quot;, fp4_s, persistent=False)
            mod.register_buffer(
                &quot;_weight_global_sf&quot;,
                weight_global_sf.to(dtype=torch.bfloat16),
                persistent=False,
            )

            # Drop the dense weight as soon as the fp4 buffers are installed
            # so it cannot keep occupying GPU memory.
            removed_weight = mod._parameters.pop(&quot;weight&quot;, None)
            if removed_weight is not None:
                removed_weight.grad = None
            del removed_weight, weight, weight_local, weight_absmax
    gc.collect()
    torch.cuda.empty_cache()</code></pre></details>
</div>
