MacBook运行Qwen3.5-397B
CVS Health的AI副总裁构建了一个7000行C语言推理引擎,在MacBook Pro上运行Qwen3.5-397B。
微信 ezpoda免费咨询:AI编程 | AI模型微调| AI私有化部署
AI工具导航 | ONNX模型库 | Tripo 3D | Meshy AI | ElevenLabs | KlingAI | ArtSpace | Phot.AI | InVideo
CVS Health的AI副总裁构建了一个7000行C语言推理引擎,在MacBook Pro上运行Qwen3.5-397B。模型大小为209GB。笔记本有48GB内存。它以每秒4.4个token的速度运行,支持完整工具调用。
没有Python。没有PyTorch。没有框架。只有原始C、Objective-C和手工调优的Metal着色器。
Dan Woods将Flash-MoE构建为一个副项目,使用Claude Code作为他的编程伙伴,并使用Andrej Karpathy的autoresearch模式运行了90多次优化实验。代码在github.com/danveloper/flash-moe公开。有人已经将其fork到iPhone 17 Pro上运行。
这不应该成为可能。以下是它的工作原理。
1、秘诀:3970亿参数中的大部分都在沉睡
Qwen3.5-397B-A17B是一个混合专家模型。名称中的"A17B"是关键。在总计3970亿参数中,每个token只激活170亿参数。其余都处于休眠状态。
架构:60层Transformer,采用混合设计。45层使用GatedDeltaNet(线性注意力机制),15层使用标准全注意力。每层有512个专家。默认配置为每个token激活其中10个专家,加上一个共享专家。
2、为什么GatedDeltaNet对此很重要
标准注意力构建完整的token-by-token注意力矩阵。GatedDeltaNet不这样做。它使用delta规则维护一个运行状态矩阵:新值和预测值之间的差异修改持久内存状态。核心递推公式:
M_t = α_t * M_{t-1} * (I - k_t * q_t^T) + k_t * q_t^T
α是衰减门(内存遗忘速度)。Delta规则处理擦除和关联更新。紧凑,但它编码了层需要记住的一切。
为什么这对Flash-MoE很重要?
GatedDeltaNet以固定大小的状态(64个头,每个维护128x128矩阵)顺序处理token,而不是关注完整上下文。这意味着内存成本不会像标准注意力那样随上下文长度增长。对于已经受SSD流限制的内存模型,这就是"能工作"和"装不下"的区别。Qwen3.5-397B将60层中的45层分配给GatedDeltaNet,仅15层给全注意力,保持注意力内存预算可管理。
完整模型规格:隐藏维度4096,词汇量248320,原生上下文262K token(通过YaRN RoPE缩放可扩展到1,010,000),通过早期融合多模态token实现视觉语言能力。
3、K=4的发现
Dan Woods发现他可以在不降低质量的情况下将专家激活从K=10减少到K=4。但K=3会导致立即崩溃。这个尖锐的阈值很有趣。它表明路由网络学会了将关键推理集中在特定的专家组中,而不是均匀分布在全部10个中。四个专家捕获了基本计算。三个不够。边界很薄。
从10减少到4个专家将每token内存访问减少约67%。因为每层一次只需要4个专家在内存中(每个约6.75 MB),总实时内存占用降至约5.5 GB。其他203GB的专家权重?它们留在SSD上直到需要。
这是使其他一切成为可能的洞察。397B参数模型听起来需要GPU集群。170亿活跃参数模型加选择性加载听起来可能适合笔记本。确实如此。
4、蓝图:苹果的"LLM in a Flash"
Flash-MoE并非凭空而来。架构基础是苹果2023年12月的研究论文《LLM in a Flash:在有限内存下高效的大型语言模型推理》。
苹果解决了一个具体问题:如何运行比可用内存更大的LLM?他们的答案:将权重存储在闪存中,并在需要时带入DRAM。论文引入了Flash-MoE直接构建的两种技术。
窗口化通过重用先前激活的神经元来减少数据传输。如果神经元为前一个token加载且再次需要,不要重新加载。
行列捆绑重构权重读取以匹配闪存对顺序访问的偏好,增加每次读取操作的大小以最大化每IO操作的吞吐量。
MoE模型有一个特性:LLM中的FFN层具有高稀疏性。许多值在激活后变为零或接近零。对于密集模型,你可以利用这一点跳过一些加载。对于具有512个专家的MoE模型,每个token只激活4个,稀疏性是结构性的,而不仅仅是数值性的。99.2%的专家权重在任何给定token上都不使用。
苹果的论文报告与朴素加载相比,CPU速度提升4-5倍,GPU提升20-25倍,使模型大小可达可用DRAM的两倍。Dan采用了这个蓝图并将其专门应用于Apple Silicon上的MoE专家流,使用手工调优的Metal内核,将比率从2倍推到超过4倍(48GB RAM上的209GB模型)。
5、SSD流:模型驻留在磁盘上
209GB的4位量化专家权重位于MacBook的NVMe SSD上。当token需要处理时,Flash-MoE通过GCD(Grand Central Dispatch)发出并行pread()调用来加载该层的4个活跃专家。每个专家约6.75 MB。以测量的17.5 GB/s顺序读取SSD带宽,加载4个专家每层约需2.4毫秒。
关于SSD速度的背景:17.5 GB/s是Apple的定制存储控制器通过Apple Fabric互连提供的速度。x86机器上的标准NVMe SSD在最快的PCIe 5.0驱动器上最高达7 GB/s。Apple Silicon的存储控制器直接集成到SoC中,与CPU、GPU和神经引擎共享相同的内存结构。这种紧密集成是为什么流方法在这里有效而在典型PC上无效的原因。
非专家权重(嵌入、注意力投影、路由矩阵、归一化参数)总计5.5 GB,通过mmap以只读映射方式驻留在内存中。Metal暂存缓冲区增加约200 MB。推理期间的总内存分配:约6 GB,为OS及其页缓存留下42 GB空闲。
6、页缓存发现
页缓存被证明是最重要的优化,而且是偶然发现的。macOS自动将最近读取的SSD页面缓存在RAM中。Flash-MoE没有实现任何自定义缓存逻辑。
Dan尝试了所有替代方案。9.8 GB Metal LRU缓存。两个基于malloc的缓存(2581条目18GB,命中率52%;500条目3.5GB,命中率37%)。LZ4压缩将209GB压缩到175GB,但增加了解压缩开销。
所有这些都表现更差。Metal LRU因产生GPU内存压力而损失38%速度。即使容量更高,malloc缓存也无法击败OS,因为它们与页缓存竞争相同的RAM。LZ4压缩节省了磁盘读取,但CPU解压时间慢于以17.5 GB/s从SSD读取未压缩数据。
OS页缓存,不做任何聪明事,通过利用专家访问模式中的自然空间局部性实现71%命中率。同一会话中的token倾向于通过类似的专家路由。OS注意到重复读取并保持这些页面热。71%命中率意味着71%的专家加载以~400 GB/s带宽来自RAM,而不是以17.5 GB/s来自SSD。这是真正的速度倍增器。
Dan将其记录为"信任OS"原则。macOS内核在其VM子系统背后有数十年的工程。试图用应用级缓存在这个硬件上智胜它是必输的游戏。
7、58次失败实验
除了缓存之外,Dan运行了58次有记录的优化实验。许多使情况更糟:
- F_RDADVISE预取: 净收益0%。SSD DMA争用使GPU减慢73%,抵消任何预取收益。
- 时间专家预测: -18%。预测下一个token需要哪些专家并预加载它们。预测准确率不够高,不值得在错误猜测上浪费带宽。
- MLP路由预测器: 构建一个小神经网络预测专家路由。达到31%准确率,低于简单启发式的53%,运行预测器的推理开销消耗了任何收益。
- 推测性早期路由: 53%预测准确率,但错误预测的缓存污染和路由开销使其总体慢38%。
- GPU LUT反量化: -2%。反量化查找表未能击败FMA方法。
- GPU缓冲区压缩: -20%。Metal的缓冲区压缩增加延迟。
- 自旋轮询等待: -23%。忙等待GPU完成消耗OS用于页缓存管理的CPU周期。
- 直接mmap专家文件: 灾难性5倍退化。每页错误比
pread()慢100倍,对于未缓存的7MB专家块。 - 推测解码: MoE上持平。每token IO成本随推测token线性扩展,所以提前起草4个token需要4倍的专家加载。无净收益。
- LZ4压缩: -13%。从209GB压缩到175GB,但热缓存读取的解压开销慢于原始SSD读取。
Dan不断重新发现的教训:在Apple Silicon上,SSD DMA和GPU计算共享相同的统一内存控制器。它们无法有利地重叠。即使最少的后台SSD IO也会通过内存控制器仲裁造成不成比例的GPU延迟峰值。GPU反量化内核已经在~418 GiB/s处饱和。任何竞争同一总线的SSD DMA流量导致的减速远大于单独数据传输所暗示的。
最佳流水线是串行的:GPU计算完成,然后SSD读取开始,然后GPU再次计算。与这个硬件约束对抗每次都使情况更糟。
8、Metal内核
Flash-MoE的性能来自1200行手工调优的Metal着色器。每个可以融合的操作都融合了。每个可以消除的中间缓冲区写入都消除了。
4位反量化矩阵向量乘法
核心计算内核。为缓存局部性分块,跨线程组SIMD缩减,共享输入缓存以避免冗余内存读取。
反量化步骤从朴素形式(nibble * scale + bias) * x重构为FMA形式:fma(nibble, scale*x, bias*x)。预计算scale * x和bias * x一次并在组中所有nibble上重用,将反量化+乘加折叠为单个融合乘加指令。这种代数重排带来12%速度提升,因为它直接映射到GPU的FMA硬件单元,使它们在~418 GiB/s处饱和。
这是实际有效的优化之一(与使情况更糟的十个不同)。2位变体使用相同的内核结构,但具有更窄的nibble提取。
融合SwiGLU和RMS归一化
两个操作,一个内核分派。SwiGLU激活(Qwen MLP块中使用的门控机制)和RMS归一化(层归一变体)作为单次Metal计算通道中的两遍缩减运行。它们之间没有中间缓冲区写入。每个本应写入设备内存并读回的字节都被消除。
GPU RoPE(旋转位置嵌入)
token旋转的内核融合。不是作为单独操作运行,RoPE计算融合到注意力矩阵构建中,在S4复杂旋转期间直接写入Q/K缓存。额外的内存遍历消除。
层间专家并行
GPU处理第N层时,CPU通过GCD预加载第N+1层的专家。这种CPU/GPU流水线重叠隐藏SSD延迟,但仅适用于已预热到OS页缓存的权重。对于冷启动或上下文切换,GPU等待。
GCD异步预读
使用dispatch_io_read与DISPATCH_IO_RANDOM提示通过Apple的GCD进行真正的异步专家加载。这比其他线程方法实现了更好的SSD吞吐量和CPU效率,让OS管理页缓存的复杂性。
缓存旁路用于注意力
GPU上的标准矩阵乘法通过Metal的纹理单元运行。这些单元有缓存,在全注意力的因果掩码层中,缓存命中失败很昂贵。Flash-MoE使用device地址空间和显式缓存控制绕过纹理单元缓存,实现缓存行大小的直接内存访问。
量化和布局优化
4位权重以64元素交错块布局存储。这最大化突发读取效率,并允许反量化内核从共享内存一次加载64个值。布局与GPU的内存访问模式匹配,实现接近理论峰值的带宽利用率。
9、架构的本质
Flash-MoE不是优化单个内核。它是设计一个在Apple Silicon特定约束下工作的系统:统一内存、SSD瓶颈、GPU限制。
关键洞察:瓶颈不是计算。具有Metal内核的M3 Max GPU可以轻松每秒处理数千个token。瓶颈是内存。209GB模型无法装入48GB RAM。因此架构围绕使SSD带宽尽可能有效而设计。
苹果"LLM in a Flash"论文中的窗口化和行列捆绑技术提供了一个起点。Dan添加了专家特定优化:积极卸载、选择性激活、依赖token重要性的自适应精度。结果是系统在约束下工作,而不是与之对抗。
状态: 运行。每秒4.4个token。工具调用。本地。无云。
原文链接: A 397B Model Running on a MacBook. 48 GB of RAM. No Cloud
汇智网翻译整理,转载请标明出处