DeepSeek V4 in vLLM: Efficient Long-context Attention

发表时间: 2026-04 · Blog post by vLLM Team (blog.vllm.ai)

原文: https://blog.vllm.ai/blog/2026-04-24-deepseek-v4

作者/机构:vLLM Team

速读

一句话结论
vLLM 框架通过统一逻辑块大小、将压缩状态视作滑动窗口以及多流算子融合等系统级优化,成功实现了 DeepSeek V4 家族模型在百万级上下文下的高效推理,将其 KV Cache 显存占用大幅降低了 8.7 倍。

要解决什么问题
长上下文推理面临显存容量和计算成本的双重物理卡点。随着上下文长度扩展至 100 万 tokens,即便使用此前显存效率极高的多头潜在注意力(MLA)架构,KV Cache 的线性增长依然会轻易撑爆 GPU 显存;同时,在如此长的序列上计算注意力,其时间开销会成为严重的性能瓶颈。为了绕开这些限制,DeepSeek V4 在算法层引入了极度复杂的异构注意力机制(混合了不同比例的 KV 压缩比、共享键值以及滑动窗口),但这给推理框架带来了严峻的系统工程挑战。在 vLLM 中直接实现该机制会导致严重的内存碎片化:不同层的压缩率不同使得内存块大小不一,且批处理时不同序列处于不同的压缩边界状态;此外,大量细碎的访存密集型算子会引发频繁的显存读写往返,导致内核启动开销激增,GPU 计算单元无法被充分打满。

怎么做的
为了在系统层面高效承载 DeepSeek V4 的异构注意力机制,vLLM 在内存管理和算子执行两条路线上进行了重构。算法内核上,DeepSeek V4 采用键值向量共享来节省一半显存,为了修正共享带来的绝对位置信息污染,对注意力输出应用逆旋转位置编码:

$$Output = \text{Attention}(Q, K, V) \cdot R_{m}^{-1}$$

。同时,模型通过 c4a(步长为 4,将 8 个 token 压缩为 1 个)和 c128a(步长为 128,将 128 个 token 压缩为 1 个)两种方式对 KV Cache 进行跨 token 压缩,并配合大小为 128 的短滑动窗口保留局部未压缩信息,最后使用稀疏注意力仅与 top-k 的压缩 token 计算注意力。针对这一复杂结构,vLLM 在内存管理上设计了三个关键部件:首先,强制采用单一逻辑块大小,所有压缩层均以 256 个原生 token 位置为一个逻辑块,屏蔽了底层压缩率的差异,使得调度和前缀缓存可以使用统一单位;其次,将压缩器的残差状态(8 个或 128 个 token 的局部状态)直接抽象为滑动窗口注意力状态,复用现有的混合 KV Cache 管理器,从而无缝接入前缀缓存和分离式 Prefill 架构,避免了引入额外的状态转移路径;最后,通过精心设计块大小、压缩率和单条目大小的乘积,将原本五花八门的缓存页面统一收敛到大、中、小三个页面大小桶中,彻底消除了跨池的内存碎片。在计算层面,vLLM 引入了深度算子融合与多流并行。通过将压缩、RMSNorm、RoPE 和缓存插入合并为一个算子(针对索引器和主注意力保持独立内核),将逆 RoPE 与 fp8 量化合并,以及利用静态 warpID 调度水平融合 Q 归一化与 KV 插入,大幅减少了显存往返。同时,利用 CUDA 多流技术,将索引器计算、主注意力 KV 压缩和滑动窗口 token 插入这三个独立分支在不同的流上重叠执行,进一步掩盖了延迟。

效果如何
实验基于 1.6T 参数的 DeepSeek-V4-Pro(运行于 8xB200 或 8xB300)和 285B 参数的 DeepSeek-V4-Flash(运行于 4xB200 或 4xB300)展开,测试上下文长度达到 100 万 tokens。对比基线为代表上一代架构的 61 层 DeepSeek V3.2 模型。在量化结果上,使用 bf16 精度时,DeepSeek V4 在 100 万上下文下每条序列仅需 9.62 GiB 的 KV Cache,比 V3.2 预估的 83.9 GiB 缩小了 8.7 倍;若在实际部署中进一步开启 fp4 索引器缓存和 fp8 注意力缓存,显存占用可在此基础上再降低约 2 倍。在算子性能上,各项内核融合技术分别带来了 1.4 至 3 倍、2 至 3 倍以及 10 至 20 倍的局部速度提升;多流重叠执行则在小 batch size 场景下使端到端延迟降低了 5% 到 6%。该方案的局限在于其异构缓存栈的内在复杂性极高,目前主要针对 NVIDIA Hopper 和 Blackwell 架构进行了深度优化,且模型自带的 fp4 MoE 权重仍需要框架层面的特殊处理,针对 MegaMoE 和 Paged prefill 的内核优化仍在进行中。

一、主要贡献

vLLM 现已全面支持 DeepSeek V4 系列模型,包括拥有 1.6 万亿参数的 DeepSeek-V4-Pro 和 2850 亿参数的 DeepSeek-V4-Flash。这些模型引入了一种专为处理高达 100 万 Token 上下文任务而设计的高效长上下文注意力机制。

长上下文推理主要面临两大挑战:一是 KV Cache 内存随上下文长度线性增长,尽管 DeepSeek 风格的模型使用了多头潜在注意力机制(Multi-head Latent Attention, MLA),但在 GPU 内存有限的情况下,扩展到 100 万 Token 仍然极为困难;二是长上下文的注意力计算成本极其高昂,即使采用了 DeepSeek 稀疏注意力(DeepSeek Sparse Attention, DSA)等技术,计算依然是显著的瓶颈。

本文的核心贡献在于深入解析了 DeepSeek V4 旨在压缩 KV Cache 并降低注意力计算时间的新型注意力架构设计,并详细阐述了 vLLM 团队在实现该模型时克服的系统级优化挑战,包括混合 KV Cache 内存管理、内核融合(Kernel Fusion)以及计算流并行调度等技术细节。

二、背景知识与设计原则

为了应对长上下文推理中的内存和计算挑战,DeepSeek 团队设计了一种全新的注意力机制,其核心设计原则包含以下四个方面:

共享键值向量(Key and Value Vectors)
为了实现 2 倍的内存节省,模型共享了键(Key)和值(Value)向量。为了保证计算的正确性,对注意力输出应用了逆旋转位置编码(Inverse RoPE)操作。

跨多 Token 压缩 KV Cache
该机制能够实现 4 倍到 128 倍的内存节省。在 DeepSeek V4 中,存在两种压缩方式:

  • c4a:将 KV Cache 压缩约 1/4。一个压缩后的 Token 是 8 个未压缩 Token 的加权和,其步长(Stride)为 4。
  • c128a:将 KV Cache 压缩约 1/128。一个压缩后的 Token 是 128 个未压缩 Token 的加权和,其步长(Stride)为 128。

采用 DeepSeek 稀疏注意力(DeepSeek Sparse Attention)
为了限制注意力计算的成本,即使在使用 c4a 注意力压缩 KV Cache 后,一个 100 万 Token 的序列仍然包含 25 万个压缩 Token。为了加速计算,模型使用了 DeepSeek 稀疏注意力机制【1,DeepSeek Sparse Attention + 2025 + arXiv + http://arxiv.org/abs/2512.02556】,使得查询(Query)只关注 前 $k$ 个压缩 Token。

保留局部性的短滑动窗口(Short Sliding Window)
DeepSeek V4 使用了一个大小为 128 的滑动窗口来捕获局部信息。该窗口直接在未压缩的 Token 上运行,从而确保查询 Token 在到达压缩边界之前,能够充分关注到局部的细粒度信息。

以下是 c4a 注意力处理 13 个 Token 的过程演示。
c4a 注意力机制动画

这种高效的注意力设计带来了巨大的 KV Cache 节省。在使用 bf16 格式的 KV Cache 时,DeepSeek V4 在 100 万上下文中每个序列仅占用 9.62 GiB 的 KV Cache。这比 61 层的 DeepSeek V3.2 风格模型估计所需的 83.9 GiB 小了约 8.7 倍。在实际应用中,vLLM 对索引器缓存(Indexer Cache)使用 fp4,对注意力缓存使用 fp8,这使得 KV Cache 的大小相比 bf16 的预估值进一步减少了约 2 倍。

DeepSeek V3.2 与 DeepSeek V4 的每层 KV 状态对比
DeepSeek V3.2 与 DeepSeek V4 的每层 KV 状态对比

三、方法细节

尽管模型在结构上实现了大幅节省,但该注意力机制本身具有内在的复杂性。在 vLLM 中高效地实现这些节省是一个系统工程问题,面临着多项实现挑战:

  • 与 DeepSeek V3.2 模型类似,注意力内核在 Prefill(预填充)阶段使用 bfloat16 格式的 KV Cache,而在 Decode(解码)阶段部分使用基于 Token 的 fp8 格式。
  • 模型混合使用了 c4a 和 c128a 注意力,且某些注意力层纯粹使用滑动窗口来获取局部信息而不进行压缩。这种异构的注意力类型使得 KV Cache 的管理变得极其复杂。
  • 在对多个序列进行批处理(Batching)时,它们在 KV Cache 压缩边界上的状态可能各不相同。
  • 模型原生附带了 fp4 格式的 MoE 权重,这在 vLLM 中需要特殊处理(注:本文未涵盖流形约束超连接【2,Manifold-Constrained Hyper-Connections + 2025 + arXiv + http://arxiv.org/abs/2512.24880】等架构更改) 。

vLLM 通过在内存管理和内核效率两个方面的优化来解决上述挑战。

保持 KV Cache 内存紧凑(Keeping the KV Cache Memory Packed)

vLLM 的 KV Cache 内存分配器必须在 GPU 内存中紧密打包多种类型的 KV 状态,同时还要兼容前缀缓存(Prefix Caching)、Prefill/Decode 分离调度、CUDA Graphs 以及 vLLM 服务路径的其余部分。以下三个设计选择确保了这一过程的可控性:

(1)单一逻辑块大小(A single logical block size)
不同的层以不同的比例进行压缩(c4a 为 1/4,c128a 为 1/128,SWA 为 1/1)。一种直观的设计是围绕“压缩后的条目数”来为每一层设定块大小,但这会导致每一层都有自己的页面布局,分配器必须分别对它们进行推理。
相反,vLLM 将每个压缩层的逻辑块固定为 256 个原生 Token 位置。因此,一个 c4a 物理块包含 256 / 4 = 64 个压缩条目,而一个 c128a 物理块包含 256 / 128 = 2 个条目。分配一个块始终意味着保留请求上下文接下来的 256 个原生位置,而不管它属于哪一层。槽位映射(Slot mapping)、调度器记账和前缀命中检测都可以使用这个统一的单元,而无需根据 compress_ratio 进行分支判断。

(2)将压缩器状态作为滑动窗口处理(Compressor state as a sliding window)
每个压缩器层还为每个请求维护一个较小的滚动残差(Rolling residual):C4 为 8 个 Token 的(重叠)部分状态,C128 为 128 个 Token 的部分状态。最初的自然想法是将其保存在每个请求的侧边缓冲区(Side buffer)中,但这在与整个服务栈交互时会变得极其棘手(例如前缀缓存需要对其进行快照和恢复,分离预填充需要单独的传输路径)。
vLLM 避免了这种做法,而是将压缩器状态视为滑动窗口 KV(Sliding-window KV)。运行时不变量是相同的:每个请求大小固定,随着解码的进行而推进,窗口外的状态要么被丢弃,要么通过缓存处理。因此,vLLM 将压缩器状态注册在滑动窗口 KV Cache 规范下,设定 sliding_window = coff * compress_ratio(C4 为 8,C128 为 128),并将其放入与 SWA 风格相同的块中,由同一个混合 KV Cache 管理器管理。
这使得多个服务功能可以复用相同的抽象:

  • 前缀缓存(Prefix caching) 复用了常规的块语义。缓存命中落在 KV Cache 块边界(即上述的 256 个位置单元)上,该边界处的压缩器状态已经是正确的交接点。
  • 分离预填充(Disaggregated prefill) 将压缩器状态视为 SWA 状态。仅传输窗口内的块,既保留了传输大小的节省,又没有引入单独的特定于残差的传输路径。
  • CUDA Graphs 和 MTP 遵循与 SWA 相同的集成模式,同时保留了特定于压缩器状态的元数据和实现细节。

(3)统一页面大小(Unifying page sizes)
上述两个选择仍然不够。一个 C4 索引器块、一个 c128a KV 块和一个 c4a 压缩器状态块的页面大小(每个块的字节数)仍然不同。如果每种缓存都有自己的块池,会导致跨池碎片化。
由于每种缓存的页面大小是 block_size * compress_ratio * per_entry_size 的乘积,且这三个因子都在控制之下,vLLM 通过精心选择,将不同种类的缓存折叠成少量的页面大小桶(Page-size buckets),每个桶由一个共享的块池支持。
在具体实现中,整个五路缓存栈被适配到三种页面大小中。每个池在加载时进行一次大小调整,分配变成了桶查找操作。没有运行时重新分区,没有每种类型的单独记账,也没有缓存种类之间的碎片化:

  • 最大桶(Largest bucket):c4a 主 KV、SWA KV、c4a 压缩器状态、c128a 压缩器状态。
  • 中间桶(Middle bucket):C4 索引器 KV、C4 索引器压缩器状态。
  • 最小桶(Smallest bucket):c128a 主 KV。

保持 GPU 满载(Keeping the GPU Busy)

内存布局只是运行时优化的一半;另一半是保持 GPU 计算的饱和。vLLM 集成了 FlashMLA 和 FlashInfer 提供优化的注意力和 MoE 内核。但该模型需要许多小型的、主要是内存受限的内核。必须避免额外的启动和 HBM(高带宽内存)往返,否则会拖慢整个解码路径。

c4a 解码路径:带有内核融合(彩色轮廓)和多流分区(默认流 = 蓝色带,索引器流 = 琥珀色带)的算子图
c4a 解码路径:带有内核融合(彩色轮廓)和多流分区(默认流 = 蓝色带,索引器流 = 琥珀色带)的算子图

(1)内核融合(Kernel Fusion)
vLLM 部署了三种融合来减少内存往返(在图中表现为算子组周围的彩色轮廓):

  • 压缩器 + RMSNorm + RoPE + 缓存插入(Compressor + RMSNorm + RoPE + cache insertion):压缩后,压缩的 K 立即经过 RMSNorm、RoPE,并插入到后续注意力的 KV Cache 中(主注意力或索引器)。由于这些阶段几乎完全是逐元素(Elementwise)的,vLLM 将它们融合为一个内核。索引器 K 缓存和主注意力 K 缓存保留了独立的内核,以便针对每个头维度调整并行化策略。整体上相比未融合基线实现了约 1.4 到 3 倍的加速。
  • 逆 RoPE + fp8 量化(Inverse RoPE + fp8 quant):在主注意力之后,输出经过逆 RoPE,然后进入用于 o_lora 投影的 fp8 批量矩阵乘法。将这两者融合避免了背靠背的 HBM 往返,提高了算术强度,相比未融合版本实现了约 2 到 3 倍的加速。
  • 融合 Q 归一化 + KV RoPE + K 插入(Fused Q norm + KV RoPE + K insert):在主注意力之前,需要为压缩路径和滑动窗口路径插入 KV Cache。压缩路径已被第一个融合覆盖,剩下的工作是对查询(Queries)和未压缩的 SWA 键(Keys)进行逐元素处理。vLLM 使用静态 warpID 调度将这些工作水平融合到一个内核中:每个 Warp 独立处理一个 Q 头或一个 K 头,因此不需要跨 Warp 通信。这比朴素的未融合内核带来了 10 到 20 倍的加速。
    此外,vLLM 还复用了 DeepSeek V3.2 工作中的融合,包括 Q RoPE + 量化 + 权重乘法,以及注意力开始时 QK 投影后 QK 归一化的水平融合。

(2)多流调度(Multi-stream)
主注意力之前的操作具有高度的并行性,可分为三个部分:索引器计算、主注意力 KV 压缩和滑动窗口 Token 插入。在初始投影之后,这些分支几乎是独立的,因此 vLLM 在多个 CUDA 流之间重叠执行它们(图中蓝色带标记默认流,琥珀色带标记索引器流):

  • 对于 c128a 层(没有索引器),将主 KV 压缩与 SWA Token 插入并行运行。
  • 对于 c4a 层,将完整的索引器流水线在其自身的流上运行,同时与主 KV 压缩和 SWA Token 插入并行(后两者彼此之间保持串行)。
    通过这些重叠,在低批处理大小下观察到端到端延迟降低了 5-6%。此外,解码路径上使用了 CUDA Graphs 来减少启动开销。

四、实验环境

  • 模型与规模:DeepSeek-V4-Pro(1.6 万亿参数)和 DeepSeek-V4-Flash(2850 亿参数),均支持高达 100 万 Token 的上下文。
  • 硬件配置:

    • Pro 模型推荐单节点部署配置:8x B200 或 8x B300 GPU。
    • Flash 模型推荐单节点部署配置:4x B200 或 4x B300 GPU。
  • 软件与依赖配置:

    • 运行环境:Docker 镜像 vllm/vllm-openai:deepseekv4-cu130。
    • 配置参数:开启 fp8 KV Cache (--kv-cache-dtype fp8)、fp4 索引器缓存 (--attention_config.use_fp4_indexer_cache=True)、块大小为 256 (--block-size 256)、启用专家并行 (--enable-expert-parallel)、开启 CUDA 图全模式 ("cudagraph_mode":"FULL_AND_PIECEWISE")。

Pro 模型启动代码示例:

docker run --gpus all \
  --ipc=host -p 8000:8000 \
  -v ~/.cache/huggingface:/root/.cache/huggingface \
  vllm/vllm-openai:deepseekv4-cu130 deepseek-ai/DeepSeek-V4-Pro \
  --trust-remote-code \
  --kv-cache-dtype fp8 \
  --block-size 256 \
  --enable-expert-parallel \
  --data-parallel-size 8 \
  --compilation-config '{"cudagraph_mode":"FULL_AND_PIECEWISE", "custom_ops":["all"]}' \
  --attention_config.use_fp4_indexer_cache=True \
  --tokenizer-mode deepseek_v4 \
  --tool-call-parser deepseek_v4 \
  --enable-auto-tool-choice \
  --reasoning-parser deepseek_v4

五、实验结果

  • KV Cache 内存节省测试:在 100 万 Token 上下文下,DeepSeek V4 使用 bf16 格式的 KV Cache 每序列仅占用 9.62 GiB,相比 61 层 DeepSeek V3.2 风格模型的 83.9 GiB 估计值,内存消耗减小了约 8.7 倍。结合 fp4 索引器和 fp8 注意力缓存,内存占用进一步缩小了约 2 倍。
  • 内核融合加速效果:

    • “压缩器 + RMSNorm + RoPE + 缓存插入”融合内核相比未融合基线实现了 1.4 到 3 倍的加速。
    • “逆 RoPE + fp8 量化”融合内核实现了 2 到 3 倍的加速。
    • “融合 Q 归一化 + KV RoPE + K 插入”内核实现了 10 到 20 倍的加速。
  • 多流并行调度效果:在低批处理大小(Batch sizes)下,通过分离 CUDA 流重叠执行计算,端到端延迟降低了 5-6%。

六、结论

vLLM 成功实现了对 DeepSeek V4 复杂且高效的长上下文注意力机制的支持。通过创新的滑动窗口压缩器状态管理、统一的内存块分配以及深度的算子融合与多流并行,有效解决了极长上下文下的内存墙与计算墙问题。未来计划的工作包括开发 DeepGEMM MegaMoE 内核和 Paged prefill 内核。此外,借助 vLLM 的可扩展插件系统,硬件供应商(如支持 Ascend 和 MLU 的插件)正在独立添加对该模型的支持。

七、附录

DeepSeek V4 注意力机制背后的数学原理

当共享键(Key)和值(Value)时为什么需要逆 RoPE(Inverse RoPE)
给定位置 $m$ 处的查询 Token,应用 RoPE【3,RoPE + 2021 + arXiv + http://arxiv.org/abs/2104.09864】后的查询表示 为 $q_m = R_m q$,其中 $R_m$ 是由位置 $m$ 参数化的旋转矩阵。旋转矩阵的基本性质包括:$R_m^T R_m = I$(正交矩阵)且 $R_m R_n = R_{m+n}$。
给定位置 $n$ 处的一组键 Token,应用 RoPE 后的键表示为 $k_n = R_n k$。
通常不对值向量应用 RoPE,值表示简写为 $v_n$。
注意力输出为(为简便省略缩放因子):
$o_m = \sum \text{softmax}(q_m^T k_n) v_n$
注意力输出的一个良好性质是平移不变性。依赖于位置的因子 $q_m^T k_n$ 仅取决于查询和键之间的相对位置。
如果共享键和值向量(即 $v_n = k_n = R_n k$),注意力输出将变为:
$o_m = \sum \text{softmax}(q_m^T k_n) R_n k$
此时,输出通过旋转矩阵 $R_n$ 直接携带了绝对位置信息。为了修复这个问题,对注意力输出应用逆 RoPE 操作:
$R_m^{-1} o_m = \sum \text{softmax}(q_m^T k_n) R_m^{-1} R_n k = \sum \text{softmax}(q_m^T k_n) R_{n-m} k$
这样,输出仅通过旋转矩阵 $R_{n-m}$ 携带相对位置信息,从而恢复了平移不变性(类似讨论见【4,Su Jianlin Blog + https://kexue.fm/archives/10862】) 。

实现细节:确切的位置范围与因果关系条件
在处理压缩的 KV Cache 时必须谨慎。对于每个压缩索引 $i$,首先组合固定的原始 Token 局部组,然后使用压缩 Token 的锚点位置应用一次 RoPE,最后将其存入 KV Cache。

  • 对于 c4a,第 $i$ 个压缩 Token 是位置范围 $[4i-4, 4i+3]$ 内 Token 的加权和($i$ 从 0 开始,负索引视为值 0)。应用 RoPE 时该压缩 Token 的位置为 $4i+3$。
  • 对于 c128a,第 $i$ 个压缩 Token 是位置范围 $[128i, 128i+127]$ 内 Token 的加权和($i$ 从 0 开始)。应用 RoPE 时该压缩 Token 的位置为 $128i+127$。
    关于因果关系,必须确保位置 $m$ 的查询 Token 只能关注位置范围 $\le m$ 的 Token 产生的信息。这意味着对于位置 $m$ 的查询和 KV Cache 中第 $i$ 个压缩 Token,必须满足 $4i+3 \le m$(对于 c4a)或 $128i+127 \le m$(对于 c128a)。

实现细节:c4a 和 c128a 中 k 的确切值
在 DeepSeek V4 的 c4a 注意力中,$k$ 的默认值为 512;在 c128a 注意力中,$k$ 的默认值为 8192(相比之下,DeepSeek V3.2 中 $k$ 的默认值为 2048)。
c128a 注意力具有更大的压缩比。在 100 万 Token 上下文中,它最多只有 8000 个压缩 Token。对于注意力计算而言,8000 个 Token 计算量很小,因此可以直接对 c128a 的压缩 Token 使用全注意力。在实现上,仍然可以将 c128a 注意力框架化为 Top-$k$ 值为 8192 的稀疏注意力问题。

实现细节:为什么需要短滑动窗口
使用 c128a 时,位置 $m$($0 \le m < 127$)的查询 Token 无法关注 KV Cache 中的任何压缩 Token,因为第一个压缩 Token 包含位置 0 到 127 的信息,而受限于因果关系,该查询 Token 不能关注位置 $m$ 之后的信息。借助短滑动窗口,查询 Token 可以关注位置范围 $[m-127, m]$ 内的未压缩 Token,从而仍然能够访问局部信息。

估算 8.7 倍内存节省背后的算术计算
针对 100 万上下文序列的推算:

  • DeepSeek V3.2(使用 bf16 KV Cache):

    • 每层每个 Token 的 MLA 缓存:$512 \times 2 = 1024$ 字节。
    • 每层每个 Token 的索引器缓存:$64 \times 2 = 128$ 字节。
    • 每层每个 Token 的总缓存状态:$1152$ 字节。
    • 在 1,048,576 个 Token 时:每层 $1.125$ GiB。
    • 61 层总计:约 $83.9$ GiB。
  • DeepSeek V4(61 层,使用 bf16 KV Cache):

    • 每个共享 KV 缓存条目存储 $512 \times 2 = 1024$ 字节。
    • 每个 c4a 索引器缓存条目存储 $64 \times 2 = 128$ 字节。
    • c4a 层:共享 KV 缓存 $(1024 / 4) \times 1M \approx 256$ MiB,加上索引器缓存 $(128 / 4) \times 1M \approx 32$ MiB,总计约 $288$ MiB。
    • c128a 层:$(1024 / 128) \times 1M \approx 8$ MiB。
    • 30 个 c4a 层和 31 个 c128a 层总计:约 $9.62$ GiB。