
做这件事之前我一度觉得“端侧跑27B”是厂商发布会上的PPT话术。直到我真的把一套27B参数的开源权重模型从云端四卡GPU机器搬到了身边的设备上才算改变这个看法。所谓设备不是高配PC而是四块RK1828核心板互相级联拼起来的小集群。跑通的参数档位是27B的Dense模型以及31B这个档位的MoE权重。这个过程中遇到的硬件形态选择、显存预算计算、推理框架配置、并行策略取舍每一环都有不少值得记录的东西。这篇东西适合谁看手里有RK1828这类端侧算力板想把模型往本地设备上搬而不是只跑个7B/8B小玩具的人。也适合正在纠结“多卡级联到底怎么联、并行怎么选、量化怎么配”的开发者。我会把能落地的命令、参数、计算过程都摆出来也把翻车经验一起放上。1. 为什么非要在端侧跑27B/31B场景、门槛与目标设定1.1 云端都干得好好的为什么还要往端侧搬先讲清楚动机不然你可能觉得我在折腾。我手上的业务场景是给某个内部知识库系统做推理服务。之前方案很常规把资料切好、做向量化索引然后丢给云端API去生成回答。平时用着还行一旦遇到断网、专线波动或者半夜跑批量任务云端接口的延迟和费用就变得很难受。更麻烦的是知识库里有不少需要保密的数据每次走公网API都要过一层脱敏效率打折心里也总觉得不踏实。于是我开始认真考虑能不能把模型直接部署到本地的端侧设备上让数据和推理都留在内网如果只跑7B、8B这种小模型业务效果跟不上。知识库问答的瓶颈在于长文本理解、多轮推理和指令遵循能力这几个指标在27B以下的模型上表现差距非常明显。所以从一开始我的目标就很明确就算用端侧硬件也要尽量跑27B级别以上的权重。这个档位在开源社区选择多、效果够用、中文能力也可控。1.2 27B/31B这个档位为什么值得折腾很多人觉得端侧跑大模型就是“能加载”就行其实不然。模型能不能跑起来只是第一关更关键的是跑起来之后能不能稳定服务、生成质量还靠不靠谱。27B的Dense模型比如Qwen2.5-27B以及31B这个档位的MoE权重比如Qwen3-30B-A3B这类激活参数更小的模型在代码生成、结构化输出、复杂指令跟随上的表现远好于8B。尤其在做工具调用和JSON输出时27B模型的格式稳定性会明显优于小参数模型。这也是我执着于这个档位的原因。但随之而来的问题是单块RK1828核心板的内存容量和算力根本扛不住27B。我手上这块RK1828载的是8GB LPDDR5单卡加载Q4_K_M量化的27B模型光权重就要占14GB左右加上KV Cache和运行时开销直接爆掉。唯一的出路就是把4块板子级联起来组成一个逻辑上的“大显存推理节点”。这个思路说起来简单落地时才发现一堆问题级联走什么物理接口、并行策略选张量并行还是层流水、模型张量怎么分配到各卡上、通信瓶颈到底卡不卡脖子。下面我会按照从硬件到软件的完整链路来拆解。2. 4卡级联的硬件形态算力池化的几种连接方案2.1 端侧级联的常见连接方式对比端侧板卡做多卡级联物理链路的选型直接决定了通信带宽和实现复杂度。我实际调研和测试过三条路以太网、USB、私有高速接口。以太网是最省事的方案。RK1828核心板基本都带千兆以太网口有些板子还能扩展2.5G网口。用网线把四块板子接到同一个交换机上各板分配固定IP上层用支持RPC分布式推理的框架直接组网。好处是拓扑简单、驱动成熟坏处是带宽相对有限千兆网的理论峰值只有125MB/s跑起张量并行来很容易成为瓶颈。USB方案我试过OTG直连用USB3.0的速率做数据传输。实测在低负载小模型的场景下表现尚可但一旦模型变大、张量切分粒度细USB主机控制器和驱动栈会成为新的瓶颈而且四块板子同时通过USB组网拓扑管理也麻烦。私有高速接口我没有采用原因是手上的板子没有开放的高速互连端口需要额外做硬件适配。如果你手头的设备支持PCIE或者类NVLink的私有协议优先用它带宽优势是碾压级的。我最终选择的方案是2.5G以太网加交换机组成星型拓扑。四块板子各自通过网线接到一台2.5G交换机主机也就是第一块板作为推理服务的入口同时负责模型加载和任务分发。这个选择不是因为它性能最强而是因为它最稳定、最容易排查问题后续扩到8卡也只需要换交换机。2.2 我选择的物理连线与网络规划细节硬件拓扑定了之后网络规划是第一个能直接影响成败的细节。这里我踩过坑养成了一个习惯所有级联板卡走独立网段不要和办公网混在一起。我用的网段是192.168.50.0/24四块板子IP分别规划为角色IP地址端口/服务主控节点 / 推理网关192.168.50.10llama-server RPC服务端计算节点1192.168.50.11rpc-server :50052计算节点2192.168.50.12rpc-server :50052计算节点3192.168.50.13rpc-server :50052计算节点4192.168.50.14rpc-server :50052每块板上都要单独配置好静态IP然后互相ping通。这里有个容易被忽略的点RPC分布式推理的底层通信非常依赖稳定性如果走DHCP或者无线网络IP一旦漂移推理任务就会中断。另外有条件的话最好把交换机的巨型帧Jumbo Frame打开MTU设到9000对降低大模型张量通信的CPU开销有帮助。在这个阶段我还建议先跑一个多机通信基准测试工具比如iperf3确认四块板子两两之间的实测带宽能达到预期。我自己的环境里2.5G网口的实测吞吐可以稳定跑到1.5Gbps以上虽然达不到线速但已足够支撑后面的层流水并行方案。3. 显存与算力预算27B/31B怎么拆进4张卡3.1 显存预算先把账算清楚再动手很多人的第一步就是下载模型然后直接跑结果OOM了再乱调参数。正确做法是先算内存账。以27B Dense模型的Q4_K_M量化版本为例我把每一项占用的显存都拆开算了一遍权重文件约14.4GBKV Cache取决于上下文长度和层数配置在4096上下文、GQA配置下大约需要2.5GB到4GB。推理时的临时激活值、中间张量会根据batch size变化单batch推理时约0.5GB到1.5GB。加起来整体内存需求在17GB到20GB之间。注意我这里的KV Cache是按量化过的估算Q8_0 KV Cache会比FP16小一半是端侧设备必须开启的选项。四块8GB板卡加起来约32GB总内存看起来够用但实际还要扣除系统、NPU运行时和框架本身的开销。我实测每块板卡大约只能稳定提供6.5GB给模型相关数据四卡合计约26GB。所以27B模型能塞进去但余量不算宽裕。3.2 31B MoE模型的显存特殊性31B这个档位我跑的是MoE架构权重。MoE模型的总参数看着很大但推理时只激活其中一部分专家这是它对端侧最友好的点。以总参数31B、激活参数3B左右的MoE模型为例在相同Q4量化下权重文件约16GBKV Cache约1.5GB到2GB激活值比同参数的Dense模型小很多约0.3GB。整体内存需求约18GB反而比27B Dense模型更容易端侧落地。不过MoE模型有个隐性痛点虽然激活参数少但权重文件还是要完整加载到内存里因为推理过程中专家路由是不确定的理论上任何一个专家都可能被激活所以没法只加载部分专家该占的内存一分不少。这也意味着MoE模型的显存瓶颈主要在权重加载而不是推理计算。实际部署时我的分配策略是前两块板子放更多的权重层后两块板子负责剩余的权重加KV Cache。你可以用--tensor-split参数按比例手动分配比如1.2,1.2,0.8,0.8让显存占用高的节点不要同时承担太多运算任务避免提前触发节流。4. 推理框架与并行策略的落地4.1 框架选型端侧没有那么多花里胡哨端侧部署大模型的推理框架第一反应可能是vLLM。但vLLM目前对ARM系SoC的适配并不友好而且多卡分布式更多面向NVLink/InfiniBand等高带宽互联环境。在RK1828这类嵌入式平台上更稳妥的选择是llama.cpp的分布式RPC方案。llama.cpp的RPC方案简单说就是有一个主进程负责加载模型和编排其他计算节点各自跑一个rpc-server进程模型张量会按规则自动分配到各节点上推理时通过以太网进行中间结果传输。我的选择逻辑非常实际第一它能跑GGUF量化格式端侧内存友好第二原生支持RPC分布式不用自己写并行代码第三和主流的Ollama、llama-cpp-python兼容上层接口不用重复改。最关键的是它有现成的OpenAI兼容API服务端我可以直接把业务代码从云端切到端侧。4.2 并行策略为什么我最终选了层流水而不是张量并行这是整篇里我最想展开的部分。多卡并行有两个基本思路张量并行和层流水Pipeline Parallelism。张量并行是把每一层的权重拆开分到多张卡上比如把一个大的矩阵乘法切成两块每卡算一半最后汇总。这种并行方式的通信次数极其频繁每一层Transformer都有多次同步点。在NVLink这种600GB/s级别的互联上没问题但在2.5G以太网上通信开销会直接吞噬掉并行收益。我实测过用张量并行在四卡级联上跑27B生成速度反而比单卡硬扛还慢卡间同步时间占了总耗时的一半以上。层流水则完全不同。它是按Transformer层来划分每块板子负责其中一段连续的层。数据像流水线一样从第一块传到第二块再传到第三块、第四块。每一层只需要把自己的输出传给下一块板子通信频率远低于张量并行通信量和模型表示层数无关只和每层的中间表征尺寸、序列长度相关。我在2.5G以太网环境下测试层流水的吞吐明显优于张量并行。因为解码阶段是逐token生成的真正跨卡传输的只有最后一个token的隐状态通信量非常固定瓶颈只会在prefill阶段比较明显。这个结论和在数据中心用PP并行而不是纯TP的思路是一致的但端侧因为带宽更窄这个选择更加关键。llama.cpp的RPC方案会按张量分配规则把不同层的权重放到对应节点上再配合--override-tensor参数可以手动指定某些层放到指定节点。我建议对显存不是特别紧张的MoE模型直接用默认策略但对27B Dense模型手动调整层分布能明显降低最大节点内存峰值。4.3 实际操作流程与参数配置以27B Dense模型为例我把完整流程拉一遍。前提是四块板子已经按前面的网络规划配好并且都能访问同一个模型文件目录或者各自持有模型文件副本。第一步编译llama.cpp并开启RPC支持在三台计算节点上分别启动rpc-server# 每台计算节点上执行 ./llama-rpc-server --host 0.0.0.0 --port 50052第二步在主控节点上启动推理服务./llama-server \ -m /models/qwen2.5-27b-instruct-q4_k_m.gguf \ --host 0.0.0.0 --port 8080 \ --rpc 192.168.50.11:50052,192.168.50.12:50052,192.168.50.13:50052,192.168.50.14:50052 \ --cache-type-k q8_0 \ --cache-type-v q8_0 \ --ctx-size 8192 \ --batch-size 512 \ --parallel 1这里的--cache-type-k q8_0 --cache-type-v q8_0是端侧设备必须开的。FP16的KV Cache在长上下文下会直接吃掉大半内存用Q8_0量化后KV Cache体积减半质量损失在常规任务中几乎感知不到。第三步验证服务curl http://192.168.50.10:8080/v1/chat/completions \ -H Content-Type: application/json \ -d {model:qwen2.5-27b,messages:[{role:user,content:你好用一句话介绍你自己}],max_tokens:200}如果返回正常说明四卡级联和分布式推理已经通了。这里有一点要注意如果你用的是Ollama也可以直接配置OLLAMA_HOST指向主控节点的8080端口业务代码不用动。我实际跑的时候发现OpenAI兼容接口的稳定性比预期好连续跑了48小时没有崩溃。5. 实测性能吞吐、首字时延与显存占用的真实表现5.1 关键指标记录性能数据部分我分两个场景记录短文本请求类似于日常问答和长文档处理类似知识库片段分析。短文本场景输入64个token输出128个token。在四卡级联层流水方案下首token时延约850ms后续生成速度稳定在9.5到11 token/s之间。这个速度在交互式问答里算是能用的虽然比不过云端A100的几十上百token/s但考虑到这是端侧设备已经达到“可服务”的及格线。长文本场景输入2048个token输出512个token。由于prefill阶段的计算量暴增首token时延飙到了3.5秒。但后续生成速度没有大幅下降维持在8 token/s左右。这说明prefill是端侧4卡级联的主要瓶颈而decode阶段受通信影响较小。我还单独测了批处理的影响。把batch-size从默认的2048降到了512首token时延反而降低了约20%。因为在端侧设备上过大的batch-size会导致显存和内存带宽被prefill阶段临时占用反而拖慢后续请求。针对交互式场景小batch-size更合适。5.2 显存占用的真实观察我用free -m和/proc/meminfo实时监控了各节点的内存使用。27B Dense模型Q4_K_M四卡平均每卡占用约5.8GB其中主控节点约6.2GB其余三卡约5.5GB。总占用接近23GB和预算基本吻合。31B MoE模型的情况更好一些平均每卡占用约5.2GB因为它的激活值更小而且我对MoE模型的层分配做了更精细的手动调整。这里有个值得分享的小技巧如果你发现某张卡内存特别吃紧可以用--override-tensor把部分Attention层的张量强制放到另一张卡上。比如提示词处理和输出层都在主控节点主控节点的内存压力天然比计算节点大可以把开头的embedding和前面的几层挪到计算节点平衡一下。5.3 从实测数据得出的优化方向从数据来看四卡级联跑27B/31B端侧模型的性能瓶颈有三个层次第一是prefill阶段的计算密度不够导致长文本首字时延偏高第二是跨卡通信在prefill大量数据交换时会有压力第三是单卡内存带宽有限限制了decode阶段的吞吐。针对这三个瓶颈后续优化方向也清晰一是考虑把prompt cache做持久化缩短重复前缀的首字时延二是尝试对不同张量类型做异构放置比如让计算密集层和执行稀疏层分开部署三是官方如果后续能开放更高带宽的互联接口可以直接把TP方案再拉回来跑一次对比。6. 踩坑实录静默丢卡、量化漂移与负载不均的排查链路6.1 坑一节点偶发失联导致推理中断第一次跑通后我做了个压力测试脚本往接口里连续灌了3000条请求跑到第800条左右时生成速度突然从11 token/s掉到2 token/s再过了一会儿直接报连接超时。查看日志发现是某个计算节点的rpc-server退出了。排查链路是这样的先确认是不是电源问题毕竟四块板子同时高负载运行对电流要求不低。我换了更大功率的电源适配器情况没有改善。再用dmesg查看内核日志发现网卡驱动报了tx timeout错误。继续追查发现是交换机端口的节能以太网EEE功能导致的它在低流量时会让网口进入休眠高流量突发时重新唤醒会产生延迟干扰了推理中的长连接。解决办法很简单在板卡的网卡参数里关闭EEEethtool --set-eee eth0 eee off关掉之后重新跑压测再没有出现节点失联的情况。这个坑特别隐蔽因为它的症状是偶发性的非常容易让人怀疑是推理框架本身的问题。我把排查链路完整写出来就是希望大家遇到类似问题时不要一上来就怀疑模型配置先检查底层网络和电源。6.2 坑二量化方案选择导致输出质量崩坏第二个坑是在换31B MoE模型时遇到的。我一开始图省事直接用了Q2_K量化版本加载是加载下来了整体内存占用也很低但生成的内容完全不能看还有不少重复和乱码。这个问题的本质是量化精度不够导致的权重漂移。MoE模型的专家权重对量化误差的敏感度比Dense模型更高因为每个专家只负责特定类型的输入如果某个专家权重被压得太狠它对特定输入的响应就会失真表现出来就是各种乱输出。解决思路是分层量化对Attention层的权重用Q5_K_M对FFN和专家层的权重用Q4_K_M两种精度混搭。llama.cpp通过--override-tensor支持按张量名前缀指定精度但更简洁的做法是直接用llama-quantize工具在生成GGUF时指定混合精度。./llama-quantize \ --allow-requantize \ --override-tensor expert_down.31.weight:Q5_K_M \ --override-tensor expert_gate.31.weight:Q5_K_M \ --override-tensor token_embd.weight:Q6_K \ -o model-q5k4m.gguf \ model-f32.gguf Q4_K_M换用混合精度量化后模型输出质量恢复到了可用水平。当然如果你的模型原版就是已经量化好的GGUF先看看它的量化类型尽量不要选Q2_KQ4_K_M是端侧部署稳定性和质量之间的最佳折中点。6.3 坑三显存负载不均导致生成速度断崖第三个坑比较隐蔽我调了好几天才发现。现象是生成速度一开始很正常跑了几十个token之后突然下降然后慢慢恢复然后又下降速度曲线像过山车一样。我以为是KV Cache满了触发重计算于是增大上下文窗口结果没用。后来我用top逐卡看进程状态发现其中一张卡的CPU占用率特别高而其他卡都比较空闲。进一步查看原来是主控节点上开了Prompt Cache也就是llama.cpp的--cache_prompt特性它会额外占用主控节点的内存和算力来处理缓存的重复前缀。在高并发请求下主控节点的内存带宽被缓存读写吃掉了导致整体速度波动。解决办法是把这个特性关掉或者在负载均衡层做调整把请求轮询到不同节点上。我最终选择的是关掉主控节点的Prompt Cache让四张卡的负载更均衡速度曲线明显变得平缓。如果你确实需要Prompt Cache加速长文档场景建议把它放在单独一张卡上不要让主控节点同时承担推理和缓存。7. 收尾个人经验总结与一条实用小建议这次把27B/31B模型跑通到四卡级联的RK1828端侧设备上最大的体会是“端侧大模型”不是一个性能问题而是一个系统工程问题。算力不够可以加卡显存不够可以级联真正的难点在于对通信带宽、并行策略、量化精度、显存分配这些因素做联合调优缺一环都会导致整个方案不可用。如果只让我留一条建议给后来者那就是先算账再动手。把模型的权重大小、KV Cache需求、并行通信频率、每张卡的可用内存这四个数字先列出来你和你的方案能不能成其实在动手前就已经能判断八九成了。我见过太多人兴冲冲下好模型加载时OOM然后才开始临时降精度、砍上下文最后性能和效果两头都保不住。这套四卡级联方案后续我还会继续扩展。一方面打算接入更完整的Agent工具调用能力让27B模型在端侧直接完成函数调用的解析另一方面也在测试RAG场景下的长文档流式处理把预处理和检索也下沉到端侧。RK1828这类平台的出现确实把过去“只能云上跑”的事拉回到了本地接下来就看大家怎么把算力利用率做到极致了。