
老显卡实验室这个系列上篇把单卡2080Ti跑27B档模型的极致榨干聊得差不多了这篇进入双卡阶段。过去三个月我的机箱里一直躺着两张二手2080Ti11G×2日常任务就是跑27B档的开源模型从最初“能加载”到后面“能长期用”踩过的坑和算清楚的账都沉淀在这篇里。如果你手里正好有老显卡或者预算有限但想本地部署27B档大模型这篇内容可以直接抄作业显存账本怎么算、去审查模型怎么选、双卡怎么切分最划算每一条都是实测过的。先给结论双卡2080Ti11G×2跑27B档模型完全可行但前提是你得先把显存账本算明白。账算错了加载的一瞬间就崩给你看账算对了模型权重、KV cache、CUDA上下文各就各位一张旧卡也能稳定服务三个月。下面按我的实际操作顺序把账簿摊开讲。1. 双卡硬件底座显存账本的第一行1.1 为什么选双卡2080Ti而不是一张大显存卡先说大方向。市面上能一张卡搞定27B量化模型的最便宜的新卡也得是24G显存起步二手3090长期在五千上下浮动4090更是轻松破万。而两张二手2080Ti按目前行情每张一千出头两千多就能拿下总计22G显存。这价格差了将近一半吸引力确实大。但便宜不是白拿的。双卡方案要面对三个问题两张卡怎么通信、模型层怎么切、显存碎片怎么忍。这些问题如果不想清楚22G就是纸面数字真正跑到一半还是爆显存。2080Ti这块卡本身也值得说两句。图灵架构不带第四代Tensor Core那么新但11G GDDR6在当年是旗舰容量二手市场量大管饱很多还是涡轮版机架式散热拆下来用在普通机箱里也压得住。另外2080Ti的FP16算力半精度在今天跑量化模型完全够用INT4推理更是游刃有余。相比老Pascal卡比如P40/P100只能跑FP32要心疼带宽2080Ti算是个甜点。1.2 NVLink与PCIe双卡通信的带宽账双卡最关键的一步不是插上就完事先看看两张卡之间能不能走NVLink。2080Ti公版和部分非公版带NVLink金手指如果你捡到的卡有这个接口再配一根NVLink桥两张卡之间的通信带宽能跑到约100GB/s级别。别小看这个数字跑27B这种跨卡推理时卡的协作非常频繁带宽直接决定你能不能在合理速度下跑完一个长对话。没有NVLink也没关系PCIe 3.0 x16的通道照样能凑合只是带宽掉到约13GB/s左右跨卡通信的延迟会明显更高。实测做张量并行tensor parallel时有桥和没桥的速度差距大概在20%到40%之间具体取决于模型层数与batch大小。层数越多、单次通信越频繁桥的作用越明显。先检查硬件拓扑Linux下用这个nvidia-smi topo -m这命令会打印两张卡之间的互联类型如果显示NV#NVLink恭喜如果显示PIXPCIe内部交换也能用只是在分配方案上别选太激进的张量切分。1.3 系统可用显存的实账两张卡不等于22G这是双卡新手最容易踩的坑。买两张11G卡理论上22G实际上两卡各自的系统保留和CUDA上下文就要吃掉大约300到500MB每张。再加上驱动预留给显示的显存以及Llama.cpp或transformers在加载时按固定粒度分配造成的碎片两张卡最后能稳定分配给你的模型权重和KV cache的空间大约是21G到21.5G。如果你用Windows跑这个折扣还要再狠点因为WDDM驱动模式下的显存管理不如Linux的TCC模式干净有时能用的就剩20G左右。所以我后来干脆把主力环境固定在Linux上Windows那套只做快速测试。这里也顺便回应一个常被问到的问题显存位置到底怎么理解实际跑起来nvidia-smi看到的每一行显存区间跟你模型里哪几层被放过去是一一对应的。我习惯先画一张“显存位置图解”的脑内地图比如第0到23层放第一张卡第24到47层放第二张卡如果走张量切分则是每一层的前半权重在第一张卡后半权重在第二张卡。这个分法决定了通信频率也是后面章节要细聊的内容。2. 27B模型的显存账本权重、KV、激活值三本账2.1 权重量化从54G压到17G的关键27B档模型也就是大约270亿参数是本地部署的一个甜点规模能力比7B/14B高一个档又比70B好伺候得多。但甜点是针对显存而言的相对说法账还得一笔一笔算。模型权重的原始体积按参数和精度决定精度每参数字节27B模型权重体积FP16/BF162字节约54GBINT81字节约27GBINT4AWQ/GPTQ约0.55-0.65字节约15-18GBGGUF Q4_K_M约0.55-0.6字节约15-17GBGGUF Q3_K_M约0.5字节约13-14GB单张2080Ti的11G是肯定装不下FP16的54G这就是量化的意义。所谓“低显存运行模型”核心思路就是把权重精度压下来把显存让给更影响体验的上下文长度。我实测下来27B档模型最稳的组合是GGUF Q4_K_M也就是权重占用16G上下。这个精度下模型的推理质量跟FP16差距已经很小尤其是对话、写作、代码辅助这些日常任务几乎感知不到差别。再往下压到Q3_K_M也能跑但长文本生成的逻辑一致性偶尔会掉链子比如写到一半主语突然变了这种问题很烦人。2.2 KV cache长上下文的隐形吞噬者权重账算完还有第二本账KV cache。很多人加载模型后看到剩余显存很多就拼命拉上下文长度结果跑了几千token直接爆显存就是因为没算KV cache。KV cache的计算公式不复杂每个token的KV显存 层数 × KV头数 × 头维度 × 2K和V各一份 × dtype字节数我举一个实际例子。假设某个27B档模型是48层采用GQA分组查询注意力每组8个KV头注意力头维度是128用FP16存KV每token每层 2 × 8 × 128 × 2字节 4096字节 4KB 48层合计 4KB × 48 192KB/token 4K上下文 ≈ 192KB × 4096 768MB 32K上下文 ≈ 192KB × 32768 6.2GB注意这只是FP16 KV cache的算法。如果你把KV cache也量化成FP8体积能再砍一半但实际收益有限因为KV cache在长上下文场景下增长太快再怎么砍也架不住塞几十万token。所以我的做法是上下文长度根据剩余显存反推而不是拍脑袋拉满。还有一个容易忽略的点如果做并发请求比如本地起了个OpenAI兼容的API服务KV cache是所有并发请求共享的每个请求都要占用一份独立的KV空间。双卡跑27B时我通常只允许1到2个并发否则上下文稍微一长就爆。2.3 双卡并行放模型层切与张量切的取舍显存账本算完接下来是物理放置问题。双卡放模型有两种主流切法层切Layer/Pipeline Parallelism把模型的第0到23层放第一张卡24到47层放第二张卡。好处是实现简单Llama.cpp的--split-mode layer就是这个逻辑坏处是层间通信有累积延迟而且如果模型层数是奇数两张卡的负载会明显不均衡。张量切Tensor Parallelism每一层内部把权重矩阵按列/行拆成两半分别放两张卡。好处是显存占用非常均衡通信集中在一个层内延迟可控坏处是通信量比层切大得多没有NVLink的情况下速度很难看。我实测的结论是如果有NVLink优先考虑张量切没有NVLink老老实实做层切。Llama.cpp新版也支持这两个模式# 层切适合无NVLink的双卡 llama-server -m model-q4_k_m.gguf --split-mode layer -ngl 999 # 张量切适合有NVLink的双卡 llama-server -m model-q4_k_m.gguf --split-mode row -ngl 999如果你是走transformers路线用device_mapauto时Accelerate会自动做层切但要注意它会优先填满第一张卡再填第二张容易造成第一张卡不够放、第二张卡还有很大余量。所以我会手动给device_map指定每层位置或者用max_memory参数约束两卡各自的分配上限。2.4 实测峰值曲线什么时候显存会突然爆掉三个月里我记录了不少次显存峰值。最有价值的一次发现是显存占用不是线性上升的而是有几个明显的爆发点。第一个爆发点在加载阶段。Llama.cpp在加载GGUF时先把整个文件mmap进来如果文件里有不连续的部分分配会有短暂的高峰可能比稳态高出1到2G。所以加载27B Q4_K_M时别以为稳态17G就够加载瞬间可能冲到19G甚至更高。第二个爆发点在长上下文生成中。生成到后半段KV cache持续累积显存占用爬坡这时候如果上下文长度刚好卡在极限就可能“在最后一公里”爆掉。我遇到过几次生成到9000多token时爆显存气得直拍桌子。后来学乖了把max context留出15%余量比如算出来能跑12000实际就设10000。第三个爆发点跟碎片有关。双卡反复加载卸载模型后显存碎片化严重新加载时明明总量够却因为无法找到连续区域而分配失败。这个问题的解法是重启进程或者用torch.cuda.empty_cache()如果你用的是PyTorch栈。顺便回应一下热词里提到的“imagez显存需求”。很多从绘图转向LLM的朋友问我跑SDXL/FLUX类出图模型是不是也吃这么多显存。绘图模型的显存账本跟LLM完全不同绘图更看重单次前向传播的激活值峰值SDXL大概10到12G就够出图任务也不怎么吃KV cache而LLM是权重KV持续双账单27B模型跑起来比大多数绘图任务紧张得多。两套账不能混着算。3. 去审查模型迁移实测少一点“我不能”的工作流3.1 原版模型的说教感是怎么来的第三个核心话题是“去审查模型”。这个词在不同语境下理解不同先把范围说清楚我这里讲的是开源模型权重层自带的行为限制以及社区如何通过权重改造让模型减少那种“作为一个AI我不能……”的拒绝话术。做过本地部署的人都懂很多开源模型虽然能力不错但训练阶段被灌入了大量“安全对齐”样本结果就是无论你问什么它都先给你来一段免责声明。偶发一两次能忍真遇到任务时比如写一个虚构的短篇小说、模拟一个角色对话、整理一份业务话术它每隔几句就打断你说“这可能不当”体验几乎没法用。这种说教感的来源本质上是模型权重里学到了一条“拒绝方向”。顺着这条方向采样模型就爱输出安全免责类内容。社区针对这个现象的做法是在权重空间里找到并削弱这个方向产出所谓的“去审查版”或“abliterated”模型。3.2 几种去审查模型的对比目前社区里常见的去审查模型有几大类Abliterated系列典型如Gemma-2-27B abliterated、Mistral系abliterated用的是权重层面削弱拒绝方向的思路。Dolphin系列主打对你放开手脚的微调版本覆盖面广从7B到70B都有。Nous系列以降低拒答率和提升指令遵循见长偏创作向。我实测对比了原版和去审查版同规模模型的表现对比维度原版去审查版普通问答良好良好差距很小虚构故事创作频繁插入提醒基本不打断角色扮演应付感强动作、语气自然很多代码辅助正常正常显存占用基本相同基本相同注意去审查版不是“性能变强”而是“行为变了”。同一个27B模型基座去审查版在MMLU这类基准上可能轻微掉零点几个点但日常使用感知不出来反而在需要输出连贯长文本的场景里体验是质的提升。3.3 双卡部署去审查模型的具体配置落到双卡部署上去审查模型的加载跟普通模型没本质区别。我用的组合是GGUF格式去审查版 Llama.cpp双卡层切命令行跟前面一样只是换模型文件。如果你用的是Ollama可以直接通过Modelfile导入外部GGUFFROM /path/to/abliterated-q4_k_m.gguf TEMPLATE {{ if .System }}system{{ .System }}/system{{ end }}user{{ .Prompt }}/userassistant PARAMETER temperature 0.7 PARAMETER top_p 0.9然后用ollama create构建成本地模型。Ollama在双卡上的显存管理默认比较保守加载前可以用OLLAMA_MAX_LOADED_MODELS1限制同时加载的模型数避免两个模型抢显存。我个人的习惯是直接在Llama.cpp上跑不用外层框架因为双卡场景下Llama.cpp的--split-mode控制最直接而且能精确看到两张卡各自的显存占用。部署完成后用nvidia-smi盯一下确保两张卡占用均衡比如第一张卡占用8.9G、第二张卡占用8.7G这种比例才正常如果出现一张卡11G拉满、另一张卡只有3G这种怪象多半是切分模式没生效。3.4 一次翻车记录去审查版也救不回来的场景聊完成功经验也得说一次翻车记录。我曾想靠去审查模型解决“工具调用老是自作主张解释”的问题结果发现完全没用。原因是那个问题出在模型对工具调用的格式理解上不是审查行为问题。换成原版模型反而更稳。这个教训很重要去审查模型解决的是“过度拒绝”这个具体问题它不是万灵丹。如果你的模型表现不好先判断是能力问题、格式问题还是拒绝行为问题别一刀切全归结为“审查太严”。另外即使去审查模型变通了很多如果你在推理框架里还挂了内容过滤插件或者用了带内置System Prompt的服务端那个过滤层仍然会起作用——这是框架层的事跟模型权重无关。还要提一句合规边界去审查模型的价值在于让AI在虚构内容创作、角色扮演、冷门知识整理等场景里保持流畅而不是制造违法违规内容的工具。越狱提示词那套东西我不碰也不建议碰那既不稳定也不安全纯属浪费电。4. 三个月运行实录速度、温度与稳定性4.1 双卡实际吞吐一个能接受的数字理论讲完上实测数字。双卡2080Ti跑27B GGUF Q4_K_M我这边记录的稳定速度大致如下场景速度范围预填充prompt处理15-25 token/s普通长度生成decoding2048上下文内8-12 token/s生成decoding4096长上下文5-8 token/s并发2路每路降到约60%-70%作为对比我用朋友的一张二手309024G单卡跑同样模型生成速度大概是25-35 token/s。也就是说双卡2080Ti花了大约一半的钱换来的是3090约三分之一的吞吐。单看单次生成双卡慢不少但如果你主要用途是任务型调用、批量文本处理、或者夜里挂着批量跑数据慢一点完全能接受显存容量才是瓶颈。另外双卡的速度瓶颈很大程度在跨卡通信。如果你没有NVLink桥建议至少用PCIe 3.0 x16插槽别傻乎乎插x4槽那会把速度砍到惨不忍睹生成速率可能跌到2-3 token/s基本没法用。4.2 长时间跑下来的显存泄漏与自动重启三个月运行里最烦人的问题不是速度是显存泄漏。Llama.cpp在长时间连续服务后偶尔会出现显存占用逐渐爬升的情况从启动时的17G慢慢涨到18.5G再过几小时甚至突破19G。这不是模型权重变了大概率是各个连接会话的上下文缓冲区没有被完全释放或者某个bug导致KV cache的旧块没被回收。我的对策是写了一个极简的守护脚本监控显存占用和日志错误一旦超阈值就自动重启服务#!/bin/bash while true; do usage$(nvidia-smi --query-gpumemory.used --formatcsv,noheader,nounits -i 0 | tr -d ) if [ $usage -gt 19000 ]; then echo $(date) 显存使用过高重启服务 pkill -f llama-server sleep 3 nohup llama-server -m model-q4_k_m.gguf --split-mode layer -ngl 999 --ctx-size 10000 /var/log/llama.log 21 fi sleep 60 done这个脚本不优雅但很管用。老显卡实验室的原则就是能自动解决的绝不手动盯着屏幕。4.3 二手卡的温度和风扇控制经验2080Ti毕竟是老卡满载跑27B模型时GPU核心温度普遍在80到85摄氏度显存温度则经常摸到95度以上。这在冬季问题不大但夏天不开空调的话机箱就是个小暖炉。我的处理方案有两步。第一步是清理换硅脂二手卡买回来第一件事就是拆开清灰、换导热垫和硅脂显存温度能降个10度以上第二步是调风扇曲线用nvidia-smi的--auto-boost-permission0加上第三方工具如nvidia-applet或coolgpu把风扇转速拉高。涡轮版2080Ti满载转速上去后很吵但放在工作室或阳台机柜里噪音可以接受。长期执行的观察是只要核心温度控制在85度以内显存温度控制在100度以内这张卡就能稳定跑几个月不罢工。我这两张卡已经连续满载跑了三个月期间没出过硬件故障。老卡最怕的不是高温而是积灰和干掉的导热垫这是定期的必备保养。5. 选型口诀与避坑清单5.1 给老显卡用户的六句口诀三个月跑下来我把经验浓缩成几句口诀分享给想抄作业的人参数看整数显存跟着量化走27B模型的4bit量化权重按参数量除以1.7到1.8估算GB基本不出大格。可用显存先打九折两张11G算出来22G按21G左右规划别卡着上限分配。上下文越长KV越贵每增长一倍上下文KV占用线性翻倍一条公式算清楚再设ctx-size。双卡没桥别硬上张量切没有NVLink的PCIe互联老老实实层切速度比频繁通信的张量切稳得多。去审查模型解决拒答不解决能力问题先定位问题类型再决定换不换模型。老卡留一G给碎片和峰值显存规划永远留出10%-15%余量保平安。5.2 最容易踩的五个坑和排查命令整理一下我踩过或者围观别人踩过的坑每个都配排查方法P2P通道没开启层切也许受影响不明显张量切直接慢到怀疑人生。排查nvidia-smi p2p -c。两张卡负载严重不均一卡满显存另一卡空闲。排查跑生成时观察nvidia-smi两卡的Memory和Utilization差距超过30%就是切分模式设置有问题。上下文溢出但不知道是谁占的不能确定是权重还是KV爆掉时把--ctx-size调到最小比如512试跑如果还爆那是权重和系统开销问题如果不爆了说明是KV撑爆的。GGUF文件损坏导致加载失败下载大模型经常遇到断档加载时直接报错。排查sha256sum核对哈希或者重新下文件。驱动版本和PyTorch/CUDA不匹配最常见于transformers路线报错往往一堆乱码。排查python -c import torch; print(torch.version.cuda)跟驱动支持的CUDA版本对比。5.3 什么时候不该用双卡方案最后泼一盆冷水双卡2080Ti虽然便宜但不是所有场景都适合。如果你预算刚好够上一张24G卡的边比如二手3090降到4000出头而且你需要的是高速生成和低延迟单卡3090是明确更好的选择。双卡方案的代价是通信延迟、显存碎片和运维复杂度换来的是显存容量适合预算紧张但能接受慢速的人。另外如果你只有短上下文需求比如每次对话就一两百token其实单卡2080Ti配合Q3量化已经能跑双卡的意义不大。反过来说只要你的需求里有一条是“长文档总结”“大批量离线处理”或者“本地私有化的24小时服务”双卡2080Ti就是性价比很高的答案。三个月用下来我对双卡2080Ti跑27B这件事的结论很实在它不是一个完美的方案但它是预算有限的情况下最接近“花小钱办大事”的一条路。账本一定要自己算一遍别信网上随手写的“11G×2能跑27B”这种话能跑跟稳跑是两码事。最后再分享一个我个人的小习惯每次换模型或改量化参数我都会用同一个提示词先跑一遍记录首token延迟和生成速度建立一张自己的基线表。这样显卡性能衰减、驱动升级影响、模型质量波动全都能用量化数据说话而不是靠感觉。老显卡实验室下篇再见。