[控场AI]
· 7 分钟阅读· 3,835 字

Qwen3.8 vs Ornith 1.5:Mac本地推理速度与代码审查实测

Qwen3.8 vs Ornith 1.5:Mac本地推理速度与代码审查实测

Mac上横评显示Ornith 1.5首token快7倍,代码审查与Qwen打平,但两模型无法共存。

作者在Mac Studio M4 Max(64GB)上用oMLX 0.7.0横评Qwen3.8-27B(带MTP)与Ornith 1.5 35B-A3B(MoE加DFlash)。结论是Ornith在速度上全面胜出:800 token提示下首token延迟0.49秒对3.46秒,差距7倍,而输出速度55.1对90.4 tokens/秒差距较小,故代码代理场景中首token时间比吞吐更关键。代码审查测试中两者检出率持平(关闭推理时9/20对8/20),但开启推理后Qwen检出反降至6/20且大量回答因超长无法解析,耗时约为Ornith两倍。Qwen占用16.1GB、Ornith 19.8GB,oMLX内存守卫拒绝二者共存,切换时可能导致请求丢失。Qwen偶有JSON截断,约束解码可修复但会禁用MTP并使速度降至约25 tokens/秒。作者目前留用Ornith。

在Mac Studio M4 Max(64GB)上,我用oMLX 0.7.0对两款本地模型进行了横评:Qwen3.8-27B(带MTP多token预测)和Ornith 1.5 35B-A3B(MoE架构,激活约3B参数,配合DFlash投机解码)。结论很明确——Ornith 1.5在速度上全面胜出,代码审查能力两者持平,而Qwen3.8在内存占用和JSON输出稳定性上存在明显短板。

Qwen3.8 vs Ornith 1.5 速度对比

首token延迟:决定性指标

对于代码代理和代码审查场景,首token时间(TTFT)才是真正的瓶颈。实测数据显示,在800 token输入提示下,Qwen3.8-27B的首token延迟为3.46秒,而Ornith 1.5仅需0.49秒——差距达7倍。输出速度方面,Qwen为55.1 tokens/秒,Ornith为90.4 tokens/秒,差距相对较小。

在聊天场景中,3秒的等待或许可以忍受。但代码审查需要连续发送长提示,此时等待首token的时间构成了主要成本。测试使用aiperf 0.12.0,单模型加载、每次运行前重启服务器、并发数为1、8次请求取平均,确保数据可比性。

两模型的加速策略截然不同:Qwen3.8-27B是稠密模型,全部270亿参数参与每个token的计算,依靠MTP头预测后续token并在单次前向中验证;Ornith 1.5采用MoE架构,每token仅激活约30亿参数,配合DFlash让小型草稿模型提议token块再由主模型校验。

**首token时间(TTFT,Time To First Token)**是指从请求发出到模型返回第一个输出token所经历的延迟,通常由提示处理(prefill)阶段主导。与输出速度(tokens/秒)只影响后续生成不同,TTFT决定了用户感知的"响应开始时间"。在代码代理或代码审查这类需要反复提交长上下文提示的交互场景中,每次都从零处理长提示,因此TTFT会随输入长度显著增长,成为体验瓶颈。而输出速度的差异在生成长文本时才会被放大。衡量TTFT时通常需要固定输入长度、并发数和预热状态,否则缓存命中、调度排队等因素会造成较大波动,这也是本文强调单模型加载、每次重启服务器的原因。

**MTP(Multi-Token Prediction,多token预测)**是一种让模型在单次前向传播中预测多个后续token的加速技术,通常在主模型上附加若干轻量预测头,一次生成若干候选token并通过并行验证保留正确结果。它不改变模型本身的输出分布,属于无损加速。DFlash则属于投机解码(speculative decoding)范式:由一个更小更快的草稿模型批量提出候选token块,再由主模型一次前向并行校验,接受匹配的部分、拒绝并重采样不匹配的部分。二者的核心区别在于草稿来源——MTP用主模型自己的预测头,DFlash用独立的小模型,因此DFlash的加速比往往更高,但需要额外加载草稿模型并承担校验失败的开销。这解释了两款模型加速收益的差异。

oMLX升级带来的提升及局限

从oMLX 0.6.4升级到0.7.0后,Qwen3.8-27B在代码提示上的输出速度从57-59 tokens/秒提升至71.7 tokens/秒,散文类内容从46-48提升至55-56。官方发布说明提到了更快的MTP验证和解码,数据吻合。Ornith的变化不大,代码场景维持在103-121 tokens/秒,散文99-102 tokens/秒。

我尝试了调整MTP草稿深度:默认4个token,提升到6时输出速度降至53.9,到8时进一步降至52.4,均低于默认的55.1。自适应控制器本身已选择了最优深度,手动干预没有收益。

代码审查:两者打平

在关闭推理模式的情况下,Qwen3.8-27B在20个植入bug中检出9个,Ornith 1.5检出8个——一个bug的差距在20个样本下属于噪声。测试方法是从四个真实仓库取20个提交,在新增行上翻转一个运算符(如<改为<=,==改为!=,删除not),要求模型单次调用审查diff,不借助工具。每个变异diff配对一个干净diff,只有在变异版中标记问题且干净版中不误报才算通过。

模型推理模式检出不可解析干净diff误报中位耗时
Qwen3.8-27B + MTP关9/204/400.710秒
Ornith 1.5 + DFlash关8/202/401.63秒
Qwen3.8-27B + MTP开6/2012/400.3194秒
Ornith 1.5 + DFlash开8/2013/400.0102秒

开启推理模式后,Qwen检出率反而降至6/20,40个回答中有12个耗尽了12000 token输出上限导致JSON无法解析。Ornith同样存在过度思考问题,13/40回答不可解析,但检出率维持在8/20,耗时约为Qwen的一半。一个需要3分钟且三分之一回答无法解析的审查工具,对任何模型来说都不实用。

内存不足:两模型无法共存

Qwen3.8-27B加载后占用16.1GB,Ornith 1.5占用19.8GB。在64GB机器上看似充裕,但oMLX 0.7.0的内存守卫会拒绝同时加载——投影内存38.24GB超过了34.51GB动态上限,返回507错误。

在0.7.0中,当一个模型空闲时oMLX会驱逐它来加载另一个,日志将卸载标记为立即中止,正在进行的请求会丢失。我意外验证了这一点:Qwen开启推理模式跑审查测试90分钟,同时另一工具持续向Ornith发送请求,oMLX反复加载和驱逐Ornith,最终在Qwen回答中途驱逐了Qwen,40个请求中19个失败。想用两个模型互相做第二意见的方案不可行。

MoE(Mixture of Experts,混合专家)架构将前馈层拆分为多个专家子网络,每个token只路由到其中少数专家,因此"总参数量"与"每token激活参数量"是两个概念。Ornith 1.5 35B-A3B即总参数约350亿、每token激活约30亿,日常计算量接近3B稠密模型,却能保留更大的知识容量。代价是全部专家权重仍需驻留内存,所以它的显存/内存占用(19.8GB)反而高于参数更少但稠密的Qwen3.8-27B(16.1GB)——这正是两者虽计算量悬殊却都无法在64GB机器上共存的根本原因。理解A3B这类命名有助于判断本地部署时的内存预算。

JSON截断问题与约束解码的代价

Qwen3.8-27B在40个审查回答中有5次返回{"findings":[]便停止,缺少闭合括号,仅出现在五六token的空回答上。经排查,MTP关闭和presence penalty为0时同样出现,最多15次运行中4次发生,是模型自身偶尔提前终止。

约束解码可以消除此问题。oMLX通过xgrammar内置支持,但Homebrew安装需显式启用:brew reinstall jundot/omlx/omlx --with-grammar。启用JSON schema后,30个回答中0个无法解析。代价是语法约束与MTP无法同时运行,这类请求退回普通解码,速度降至约25 tokens/秒。

**约束解码(constrained decoding)**通过对每一步的logits施加语法掩码,只允许当前上下文合法的token被采样,从而保证输出严格符合JSON等目标文法。oMLX借助xgrammar实现,能在采样层面杜绝缺括号、缺引号等结构错误。代价主要有两点:一是语法掩码对每一步都要重新计算,带来额外开销;二是语法约束下的逐token依赖会破坏MTP、投机解码等"批量预测后校验"的加速路径,因为这些方法假设被预测token可被自由并行验证。因此启用schema后请求会退回普通自回归解码,速度显著下降。是否启用需在"输出可解析性"与"吞吐速度"之间权衡。

遗留问题与选择建议

Qwen开启推理模式的数据混合了两次运行:21个回答来自有并发流量的早晨,19个失败请求在下午安静环境下重跑。我尚未在单次干净运行中重测全部40个。Qwen的视觉能力也未测试——Ornith量化版不支持视觉,如果Qwen的视觉能与MTP配合,或许可以退役我用于图像的第三个更小模型。Ornith配合DFlash使用JSON schema的代价同样未知。

速度测试也需要更多请求和数千token的提示来验证。我预期首token差距会随长度扩大,但只测了一个尺寸。

目前Ornith留用。如果你在为Mac选择本地模型,先测量你实际发送的提示长度下的首token时间,再去看tokens/秒。

#Qwen3.8#Ornith 1.5#Mac本地推理#oMLX#代码审查#MTP#DFlash#MoE模型
分享:

相关推荐