# 缓存

缓存通过存储并复用不同层（如注意力层和前馈层）的中间输出，而非在每个推理步骤中执行完整计算，从而加速推理。它以占用更多内存为代价，显著提升生成速度，且无需额外训练。

本指南将向您展示如何使用 Diffusers 支持的缓存方法。

## 金字塔注意力广播

[Pyramid Attention Broadcast (PAB)](https://huggingface.co/papers/2408.12588) 基于以下观察：在生成过程的连续时间步之间，注意力输出之间的差异并不大。交叉注意力层中的注意力差异最小，且通常在更长的时间步范围内被缓存。随后是时间注意力层和空间注意力层。

> [!TIP]
> 并非所有视频模型都包含三种注意力机制（交叉注意力、时间注意力和空间注意力）！

PAB 可以与其他技术（如序列并行和 classifier-free guidance 并行（数据并行））结合使用，以实现近乎实时的视频生成。

设置一个 [PyramidAttentionBroadcastConfig](/docs/diffusers/v0.43.0/zh/api/cache#diffusers.PyramidAttentionBroadcastConfig) 并将其传递给 pipeline 的 transformer 以启用该功能。`spatial_attention_block_skip_range` 用于控制跳过空间注意力块中注意力计算的频率，而 `spatial_attention_timestep_skip_range` 则是需要跳过的时间步范围。请注意选择合适的范围，因为较小的间隔可能导致推理速度变慢，而较大的间隔则可能降低生成质量。

```python
import torch
from diffusers import CogVideoXPipeline, PyramidAttentionBroadcastConfig

pipeline = CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-5b", dtype=torch.bfloat16)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

config = PyramidAttentionBroadcastConfig(
    spatial_attention_block_skip_range=2,
    spatial_attention_timestep_skip_range=(100, 800),
    current_timestep_callback=lambda: pipe.current_timestep,
)
pipeline.transformer.enable_cache(config)
```

## FasterCache

[FasterCache](https://huggingface.co/papers/2410.19355) 会缓存并复用注意力特征，其原理与 [PAB](#pyramid-attention-broadcast) 类似，因为相邻时间步之间的输出差异很小。

当使用无分类器引导进行采样时（这在大多数基础模型中很常见），该方法也可以选择跳过无条件分支预测，并在连续时间步的预测潜在输出之间存在显著冗余时，从条件分支预测中对其进行估计。

设置一个 [FasterCacheConfig](/docs/diffusers/v0.43.0/zh/api/cache#diffusers.FasterCacheConfig) 并将其传递给 pipeline 的 transformer，以启用该功能。

```python
import torch
from diffusers import CogVideoXPipeline, FasterCacheConfig

pipe line= CogVideoXPipeline.from_pretrained("THUDM/CogVideoX-5b", dtype=torch.bfloat16)
pipeline.to("cuda")  # or "mps", "xpu", "cpu"

config = FasterCacheConfig(
    spatial_attention_block_skip_range=2,
    spatial_attention_timestep_skip_range=(-1, 681),
    current_timestep_callback=lambda: pipe.current_timestep,
    attention_weight_callback=lambda _: 0.3,
    unconditional_batch_skip_range=5,
    unconditional_batch_timestep_skip_range=(-1, 781),
    tensor_format="BFCHW",
)
pipeline.transformer.enable_cache(config)
```

## SeaCache

[SeaCache](https://huggingface.co/papers/2602.18993) 会对比连续去噪步骤之间的 Spectral-Evolution-Aware (SEA) 指标。当累积的指标变化低于阈值时，它会跳过计算开销较大的 transformer block 堆栈，并利用缓存的残差来预测其输出。该指标由构成生成输出的视觉潜变量（visual latents）构建。如果干净的条件帧属于该输出轨迹的一部分（例如在图生视频和视生视频生成中），则应将其包含在内。应排除那些用于条件化生成但不属于输出的一部分的独立视觉提示。文本条件被排除在外，因为它不是视觉潜变量。

Cosmos 3 Transfer 将控制提示作为独立的视觉序列进行打包，因此其适配器会将这些提示从指示器中排除。Control-CFG 分支在比较相同的输出轨迹时，会保留各自缓存的残差。控制提示仍然会对 transformer 进行条件化。

该实现为以下模型提供了内置适配器：

- **Cosmos 3** 是主要经过优化和基准测试的集成方案。它通过 post-normalization 边界缓存完整的解码器堆栈。
- **Wan T2V** 在 eager 模式下使用通用的重复块路径。此集成展示了另一种单流视频 Transformer 如何向 SeaCache 提供原始视觉潜变量；这并不意味着相同的缓存参数对 Wan 也是最优的，也不表示支持其他 Wan 变体。

其他视频 Transformer 在满足以下条件时，可以集成到通用路径中：使用 `CacheMixin`、暴露一个可识别的重复块列表，并在 `TransformerBlockRegistry` 中注册块的输入/输出布局。流水线必须在每次 Transformer 调用时进入 `cache_context`，附加 `step_index`、`sigma` 和 `num_inference_steps`，并为独立的轨迹（例如条件引导和非条件引导）使用不同的上下文名称。当没有内置适配器时，请传入一个 `raw_vision_callback`，该回调返回构成生成输出的视觉潜在变量。请针对每个模型和调度器验证输出质量并调整缓存参数；对 Cosmos 3 的支持和基准测试结果不会自动迁移。

### Cosmos 3

SeaCache 默认处于禁用状态。请在 transformer 上启用它；Cosmos 3 的去噪循环会将当前活跃的调度器步长、sigma 以及步数附加到每个 `cache_context` 调用中，因此无需进行额外的配置：

```python
from diffusers import Cosmos3OmniPipeline, SeaCacheConfig

pipe = Cosmos3OmniPipeline.from_pretrained("nvidia/Cosmos3-Nano")
pipe.transformer.enable_cache(SeaCacheConfig(threshold=0.2, max_consecutive_cached=2))
```

此模型级 API 适用于 [Cosmos3OmniPipeline](/docs/diffusers/v0.43.0/zh/api/pipelines/cosmos3#diffusers.Cosmos3OmniPipeline)、[Cosmos3OmniModularPipeline](/docs/diffusers/v0.43.0/zh/api/pipelines/cosmos3#diffusers.Cosmos3OmniModularPipeline) 和 [Cosmos3DistilledModularPipeline](/docs/diffusers/v0.43.0/zh/api/pipelines/cosmos3#diffusers.Cosmos3DistilledModularPipeline)。SeaCache 是一种近似优化，可能会改变生成的输出。当您需要每个去噪步骤都执行完整的 transformer 时，请调用 `pipe.transformer.disable_cache()`。

## FirstBlockCache

[FirstBlock Cache](https://huggingface.co/docs/diffusers/main/en/api/cache#diffusers.FirstBlockCacheConfig) 会检查去噪器（denoiser）的早期层在相邻时间步之间的变化程度。如果变化较小，模型将跳过代价高昂的后续层，并复用之前的输出。

```py
import torch
from diffusers import DiffusionPipeline
from diffusers.hooks import apply_first_block_cache, FirstBlockCacheConfig

pipeline = DiffusionPipeline.from_pretrained(
    "Qwen/Qwen-Image", dtype=torch.bfloat16
)
apply_first_block_cache(pipeline.transformer, FirstBlockCacheConfig(threshold=0.2))
```
## TaylorSeer 缓存

[TaylorSeer Cache](https://huggingface.co/papers/2403.06923) 通过利用泰勒级数展开来近似并缓存去噪步骤之间的中间激活值，从而加速扩散推理。该方法基于过去的计算预测未来的输出，并在指定的间隔处复用这些结果，以减少冗余计算。

该缓存机制在极小的额外内存开销下即可取得显著效果。有关详细的性能分析，请参阅[我们在此处的研究结果](https://github.com/huggingface/diffusers/pull/12648#issuecomment-3610615080)。

要启用 TaylorSeer Cache，请创建一个 [TaylorSeerCacheConfig](/docs/diffusers/v0.43.0/zh/api/cache#diffusers.TaylorSeerCacheConfig) 并将其传递给您的 pipeline 中的 transformer：

- `cache_interval`：在执行完整前向传播之前，复用缓存输出的步数
- `disable_cache_before_step`：初始步骤，使用完整计算来收集用于近似的数据
- `max_order`：近似精度（理论上，较高的值可以提高质量，但会增加内存使用量，我们建议将其设置为 `1`）

```python
import torch
from diffusers import FluxPipeline, TaylorSeerCacheConfig

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-dev",
    dtype=torch.bfloat16,
).to("cuda")  # or "mps", "xpu", "cpu"

config = TaylorSeerCacheConfig(
    cache_interval=5,
    max_order=1,
    disable_cache_before_step=10,
    taylor_factors_dtype=torch.bfloat16,
)
pipe.transformer.enable_cache(config)
```

## MagCache

[MagCache](https://github.com/Zehong-Ma/MagCache) 通过根据残差更新的幅度来跳过 Transformer 块，从而加速推理。它观察到，在扩散过程中，更新幅度（Output - Input）会可预测地衰减。通过基于预先计算的幅度比率累积“误差预算”，它动态地决定何时跳过计算并复用之前的残差。

MagCache 依赖于 **幅度比率**（`mag_ratios`），用于描述该衰减曲线。这些比率因模型检查点和调度器而异。内置的 `FLUX_MAG_RATIOS` 是在 FLUX.1 上测量得到的；其他模型（包括 Flux2 和 Flux2 Klein）需要各自进行校准运行。

要使用 MagCache，通常需遵循两步流程：**校准**和**推理**。

1.  **校准**：使用 `calibrate=True` 运行一次推理。该 hook 会测量残差幅度，并将计算出的比率打印到控制台。
2.  **推理**：将这些比率传递给 `MagCacheConfig` 以启用加速。

```python
import torch
from diffusers import FluxPipeline, MagCacheConfig

pipe = FluxPipeline.from_pretrained(
    "black-forest-labs/FLUX.1-schnell",
    dtype=torch.bfloat16
).to("cuda")  # or "mps", "xpu", "cpu"

# 1. Calibration Step
# Run full inference to measure model behavior.
calib_config = MagCacheConfig(calibrate=True, num_inference_steps=4)
pipe.transformer.enable_cache(calib_config)

# Run a prompt to trigger calibration
pipe("A cat playing chess", num_inference_steps=4)
# Logs will print something like: "MagCache Calibration Results: [1.0, 1.37, 0.97, 0.87]"

# 2. Inference Step
# Apply the specific ratios obtained from calibration for optimized speed.
# Note: For Flux models, you can also import defaults: 
# from diffusers.hooks.mag_cache import FLUX_MAG_RATIOS
mag_config = MagCacheConfig(
    mag_ratios=[1.0, 1.37, 0.97, 0.87],
    num_inference_steps=4
)

pipe.transformer.enable_cache(mag_config) 

image = pipe("A cat playing chess", num_inference_steps=4).images[0]
```

> [!NOTE]
> `mag_ratios` 表示模型固有的幅度衰减曲线。针对较高步数（例如 50 步）校准的比率可复用于较低的步数（例如 20 步）。该实现使用插值将曲线映射到当前的推理步数。

> [!TIP]
> 对于按顺序执行 Classifier-Free Guidance 的流水线（例如 Kandinsky 5.0），校准日志可能会打印两个数组：一个用于 Conditional 通道，另一个用于 Unconditional 通道。在大多数情况下，应使用第一个数组（Conditional）。

> [!TIP]
> 对于以**批量**方式运行 Classifier-Free Guidance 的流水线（例如 SDXL 或 Flux），模型处理的`hidden_states`包含拼接在一起的有条件分支和无条件分支。校准过程会自动处理这一点，生成一个表示联合行为的比率数组。您可以直接使用该生成的数组，无需任何修改。

