随着大语言模型规模不断增长,本地部署大模型时遇到的主要问题,已经不只是 GPU 算力是否足够,而是模型权重能不能放进显存,以及 CPU 和 GPU 之间如何合理分配这些权重。

DeepSeek-V4 这类大规模 MoE 模型就是一个很典型的例子。模型整体参数规模很大,即使使用一张拥有 96GB 显存的 RTX PRO 6000,也很难简单地把完整模型全部加载到 GPU 中。但 MoE 模型与传统 Dense 模型不同:在一次前向计算中,并不是所有 Expert 都会同时参与计算,而是由 Router 根据当前 token 选择其中一部分 Expert。这样的稀疏激活特性,为单卡部署超大模型提供了另一种可能——Expert Offload。

Expert Offload 的基本思路并不复杂:把 Attention、KV Cache 以及部分高频或计算关键的权重保留在 GPU 中,同时将大量 MoE Expert 权重放在 CPU 内存中,通过 CPU 和 GPU 的协同完成推理。这样做虽然会牺牲一定的推理速度,但可以显著降低对 GPU 显存容量的要求,使原本无法完整放入显存的大型 MoE 模型能够在单张 GPU 上运行。

目前开源社区已经有多种实现 CPU/GPU 混合推理的方案。其中,llama.cpp 依托 GGUF、量化以及成熟的 CPU/GPU 混合推理能力,提供了一条相对简单、容易复现的本地部署路线;而 KTransformers / KT-Kernel 则更加关注大型 MoE 模型的异构推理,通过将不同 Expert 分布在 CPU 和 GPU 上运行,并结合 SGLang 等推理框架,可以进一步探索 Expert Offload 场景下的性能优化。

本文将以 RTX PRO 6000 96GB 单卡环境为例,尝试部署 DeepSeek-V4-Flash-0731,并围绕下面几个问题展开:

  • MoE 模型为什么有机会在单张 GPU 上运行?
  • Expert Offload 实际上解决了什么问题?
  • llama.cpp 与 SGLang + KTransformers / KT-Kernel 分别采用了怎样的部署思路?

这篇文章不深入讨论 MoE 的训练方法或者复杂的数学原理,更关注实际部署过程中真正会遇到的问题:模型如何放进机器、CPU 和 GPU 如何分工、不同推理框架有什么区别,以及在有限硬件资源下如何找到一个能够稳定运行且性能相对合理的配置。

如果你手上也有一张大显存消费级或工作站 GPU,或者单纯想了解目前开源社区是如何让这种超大 MoE 模型跑在单机上的,希望本文能够提供一些可复现的参考。

1.DeepSeek-V4 为什么能单卡运行

在讨论 Expert Offload 之前,首先需要回答一个看起来有些矛盾的问题:DeepSeek-V4 的参数规模如此巨大,为什么还有可能在单张 GPU 上运行? 答案主要来自两个方面:一是 DeepSeek-V4 本身采用的 MoE(Mixture of Experts)架构,二是推理时可以利用 CPU 内存和 GPU 显存组成一个更大的异构存储空间。

“能够单卡运行”并不意味着模型的全部参数都被塞进了 GPU,真正需要的是让 GPU 只保存和计算其中更适合 GPU 的部分,其余权重则留在系统内存中。

1.1 从 Dense 到 MoE

传统的 Dense Transformer 中,每一层的 FFN 参数都会参与每个 token 的计算。 可以把它简单理解为:

 

 

 

因此,对于 Dense 模型来说,随着模型参数量增加,每生成一个 token 所需要执行的计算量也会随之增长。MoE 的思路则有所不同。MoE准备多个彼此独立的 Expert,并额外增加一个 Router,用来决定当前 token 应该交给哪些 Expert 处理。

大致可以表示为:

 

 

 

虽然模型中可能存在大量 Expert,但一个 token 在经过某一层时,只会选择其中少

数几个 Expert 参与计算。这也是 MoE 最重要的特点之一:

模型可以拥有非常大的总参数量,但每个 token 实际参与计算的参数量远小于模型总参数量。

DeepSeek-V4 延续了 DeepSeekMoE 架构。以目前发布的两个主要版本为例,DeepSeek-V4-Pro 总参数规模约为 1.6T,但每个 token 激活的参数约为 49B;DeepSeek-V4-Flash 总参数约为 284B,激活参数约为 13B。

也就是说,从“单个 token 需要执行多少计算”这个角度来看:

 

 

 

对于 Deepseek-V4-Flash 来说,虽然模型拥有 284B 级别的总参数,但一次前向过程中真正参与当前 token 计算的只是其中的一部分,这也让超大规模 MoE 模型在更低成本的硬件上仍然具有实际运行推理的可能。

1.2 “算得动”和“装得下”是两个问题

不过,这里有一个特别容易产生的误解:既然一个 token 只激活 49B 参数,是不是只需要准备能够容纳 49B 参数的显存?其实并不是。

“Activated Parameters”主要描述的是一次前向过程中有多少参数实际参与计算,而不是模型总共需要保存多少权重。

举一个例子,假设一个 MoE Layer 有很多 Expert:

Expert 0
Expert 1
Expert 2
Expert 3
Expert 4
Expert 5
...
Expert N

当要处理一个token时,可能只访问:

Expert 3
Expert 7
Expert 12

但下一个 token 激活的参数就有可能不同,有可能会访问:

Expert 1
Expert 9
Expert 15

所以,从计算角度看,我们只需要计算被 Router 选中的 Expert;但是从存储角度看,所有 Expert 的权重仍然需要存在于某个地方。

这就产生了 MoE 本地部署中一个非常关键的区别:

 

 

 

MoE 很大程度上解决了左边的问题:不需要让所有参数参与每个 token 的计算,但它并没有自动解决右边的问题:这些 Expert 权重仍然需要存下来。 对于单卡部署来说,后者往往才是真正的瓶颈。

1.3 为什么 96GB 显存仍然不够?

RTX PRO 6000 拥有 96GB 显存,对于单卡而言已经是非常可观的容量,但面对 DeepSeek-V4 这样的模型时,依然无法简单地将全部模型权重加载到 GPU 中。

而且推理过程中 GPU 显存也不能全部拿来保存模型权重,还需要为其他内容预留空间,例如模型的权重,KV cache,各种runtime buffer,以及其它的临时空间等等。特别是在长上下文推理时,KV Cache 本身也可能占用相当大的显存。所以单卡运行 DeepSeek-V4 真正需要解决的问题其实变成了:既然所有权重无法同时放进 96GB 显存,那么哪些东西应该放 GPU,哪些东西可以放到其他地方?

答案自然就是 CPU 内存。

一台工作站可能只有96GB的GPU显存,但同时拥有:256GB甚至1TB+的内存, 如果能够把两者结合起来,那么模型可以使用的存储空间实际上就从单纯的 96GB VRAM 扩展成96+1TB的存储空间。当然,CPU RAM 的带宽和计算速度都无法与 GPU 显存相比,因此并不能简单地把整个模型全部扔到 CPU 上,否则推理速度会非常差。真正有意思的地方在于 MoE 本身就给了我们一个天然的权重切分单位——Expert。

1.4 MoE 单卡部署

回到一个 Transformer MoE Layer:

 

 

 

Attention 等模块几乎每个 token 都需要执行,而大量 Routed Experts 则具有明显的稀疏访问特征。

因此,自然地把计算频繁、适合 GPU 执行的部分尽可能保留在显存中,同时把大量 Expert 权重放到容量更大的系统内存中。当一个 token 被 Router 分配到某些 Expert 时,再由推理框架决定这些 Expert 应该直接在 GPU 上计算还是在 CPU 上计算,或者通过更加复杂的缓存、预取和 CPU/GPU 协同机制完成计算。

于是,我们实际上并没有让 DeepSeek-V4 “变小”,也没有凭空增加 RTX PRO 6000 的显存,我们只是改变了模型权重的放置方式,这就是单卡部署大型 MoE 模型的基本出发点。

2.DeepSeek-V4 的单卡部署方案

在一台拥有大容量系统内存、但只有单张 GPU 的机器上运行 DeepSeek-V4, 比较值得关注的主要有两条路线:

路线A:

DeepSeek-V4
    ↓
   GGUF
    ↓
llama.cpp
    ↓
CPU + GPU Hybrid Inference

以及路线B:

DeepSeek-V4
    ↓
SGLang
    ↓
KT-Kernel
    ↓
CPU + GPU Expert Offload

虽然两条路线最终都可以利用 CPU RAM 和 GPU VRAM 协同推理,但它们的设计目标、模型格式以及对 MoE 的处理方式并不完全相同。llama.cpp 更关注如何简单、高效地在各种硬件上运行模型;KTransformers / KT-Kernel 更关注如何针对大型 MoE 模型进行 CPU-GPU 异构推理;SGLang 则负责更上层的模型 Serving 和推理调度。

2.1 llama.cpp:成熟的 CPU/GPU Hybrid Inference

llama.cpp 应该是目前本地大模型社区中最常见的推理项目之一。 它是一个以 C/C++ 为核心实现的大模型推理框架,目标之一就是在尽可能少的依赖下,让模型能够运行在不同硬件平台上。除了纯 CPU 推理之外,llama.cpp 还提供 CUDA、Metal、Vulkan、HIP 等多种后端,并支持 CPU + GPU Hybrid Inference,也就是让一部分计算位于 GPU,另一部分保留在 CPU。

因此,它天然适合下面这种情况:

Model Size > GPU VRAM

模型不需要全部塞进 GPU。

一部分权重可以放在 GPU:

GPU VRAM
│
├── Layer
├── Layer
├── Layer
└── ...

其余部分保留在 CPU:

System RAM

│
├── Layer
├── Layer
└── ...

这也是很多本地玩家使用 llama.cpp 运行“显存装不下”的模型时最常见的方式。

llama.cpp 官方也将 CPU+GPU hybrid inference 列为核心能力之一,用于部分加速超过显存容量的模型。使用 llama.cpp 时,经常会遇到另一个关键词:GGUF

###

2.2 GGUF与量化

GGUF 可以理解成 llama.cpp / ggml 生态中使用的一种模型文件格式。 模型经过转换和量化后,最终可能得到类似:

DeepSeek-V4-Flash-Q4_K_M.gguf

这样的文件。

对于本地部署来说,GGUF 的优势之一是量化生态非常成熟。

例如同一个模型可能存在:

Q8
Q6
Q5
Q4
Q3
IQ4
IQ3
...

不同量化版本。

更低的量化精度通常意味着:

Model Size ↓
RAM / VRAM Usage ↓

代价则可能是精度降低,或者是某些kernel的计算效率发生变化 因此 llama.cpp 的一个典型使用思路就是:原始模型量化后转为GGUF格式,然后进行CPU+GPU的异构推理

对于单机开源社区用户来说,这条路线最大的优势就是比较直观。

你通常不需要维护一套复杂的分布式推理系统,只需要准备一个兼容的 GGUF 文件,然后通过:

llama-cli

或者:

llama-server
llama-server

2.3 KTransformers / KT-Kernel:面向大型 MoE 的 CPU-GPU 异构推理

如果说 llama.cpp 的出发点是尽可能让各种模型在各种硬件上跑起来, 那么 KTransformers 更关注的问题可以概括为:如何利用 CPU 和 GPU 各自的优势,高效运行一台设备单独装不下的大型模型。

KTransformers 本身就是一个围绕 CPU-GPU heterogeneous computing,也就是 CPU-GPU 异构计算展开的项目。当前项目的推理能力主要集中在 KT-Kernel 上。

这类设计对于 MoE 尤其合适。 因为 MoE 天然可以把模型拆成Dense部分和expert

于是可以进一步变成:

 

 

 

也就是说,GPU 可以负责:

  • 高吞吐计算;
  • 适合 GPU Kernel 的部分;
  • Hot Experts;
  • Attention 等高频模块。

CPU 则利用更大的系统内存容量:

  • 保存大量 Expert 权重;
  • 执行 CPU Expert computation;
  • 运行 Cold Experts。

因此,KTransformers 并不一定需要像传统 Layer Offload 那样,只按照完整 Transformer Layer 进行 CPU/GPU 切分。

它可以进一步细化到:

Expert Placement。

例如,一个 MoE Layer 有 256 个 Routed Experts,可以配置为:

GPU:
Expert 0 ~ Expert 63

CPU:
Expert 64 ~ Expert 255

当 Router 完成 Expert 选择后:

                   ┌── GPU Expert → GPU Kernel
Token → Router ────┤
                   └── CPU Expert → CPU Kernel

最终再将不同设备上的 Expert 结果合并。

这就是 KTransformers / KT-Kernel 实现 Expert Offload 的核心思路。

KT-Kernel 当前的 SGLang 集成文档就明确采用了类似的设计: GPU 运行 “hot experts”,CPU 运行 “cold experts”,从而进行 CPU-GPU heterogeneous inference。

这其实就是我们前面讨论的 Expert Offload 的一个非常直接的工程实现。

2.4 SGLang:负责把模型“服务起来”

讲到这里还有一个很容易产生的疑问:

既然已经有 KT-Kernel 负责 Expert Offload,为什么还需要 SGLang?

因为它们解决的不是完全同一层的问题。

KT-Kernel 更偏向:

Expert Compute
CPU Kernel
GPU Kernel
Expert Placement

而 SGLang 更偏向:

Request
Batching
Scheduling
KV Cache
Model Runtime
API Serving

可以简单画成:

 

 

 

SGLang 本身已经提供了比较完整的模型 Serving 能力,包括模型加载、内存管理、并行策略以及 OpenAI-compatible API 等功能,并且原生 runtime 也包含针对 MoE 的多种执行和 Expert Parallel 参数。

而在 KTransformers 这条路线中,KT-Kernel 可以集成进 SGLang,让下层的 MoE Expert computation 由 KT-Kernel 接管。

需要注意的是,截至本文编写时,KT-Kernel 官方文档要求 SGLang 集成使用 KTransformers 项目提供的 sglang-kt / kvcache-ai fork,而不是直接安装标准的官方 sglang PyPI 包。因此实际复现时,版本和安装来源需要特别记录清楚。

3.Expert Offload 的性能瓶颈

Expert Offload 解决了“模型装不下”的问题,但并不是没有代价。实际性能通常会受到下面几个因素影响。

3.1 CPU 内存带宽

如果大量 Expert 在 CPU 上执行,CPU 必须不断读取这些权重。 此时瓶颈很可能不再是 CPU Core 数量,而是:

System RAM-> Memory Bandwith-> CPU

特别是在大模型推理中,矩阵权重的数据量非常大,因此 DDR5 的通道数量、频率以及 NUMA 拓扑都会影响实际性能。

3.2 CPU 计算能力

如果 Expert 直接在 CPU 上执行:

AVX
AVX2
AVX-512
AMX

以及:

  • CPU 核心数;
  • SIMD 支持;
  • NUMA;
  • 推理 Kernel 的实现; 都会影响 CPU Expert 的速度。这也是KTransformers / KT-Kernel 这类方案会专门针对 CPU Expert computation 做优化的原因。

 

3.3 瓶颈:PCIe 带宽

CPU 与 GPU 在推理过程中不是完全独立并行工作,二者之间依赖 PCIe 总线进行权重参数的传输。以 PCIe 4.0 为例,其理论带宽约为 32 GB/s,PCIe 5.0 则约为 64 GB/s。然而,GPU 的计算速度远高于此传输速率,导致实际推理延迟主要消耗在权重数据的搬运上,而非计算本身——这是典型的“显存/内存带宽受限”(memory‑bound)场景,也是当前大模型推理性能的主要瓶颈之一。

以 DeepSeek‑V4-flash为例,单次推理需激活约 13B 参数。即便不考虑显存容量限制,仅从带宽角度估算:若采用 FP8 精度,权重体积约为 13 GB;

假设使用 Pro 6000 这类 GPU,其显存带宽约为 1.8 TB/s,则权重加载耗时约为 13 / 1800 ≈ 0.0072 秒。因此,单 token 的解码(decode)阶段,理论上限约为 1 / 0.0072 ≈ 139 tokens/s。可见,即便计算资源充足,显存带宽也已构成硬性约束。

这也解释了为何将 MoE 的全部权重置于 CPU 内存、通过 PCIe 逐次传输至 GPU 时,推理吞吐量仅能维持在约 7 tokens/s 的数量级——问题并非 GPU 算力不足,而是数据传输延迟成为主导因素,导致计算单元长期处于等待状态。

3.4 NUMA

双路服务器尤其需要注意 NUMA。 例如本文测试机器使用两颗 Xeon CPU,那么系统内存实际上分布在两个 NUMA Node 上。

理想的数据访问路径是:

CPU 0 → Local Memory
CPU 1 → Local Memory

如果线程频繁访问 Remote NUMA Memory,则可能形成:

CPU 0
  ↓
UPI / Interconnect
  ↓
CPU 1 Memory

增加额外的数据传输开销。

因此:

  • Expert Weight 分配在哪个 NUMA Node;
  • CPU Thread 绑定在哪里;
  • GPU 更靠近哪颗 CPU;
  • 是否使用 numactl --interleave=all

都会影响实际 Decode 性能。

后面实际启动模型时,我也会使用 numactl 控制内存分配策略。

 

4.实际部署部分

本文使用 KTransformers v0.6.4,在服务器上仅启用一张 RTX PRO 6000。 测试环境:

首先设置相关环境变量:

export SGLANG_DSV4_MODE=2604
export SGLANG_DSV4_2604_SUBMODE=2604B
export FLASHINFER_CUDA_ARCH_LIST=12.0a
export TORCH_CUDA_ARCH_LIST="12.0+PTX"
export CUDA_VISIBLE_DEVICES=1

其中:

CUDA_VISIBLE_DEVICES=1

表示只让当前进程看到服务器中的第二张 GPU。

然后进入 KTransformers 环境:

cd /root/ktransformers
source .venv/bin/activate

启动命令如下:

numactl --interleave=all \
python -m sglang.launch_server \
    --host 0.0.0.0 \
    --port 14000 \
    --model /root/code/modelscope/deepseek-v4-flash-0731 \
    --served-model-name deepseek-v4-flash-0731-MXFP4 \
    --kt-weight-path /root/code/modelscope/deepseek-v4-flash-0731 \
    --kt-method MXFP4 \
    --kt-num-gpu-experts 1 \
    --kt-cpuinfer 64 \
    --kt-threadpool-count 2 \
    --kt-gpu-prefill-token-threshold 4096 \
    --kt-enable-dynamic-expert-update \
    --kv-cache-dtype fp8_e4m3 \
    --tensor-parallel-size 1 \
    --context-length 32768 \
    --attention-backend compressed \
    --sampling-backend flashinfer \
    --chunked-prefill-size 16384 \
    --max-running-requests 1 \
    --watchdog-timeout 1200 \
    --disable-shared-experts-fusion \
    --trust-remote-code \
    --cuda-graph-bs 1 \
    --cuda-graph-max-bs 1 \
    --disable-radix-cache \
    --skip-server-warmup \
    --tool-call-parser deepseekv4 \
    --reasoning-parser deepseek-v4

几个关键参数

这里重点解释几个后续调优中非常重要的参数。

--kt-num-gpu-experts

--kt-num-gpu-experts 1

表示每个 MoE Layer 中常驻 GPU 的 Routed Expert 数量。

例如:

--kt-num-gpu-experts 1

意味着每层只有少量 Expert 常驻 GPU,大部分 Expert 保留在 CPU。

如果设置得更高,例如:

32
64
80
96

则会有更多 Expert 常驻 GPU。

通常意味着:

GPU Experts ↑
      ↓
CPU Expert Workload ↓
      ↓
Decode Performance ↑

但同时:

VRAM Usage ↑

因此这个参数本质上是在:

GPU 显存占用与 Decode 性能之间做交换。

--kt-cpuinfer

--kt-cpuinfer 64

用于配置 CPU Expert 推理相关线程资源。

在 Expert 大量 Offload 到 CPU 的情况下,CPU Expert Kernel 的线程配置会直接影响最终推理速度。

不过线程并不是越多越好。

对于双路 NUMA 服务器,还需要同时考虑:

  • CPU Core 数量;
  • Hyper-Threading;
  • Memory Bandwidth;
  • NUMA;
  • Thread Pool;
  • CPU Cache。

因此实际配置仍然需要 Benchmark。

--kt-threadpool-count

--kt-threadpool-count 2

用于配置 CPU Expert 执行相关 Thread Pool。

在双路 CPU 环境中,多个 Thread Pool 可以用于提高 CPU Expert 并行能力,但具体效果仍然会受到 NUMA 和 Memory Bandwidth 限制。

--kt-gpu-prefill-token-threshold

--kt-gpu-prefill-token-threshold 4096

这是一个非常重要的 Prefill 参数。

它决定当 Prefill Token 数达到一定规模后,是否切换到更积极的 GPU Prefill 路径。

可以简单理解为:

较短 Prompt
    ↓
CPU/GPU Hybrid Prefill
较长 Prompt
    ↓
达到 Threshold
    ↓
更积极利用 GPU 完成 Prefill

因此这个参数更多影响:

TTFT 和长 Prompt Prefill 性能。

--kt-num-gpu-experts 则更多影响:

Decode 阶段。

后续实际调优时,这两个参数最好分开理解,而不是简单地认为:

GPU Expert 越多
=
所有阶段都越快

--kv-cache-dtype fp8_e4m3

--kv-cache-dtype fp8_e4m3

这里使用 FP8 KV Cache,主要目的是降低长上下文场景下 KV Cache 的显存占用。

对于单卡 96GB 来说,这一点非常重要。

因为显存不仅需要存放模型和 GPU Experts,还需要留给:

KV Cache
+
Prefill Workspace
+
Runtime Buffer

如果 KV Cache 占用过大,就会直接压缩 GPU Expert 和运行时空间。

--context-length 32768

--context-length 32768

本文暂时将最大 Context Length 设置为 32K。

单卡部署中,Context Length 并不是越大越好。

因为:

Context Length ↑
      ↓
KV Cache Budget ↑
      ↓
Available VRAM ↓

当目标是提高 Decode 性能时,适当降低 Context Length,往往可以释放更多显存给 GPU-resident Experts。

--chunked-prefill-size

--chunked-prefill-size 16384

这里使用 16K Chunked Prefill。

Chunked Prefill 可以避免一次 Prefill 占用过大的瞬时资源,同时也能够让调度器更灵活地处理长 Prompt。

但 Chunk Size 越大,单次 Prefill 的 Activation 和 Workspace 压力通常也会更高。

因此在单卡显存非常紧张时,这也是一个需要重点调整的参数。

##

单卡 MoE 推理真正的资源分配问题

从前面的分析可以看到,单张 96GB GPU 的显存实际上存在几个竞争者。

可以简单划分为:

96GB VRAM
│
├── Dense / Attention Weight
│
├── GPU-resident Experts
│
├── KV Cache
│
├── Prefill Workspace
│
├── CUDA Graph
│
└── Runtime Buffer

因此:

GPU Experts ↑

通常意味着:

可用 KV Cache ↓
Prefill Workspace ↓

而:

Context Length ↑

意味着:

KV Cache ↑
可用于 Expert 的显存 ↓

同样,如果为了获得更快的长 Prompt Prefill 而预留更多 GPU Workspace,就必须减少其他常驻显存占用。

因此,单卡 96GB 的真正问题不是:

“到底设置多少个 GPU Experts 最快?”

而应该是:

“我的工作负载更看重什么?”

如果更在意长 Prompt 的 TTFT:

Prefill Workspace
优先级更高

如果更在意持续生成速度:

GPU-resident Experts
优先级更高

如果更在意超长上下文:

KV Cache
优先级更高

而这三者往往无法同时最大化。

5.小结

到这里,我们已经可以得到几个比较重要的结论。

首先,DeepSeek-V4 之所以有机会在单卡上运行,并不是因为整个模型能够放进 96GB 显存,而是因为 MoE 提供了天然的 Expert 级切分能力。

模型可以通过:GPU VRAM + System RAM共同保存权重。

其次,MoE 的稀疏激活解决的是每个 token 实际计算多少参数,但并没有解决完整模型权重存在哪里。这正是 Expert Offload 要解决的问题。

第三,llama.cpp 与 KTransformers 都能够进行 CPU/GPU 混合推理,但两者的设计思路并不完全相同。

llama.cpp 更偏向成熟、简单的通用 Hybrid Inference,并拥有完善的 GGUF 与量化生态。

而 KTransformers / KT-Kernel 更加关注大型 MoE 的异构执行,可以进一步将 Expert 分布到 CPU 与 GPU 上,由不同设备直接承担 Expert computation。

SGLang 则位于更上层,负责:

Request
Scheduling
Batching
KV Cache
Prefill
Decode
API Serving

最后,Expert Offload 虽然解决了“模型装不下”的问题,但同时也把性能瓶颈从单一 GPU 扩展到了整个异构系统:

CPU DRAM
+
CPU Kernel
+
NUMA
+
PCIe
+
GPU Memory
+
CPU/GPU Synchronization

因此,在单卡 96GB 环境中真正有效的调优方式,并不是单纯把更多 Expert 塞进 GPU,而是根据具体业务,在:

KV Cache
GPU-resident Experts
Prefill Workspace

之间重新分配有限的显存资源。

后续可以进一步通过实际 Benchmark 分析:

  • --kt-num-gpu-experts 如何影响 Decode;
  • --kt-gpu-prefill-token-threshold 如何影响 Prefill;
  • 为什么增加 GPU Experts 后可能出现 OOM;
  • SGLang 的 Input/Output Throughput 应该如何正确解读;
  • llama.cpp 与 KTransformers 的 Offload 策略为什么会产生不同的 Decode 性能。

这些问题也是单卡运行 DeepSeek-V4 时真正值得进一步分析的部分。

测试数据

两组测试的最终结果如下:

配置 Input Tokens TTFT 有效 Prefill 速度 TPOT Decode 速度
64 GPU Experts / Layer 8192 24.01 s 341.1 tok/s 57.03 ms 17.53 tok/s
1 GPU Expert / Layer 16000 39.81 s 401.9 tok/s 64.08 ms 15.61 tok/s

其中实际阶段性能按照下面的方式计算:

Prefill Speed ≈ Input Tokens / TTFT
Decode Speed  ≈ 1000 / TPOT(ms)

 

Logo

ModelScope旨在打造下一代开源的模型即服务共享平台,为泛AI开发者提供灵活、易用、低成本的一站式模型服务产品,让模型应用更简单!

更多推荐