ARTICLE · 1167412
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)。
硬件参数(实测)
| Intel Core Ultra X7 358H | ||
| Intel Arc B390 | 没有独立显卡 | |
| 无独立显存 | ||
| 31.55 GiB | ||
ggml-sycl.dll 走 GPU |
关键点:B390 是集成显卡,它的"显存"并不是一块独立的存储,而是从这 31.55 GiB 系统内存里划出来的一块。所以"显存有多大"和"内存有多大"本质上是同一个池子里的两个额度,而不是两笔资源。
显存是怎么被"提升"的
Intel 驱动用一个注册表项控制显卡最多能提交多少比例的系统内存:
HKLM\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\MemoryManager SystemPartitionCommitLimitPercentage (REG_DWORD)| 80 | ||
0x39 | 0x50 | |
操作方法(需要管理员 + 重启)
方法 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% → 重启 → 重复同一系列。
失败时报的是明确的设备内存错误,而不是系统内存不足:
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 逐块分配显存,一直分配到失败为止:
| 16.46 GiB(没有变化!) | ||
| 20.50 GiB |
这里有个反直觉现象:改完之后,驱动上报给 torch 的上限数字仍然是 16.46 GiB,一点没变,但实际能分配的内存确实超过了它。也就是说:工具看到的额度和实际可用的额度不一致。(对 Unsloth 这类按上报值做显存规划的框架,仍会按旧的 16.46 GiB 保守估计。)
为什么还是装不下更大的模型
真正的约束:物理内存,不是显存额度
内存不是两个池子,是一个池子。把显卡额度从 18 GiB 提到 25.2 GiB,并没有给机器增加一个字节的内存,只是把"谁可以占用"的闸门放宽了。
| 25.69 GiB | |
| 1.15 GiB | |
| 0.56 GiB | |
| 0.72 GiB |
看第一行和第三行:要塞进 15.33 GiB 的权重,系统实际付出了约 24.5 GiB 的代价(25.69 − 1.15 = 24.54)。多出来的约 9.2 GiB 是加载模型时才会产生的固定开销。
换算成一条经验公式:
系统内存占用 ≈ 模型权重 × 1.6 + 5.8 GiB(Windows 基线)
代入验证:
那些"看不见"的开销到底是什么
同一时刻采样,两次得到一致的结果:
各进程工作集合计 : 14.59 GiB系统实际占用 : 30.82 GiB ───────────── 约 16 GiB 在进程之外这部分内存不属于任何进程的工作集,因此任务管理器里看不到,但它实实在在占着内存:
| 598.5 MiB 固定 | 已验证可用 -np 1 降到 149.6 MiB | |
上下文到底吃掉多少显存(llama.cpp 分配的实测明细)
用 -lv 5 让 llama.cpp 自己打印每个缓冲区的分配量——这比看系统空闲内存可靠得多:
| 非权重合计 | |||||
|---|---|---|---|---|---|
| 885 MiB | |||||
| 1351 MiB | |||||
| 1991 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,且与上下文长度无关(每档都省):
-np 4 | -np 1 | ||
|---|---|---|---|
| RS buffer | 149.62 MiB | −448.88 MiB | |
| 非权重合计 | 1351 MiB | 902 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):
| 212992 | ||
UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY | ||
failed to allocate compute pp buffers |
模型原生支持 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)逐档实测:
| 非权重合计 | ||||
|---|---|---|---|---|
| 190 MiB | ||||
| 599 MiB | ||||
| 1067 MiB | ||||
| 2003 MiB | ||||
| 2939 MiB | ||||
| 262144 | 2720.00 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):
| 5.2 GiB | ||||
| Qwen3.6-35B-A3B(MoE 3B 激活) | 2.0 GiB |
所以日常首选 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:
| 23~24 tok/s | |
本机 C 盘是 SSD,但即便是 SSD,随机读 15 GB 权重也意味着每个 token 要等几百毫秒到数秒。
一个补充:MoE 模型(如 35B-A3B,每 token 只激活约 3B 参数)对这种溢出的耐受度会略好——因为它每次只碰一小部分专家权重,被换出的专家可能不会立刻被用到。但这是"能不能勉强跑"的差别,不是"能不能跑得好"的差别,不建议作为方案依赖。
结论:显存提升到底买到了什么
| 无变化 | |||
| 20.50 GiB | |||
| 能加载的模型权重上限 | ~15.5 GiB | 几乎没有变化 | |
| 能开的上下文长度 | 16384+ | 提升 4 倍 |
所以这次调优换来的不是"能装更大的模型",而是"同一个模型能开更长的上下文、更大的计算缓冲"。
原因很直白:显存额度的水龙头拧大了,但水池(物理内存 31.55 GiB)没有变大,而池子里还要装 Windows、驱动、SYCL 运行时、KV cache 和计算缓冲。
实操建议
1. 想跑更大的模型,唯一的硬解法是换内存更大的机器(>48 GiB,最好 64 GiB)。本机内存是板载焊接的,无法加装,这是物理限制,任何软件调优都绕不过去。 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. 跑模型前关掉浏览器:加载后只剩 0.7 GiB 空闲,一个 Edge 窗口就能把它推入换页。 4. 上下文按需给,它是要花显存的:27B 从 4k 开到 64k 要多花 2.33 GiB 设备内存(KV 约 34 KiB/token)。日常用 8k~16k 即可,64k 只在真需要啃长文档/长代码库时打开。 5. 用 -np 1启动(已设为默认):单用户可省 449 MiB 固定开销,等价于白送约 13k token 的上下文额度。只有确实需要并发请求时才调大第 4 个参数。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. 不要用"系统空闲内存"推断显存占用。 本机内存负载常年 95~97%,Windows 会靠压缩和回收待机缓存把"空闲"维持在近似水平,导致增量被吃掉、看起来"几乎不涨"。要看 llama.cpp 的 buffer 明细。 2. 不要把驱动上报的显存值当成上限。 llama-ls-sycl-device或启动横幅里的数字是get_global_mem_size()/1000000(SYCL 静态属性,十进制 MB),改注册表也不会变;真正的闸门由SystemPartitionCommitLimitPercentage控制,两者不是一回事。
本文所有数字均为本机实测值,非估算或引用。