夜雨聆风学习资料网

ARTICLE · 1167412

Ultra X7 358H 笔记本电脑,共享显存占比从 57% 提到 80%,成功让同一个模型能开 4 倍上下文

Ultra X7 358H 笔记本电脑,共享显存占比从 57% 提到 80%,成功让同一个模型能开 4 倍上下文

在之前文章《Ultra X7 358H 笔记本电脑,本地部署当红炸子鸡 Qwen3.8-27B-Q4,实测生成速度 5.6 tok/s》中,Qwen3.8-27B-Q4 的上下文才 4K,远远不够用。

后来在《Ultra X7 358H 笔记本电脑,寻找本地用于编码的最强大模型,实测 21.0 tok/s,上下文 256K》中,AI 发现我这台笔记本电脑可以提升显存占比,并且能开大得多的上下文,这实在是一个惊喜!

下面是 AI 对实测过程的总结,有兴趣的可以浏览(使用 Deepseek Harness Desktop + Deepseek V4.1 Flash)。

概述

本机把 Intel iGPU 共享显存从 57% 提到 80%,成功让同一个模型能开 4 倍上下文,但几乎没能让更大的模型跑起来。本文用实测数据说明硬件参数、提升方法,以及为什么"显存变大"≠"能跑更大的模型"。

数据来源:本机 2026-10 实测(Windows 11 build 26200 / llama.cpp SYCL / torch 2.9.0+xpu)。

硬件参数(实测)

项目
实测值
说明
CPU
Intel Core Ultra X7 358H
Panther Lake 平台
GPU
Intel Arc B390
(集成显卡,驱动 32.0.101.8509)
没有独立显卡
显存
无独立显存
,与系统内存共享
这是全文的前提
物理内存
31.55 GiB
(33.9 GB)
板载焊接,不可扩容
页面文件
提交上限 38.3 GiB(系统托管,C 盘)
换页会拖垮推理速度
C 盘
300 GB(可用 175 GB)
页面文件所在盘
D 盘
624 GB(可用 545 GB)
模型与工具所在盘
操作系统
Windows 11(build 26200)
推理引擎
llama.cpp 0.5.0-dev,IntelLLVM 2025.3.3 编译的 SYCL 版
用 ggml-sycl.dll 走 GPU

关键点:B390 是集成显卡,它的"显存"并不是一块独立的存储,而是从这 31.55 GiB 系统内存里划出来的一块。所以"显存有多大"和"内存有多大"本质上是同一个池子里的两个额度,而不是两笔资源。

显存是怎么被"提升"的

Intel 驱动用一个注册表项控制显卡最多能提交多少比例的系统内存:

HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager    SystemPartitionCommitLimitPercentage   (REG_DWORD)
值
原状态
改后
十进制
57
80
十六进制
0x390x50
名义上限(31.55 GiB × 比例)
18.0 GiB
25.2 GiB

操作方法(需要管理员 + 重启)

方法 A:双击注册表文件

D:\AI_Tools\igpu-shared-80.reg → 同意 UAC → 重启(回滚用 igpu-shared-restore-57.reg)

方法 B:管理员命令行

reg add "HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager" /v SystemPartitionCommitLimitPercentage /t REG_DWORD /d 80 /f

执行后必须重启才生效。

⚠️ 不要在 80% 以上继续加。85% 时只剩 4.7 GiB 给 Windows,系统会开始换页,日常使用就卡了。这个比例只是额度上限,不是预留——内存仍然是按需占用。

怎么确认真的生效了(两个层次,缺一不可)

只查注册表是不够的,必须做功能验证。

验证 1:注册表值

reg query "HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager" /v SystemPartitionCommitLimitPercentage

应显示 0x50。

验证 2:A/B 对照实验(最终判决)

方法:把注册表改回 57% → 重启 → 用同一模型、同一参数(q8_0 KV、-ngl 99)依次测试 16k / 32k / 64k;再改回 80% → 重启 → 重复同一系列。

上下文
57%(旧额度 18.0 GiB)
80%(新额度 25.2 GiB)
16384
✅ PASS(测试时系统空闲 24.58 GiB)
✅ PASS
32768
❌ FAIL(测试时系统空闲 25.43 GiB)
✅ PASS
65536
❌ FAIL(测试时系统空闲 21.46 GiB)
✅ PASS

失败时报的是明确的设备内存错误,而不是系统内存不足:

level_zero backend failed with error: 39 (UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY)

这条实验排除了所有替代解释:32k 失败时系统还空闲 25.43 GiB——比 80% 下成功加载 64k 时更宽松,所以失败原因不是物理内存不足,而是显卡提交额度被打满。

结论:57% → 80% 的调整,确实是 32k / 64k 能打开的直接原因。扣掉 15.33 GiB 权重后,留给上下文+计算缓冲的余量从约 2.7 GiB 变成约 9.9 GiB。

修正本文早期版本的一处推测:曾推测"改前只能开 4096"。实测证明 57% 下 16k 本来就能开,只有 32k 及以上被挡住——start_qwen38.bat 里的 -c 4096 是保守设置,不是当时的硬限制。

验证 3:阶梯分配测试

用脚本 D:\AI_Tools\unsloth\scripts\check_xpu_memory.py 逐块分配显存,一直分配到失败为止:

改前
改后
torch 上报的设备上限
16.46 GiB
16.46 GiB(没有变化!)
实测能真正分配到
未测到失败点
20.50 GiB
(被我设的系统内存安全阈值拦下,并非分配失败)

这里有个反直觉现象:改完之后,驱动上报给 torch 的上限数字仍然是 16.46 GiB,一点没变,但实际能分配的内存确实超过了它。也就是说:工具看到的额度和实际可用的额度不一致。(对 Unsloth 这类按上报值做显存规划的框架,仍会按旧的 16.46 GiB 保守估计。)

为什么还是装不下更大的模型

真正的约束:物理内存,不是显存额度

内存不是两个池子,是一个池子。把显卡额度从 18 GiB 提到 25.2 GiB,并没有给机器增加一个字节的内存,只是把"谁可以占用"的闸门放宽了。

状态
系统空闲内存
无模型(重启后基线)
25.69 GiB
加载 27B(15.33 GiB 权重)@ 4096 上下文
1.15 GiB
加载 27B @ 16384 上下文
0.56 GiB
加载 Qwen3.6-35B-A3B(15.46 GiB 权重)@ 32768 上下文
0.72 GiB

看第一行和第三行:要塞进 15.33 GiB 的权重,系统实际付出了约 24.5 GiB 的代价(25.69 − 1.15 = 24.54)。多出来的约 9.2 GiB 是加载模型时才会产生的固定开销。

换算成一条经验公式:

系统内存占用 ≈ 模型权重 × 1.6 + 5.8 GiB(Windows 基线)

代入验证:

模型权重
按公式所需
31.55 GiB 能否承受
15.33 GiB
30.3 GiB
✅ 实测通过(余 0.56~1.15 GiB)
15.46 GiB
30.5 GiB
✅ 实测通过(余 0.72 GiB)
16.51 GiB
32.2 GiB
❌ 超出,会换页
20.61 GiB
38.8 GiB
❌ 严重超出

那些"看不见"的开销到底是什么

同一时刻采样,两次得到一致的结果:

各进程工作集合计 : 14.59 GiB系统实际占用     : 30.82 GiB                   ─────────────                    约 16 GiB 在进程之外

这部分内存不属于任何进程的工作集,因此任务管理器里看不到,但它实实在在占着内存:

开销来源
量级
能否压缩
Windows 内核 + 常驻服务
~5.8 GiB
基本不能(已关掉酷狗/腾讯视频/网易云/夸克/OneDrive/MagicClaw 自启)
显卡提交:模型权重
15.33 GiB(固定)
只能换更小的量化
显卡提交:KV cache
随上下文线性增长
已用 q8_0 量化
显卡提交:RS buffer(循环状态)
598.5 MiB 固定
(默认 4 槽位)
已验证可用 -np 1 降到 149.6 MiB
显卡提交:计算缓冲
随上下文增长
靠调小上下文

上下文到底吃掉多少显存(llama.cpp 分配的实测明细)

用 -lv 5 让 llama.cpp 自己打印每个缓冲区的分配量——这比看系统空闲内存可靠得多:

上下文
KV buffer
RS buffer
计算缓冲*
非权重合计
相对 4k
4096
136 MiB
598.5 MiB
150.6 MiB
885 MiB
—
16384
544 MiB
598.5 MiB
208.6 MiB
1351 MiB
+466 MiB
32768
1088 MiB
598.5 MiB
304.6 MiB
1991 MiB
+1106 MiB
65536
2176 MiB
598.5 MiB
496.6 MiB
3271 MiB+2386 MiB

* 计算缓冲 = SYCL compute + Host compute

结论:27B 从 4k 开到 64k,设备侧要多花 2.33 GiB。 其中 KV 占 2.0 GiB(约 34 KiB/token),计算缓冲占 0.35 GiB;RS buffer 是固定的 598.5 MiB,只跟服务槽位数(n_slots = 4)有关,与上下文长度无关。

这份明细也精确解释了 A/B 实验的失败点:

【32k @57%】KV 1088 MiB 分配成功 → RS 598.5 成功 → 计算图分配时炸:            level_zero backend failed with error: 39 (UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY)【64k @57%】KV 2176 MiB 分配成功 → 轮到 RS 时炸:            failed to allocate SYCL0 buffer of size 627572736   ← 正好是 598.5 MiB 的 RS buffer

反推:57% 下留给非权重分配的余量,落在 1351 MiB(16k 成功)与 1991 MiB(32k 失败)之间,即约 1.3~1.9 GiB(名义额度 18.0 GiB 减去权重 15.33 GiB,再扣驱动自身占用)。

直接省下 449 MiB:把服务槽位从 4 降到 1(-np 1)

llama-server 默认开 4 个并行槽位(n_parallel = auto → 4),每个槽位都要自己的一份循环状态。单用户用不到并发,改成 1 个槽位可以立刻省下约 449 MiB,且与上下文长度无关(每档都省):

16k 上下文
默认 -np 4
-np 1
变化
RS buffer
598.50 MiB
149.62 MiB−448.88 MiB
KV buffer
544.00 MiB
544.00 MiB
不变
计算缓冲(SYCL + Host)
208.56 MiB
208.56 MiB
不变
非权重合计1351 MiB902 MiB−449 MiB

换算到 64k:非权重占用从 3271 MiB 降到 2822 MiB。已写入 D:\AI_Tools\llama-server.cmd(第 4 个参数可覆盖,默认 1)。

-np 1 加持下的上下文上限(80% 额度 + q8 KV,27B 实测)

省下的 449 MiB 直接变成了可用的上下文额度。逐档实测("能加载 + 能出词"才算 PASS):

上下文
结果
备注
65536
✅ PASS
非权重占用 2822 MiB
131072
✅ PASS
加载 56s
196608
✅ PASS
加载 46s
212992
✅ PASS
加载 67s ← 实测可用上限
229376
❌ FAIL
UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY
262144
❌ FAIL
failed to allocate compute pp buffers
(把 batch 降到 512 也失败)

模型原生支持 262144(256K),但本机实测到 208K 到顶,差一档。256k 需要约 10.5~11 GiB 的非权重分配,而 80% 额度只留出约 9 GiB。(256k 失败时系统还空闲 25.93 GiB——再次说明卡的是显卡额度,不是内存。)

对比改注册表之前:同一个模型在 57% 下只能到 16k。现在是 208K,13 倍。

两个模型的上下文开销对比(都是 q8 KV + -np 1 + 80% 额度)

日常实际在用的 Qwen3.6-35B-A3B(qwen35moe,权重 15.46 GiB)逐档实测:

上下文
KV buffer
RS buffer
计算缓冲*
非权重合计
4096
42.50 MiB
62.81 MiB
84.56 MiB
190 MiB
32768
340.00 MiB
62.81 MiB
196.56 MiB
599 MiB
65536
680.00 MiB
62.81 MiB
324.56 MiB
1067 MiB
131072
1360.00 MiB
62.81 MiB
580.56 MiB
2003 MiB
196608
2040.00 MiB
62.81 MiB
836.56 MiB
2939 MiB
2621442720.00 MiB
62.81 MiB
1092.56 MiB
3875 MiB

* 计算缓冲 = SYCL compute + Host compute

两个关键结论:

① 35B-A3B 能用满它的原生 256K 上下文(加载仅 46 秒),全部非权重开销才 3.79 GiB;而 27B 在 208K 就到顶了(原生 256k 差一档)。日常用 35B-A3B 就没有这个遗憾。

② 为什么差这么多——看 llama.cpp 打印的这行:

35B-A3B:  KV buffer size = 680.00 MiB (65536 cells, 10 layers, 1/1 seqs)27B:      KV buffer size = 2176.00 MiB (65536 cells, 16 layers, 1/1 seqs)

35B-A3B 的 40 层里只有 10 层有 KV cache,其余 30 层是线性/循环状态(ssm.state_size = 128);27B 的 65 层里有 16 层是全注意力,且每层的 KV 头数更多。结果就是 KV 每 token 便宜 3.2 倍(35B-A3B 约 10.6 KiB/token,27B 约 34 KiB/token),RS buffer 也小 2.4 倍(62.81 vs 149.62 MiB)。

同上下文下的横向对比(128k):

模型
KV
计算缓冲
非权重合计
能否到 256k
Qwen3.8-27B(dense 27B)
4352 MiB
580 MiB
5.2 GiB
❌ 只能到 208k
Qwen3.6-35B-A3B(MoE 3B 激活)
1360 MiB
580 MiB
2.0 GiB
✅ 能用满 256k

所以日常首选 35B-A3B 不只是因为它快 5 倍(23 vs 4.5 tok/s),它的上下文开销也只有 27B 的 40%。

⚠️ 本文早期版本的方法论错误(已修正)

早期版本写过"27B 从 4096 → 16384 只多占 0.6 GiB""35B-A3B 开 32768 只要 0.3 GiB"。那些数字是从系统空闲内存的差值推出来的,属于错误方法:本机每次测试时内存负载都在 95~97%,Windows 会持续压缩内存、回收待机缓存来维持"空闲"数值,因此该指标根本测不出真实增量(三次读数 1.15 / 0.56 / 0.81 GiB 的差异本身就在噪声范围内)。

改用 llama.cpp 自身的 buffer 分配明细(-lv 5)重测后,4k→64k 的真实代价是 2.33 GiB,是早期说法(0.3~0.6 GiB)的4~8 倍。上表中的数字全部来自新方法。

超了会怎样:从 23 tok/s 掉到 1 tok/s 以下

一旦内存不够,超出部分会落到页面文件(C 盘)。而生成每一个 token 都要读取全部活跃权重,只要权重有一部分在磁盘上,每一步都要等磁盘 I/O:

场景
实测速度
权重完全在内存里(Qwen3.6-35B-A3B)
23~24 tok/s
27B dense(同量级权重,架构不同)
4.5 tok/s
权重溢出到页面文件(推算)
< 1 tok/s,且硬盘持续读

本机 C 盘是 SSD,但即便是 SSD,随机读 15 GB 权重也意味着每个 token 要等几百毫秒到数秒。

一个补充:MoE 模型(如 35B-A3B,每 token 只激活约 3B 参数)对这种溢出的耐受度会略好——因为它每次只碰一小部分专家权重,被换出的专家可能不会立刻被用到。但这是"能不能勉强跑"的差别,不是"能不能跑得好"的差别,不建议作为方案依赖。

结论:显存提升到底买到了什么

改前 57%
改后 80%
变化
显卡提交额度(名义)
18.0 GiB
25.2 GiB
+40%
驱动上报给 torch 的额度
16.46 GiB
16.46 GiB
无变化
实测可分配显存
~16 GiB
20.50 GiB
+28%
能加载的模型权重上限
~15.3 GiB
~15.5 GiB几乎没有变化
能开的上下文长度
4096
16384+提升 4 倍

所以这次调优换来的不是"能装更大的模型",而是"同一个模型能开更长的上下文、更大的计算缓冲"。

原因很直白:显存额度的水龙头拧大了,但水池(物理内存 31.55 GiB)没有变大,而池子里还要装 Windows、驱动、SYCL 运行时、KV cache 和计算缓冲。

实操建议

  1. 1. 想跑更大的模型,唯一的硬解法是换内存更大的机器(>48 GiB,最好 64 GiB)。本机内存是板载焊接的,无法加装,这是物理限制,任何软件调优都绕不过去。
  2. 2. 在这台机器上的安全预算:模型权重 ≤ 15.5 GiB。已实测跑通的最佳选择是Qwen3.6-35B-A3B-UD-Q3_K_M.gguf(15.46 GiB,SWE-bench Verified 73.4,23 tok/s)。
  3. 3. 跑模型前关掉浏览器:加载后只剩 0.7 GiB 空闲,一个 Edge 窗口就能把它推入换页。
  4. 4. 上下文按需给,它是要花显存的:27B 从 4k 开到 64k 要多花 2.33 GiB 设备内存(KV 约 34 KiB/token)。日常用 8k~16k 即可,64k 只在真需要啃长文档/长代码库时打开。
  5. 5. 用 -np 1 启动(已设为默认):单用户可省 449 MiB 固定开销,等价于白送约 13k token 的上下文额度。只有确实需要并发请求时才调大第 4 个参数。
  6. 6. 想回滚:双击 D:\AI_Tools\igpu-shared-restore-57.reg 并重启。

附录:本次用到的验证命令

:: 1. 查当前共享显存比例reg query "HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager" /v SystemPartitionCommitLimitPercentage:: 2. 阶梯分配测试,测出实际能分配多少显存(参数1=测试上限GiB,参数2=系统剩余内存安全阈值GiB)D:\AI_Tools\unsloth\run.cmd scripts\check_xpu_memory.py 22 1.2:: 3. A/B 判决测试:在任意共享显存比例下自动测多个上文档位(PASS/FAIL + 出词验证)D:\AI_Tools\unsloth\run.cmd scripts\test_ctx_load.py 16384 32768 65536:: 4. 【推荐】读 llama.cpp 自己报的 buffer 分配明细(比看系统空闲内存可靠)::    会依次用 -lv 5 启动各上下文,抓取 KV / RS / compute buffer 的真实大小D:\AI_Tools\unsloth\run.cmd scripts\probe_buffers.py 4096 16384 32768 65536:: 5. 手动看某个上下文下的分配明细"<llama.cpp>\build\bin\llama-server.exe" -m <模型> -ngl 99 -c 65536 ^    --cache-type-k q8_0 --cache-type-v q8_0 -lv 5 --port 8098::    关注这几行:KV buffer size / RS buffer size / compute buffer size:: 6. 看系统真实内存占用(含进程外的部分)::    进程工作集合计 vs 系统实际占用,两者差额即为驱动/内核占用Get-Process | Measure-Object WS -Sum

附录 B:两个容易踩的方法论坑

  1. 1. 不要用"系统空闲内存"推断显存占用。 本机内存负载常年 95~97%,Windows 会靠压缩和回收待机缓存把"空闲"维持在近似水平,导致增量被吃掉、看起来"几乎不涨"。要看 llama.cpp 的 buffer 明细。
  2. 2. 不要把驱动上报的显存值当成上限。llama-ls-sycl-device 或启动横幅里的数字是get_global_mem_size()/1000000(SYCL 静态属性,十进制 MB),改注册表也不会变;真正的闸门由 SystemPartitionCommitLimitPercentage 控制,两者不是一回事。

本文所有数字均为本机实测值,非估算或引用。

相关学习资料