iPhone 上真能跑 35B 了,可我那把尺子量出来还是同一个答案

cover

Hello,我是飞飞。

刷到一个叫 Swiftlet 的项目,一句话概括:让普通苹果设备跑起 35B 和 80B 的 Qwen。iPhone 上跑 35B,Mac 上跑 80B 只占 4.3 GB 内存。

我第一反应是去翻自己五月那篇。当时我在 iPhone 15 Pro 上装的是 Qwen3.5 的 0.8B,文件 800 多兆。

0.8B 到 35B,四十三倍。

先撇清一下。五月那篇讲的是手机上怎么入门跑小模型,七月二十八号那篇讲的是有人把 K3 塞进 64G 的 Mac、代价是三个字等一分钟,七月十九号那篇讲的是哪类活该搬回本地。这篇跟三篇都挨着,但干的是另一件事:七月底我立过一把尺子,今天拿它量一量这个新东西。

量完的结果有点出乎我意料,也有点在意料之中。

它把货堆在磁盘上

先说它怎么做到的,因为这决定了后面所有的判断。

我去读了 README,核到的规格跟我看到的摘要口径不太一样,得先纠正两处。

4.3 GB 是峰值内存,不是常驻。更要紧的是摘要没提的那个数:80B 那档磁盘要占 42 GB,35B 那档占 18 GB。内存那个数好看,是因为压力挪到了磁盘上。

机制本身挺巧。它把几万个路由专家重新打包成固定步长的块,塞进一个自定义容器里。这么做的好处是,取一个专家正好等于一次 pread,从本地固态硬盘读

拿个画面说。它像一间只有一张工位的作坊。四十二个 G 的料全堆在仓库里,工位上永远只摆着三个 B 那么点东西。每次要用哪个专家,从仓库取一件搬上工位,用完换下一件。

工位小,所以内存占用低。可每件料都得跑一趟仓库,这趟路是省不掉的。

这跟七月底那个把 K3 塞进 M1 Max 的项目是同一个思路,区别在取货的地方。那个是按需从 HuggingFace 拉,每个专家 17.55 MB,慢在网络上。Swiftlet 是从本机固态硬盘读,慢在磁盘和内核上。

我那把尺子量准了

七月底那篇我给自己立了一把尺子,原话是:别看参数量,看激活参数量和你机器的内存带宽。

这次我发现,这把尺子不光准,它的官方版本就写在模型名字里。

Swiftlet 支持的两个模型叫 Qwen3.6-35B-A3B 和 Qwen3-Next-80B-A3B。后面那个 A3B 是什么意思?activated 3B,每个 token 只激活三十亿参数。

80B 是 35B 的两倍出头,激活的却是同一个 3B。

所以那个漂亮的内存数字一点都不神秘。常驻在工位上的本来就只有 3B 那部分,剩下的全在仓库躺着。你按总参数量去估内存,会估错一个数量级;按激活参数量估,一估一个准。

这条我七月底是从 K3 那个案例里逼出来的判断,当时手里只有一个样本。现在又来了一个完全独立的样本,还带着官方命名法的背书。一把尺子被另一个毫不相干的案例验中,它才算真的立住了。

慢这一层纹丝没动

接下来是这篇最要紧的部分。

我七月底那篇的结论是,自托管这条路对我依然关着,而真正拦住我的是速度。当时 K3 那个案例是 14.6 秒吐一个字,跑一篇稿子要十二个小时。

那么这次呢。容量这一关明显松了一大截,速度跟着松了吗?

README 把数给全了,我照抄:

  • 35B 在 M5 Mac 上,解码 7 到 11 tok/s
  • 80B 在 M5 Mac 上,4.5 到 5 tok/s
  • 35B 在 iPhone 17 上,约 1 tok/s

一秒钟一个 token。

我七月底说过自己的放弃线,等超过五秒就烦。1 tok/s 比 14.6 秒一个字快了十几倍,可你要真拿它在手机上写点东西,还是得盯着屏幕一个字一个字地等。

Mac 上那个 7 到 11 才勉强进入能用的区间。我四月用 Ollama 跑 gemma4 的时候是每秒 20 到 40,当时我的评价就是「跟云端一比就是慢」。现在这个数还不到那次的一半,模型大了将近十倍。

所以这一层的答案很清楚。容量那道坎被撬开了,撬开的方式是把代价挪到了时间和磁盘上。四十二个 G 的占用和一秒一个字,就是这次跃迁的标价。

作者自己说了实话

README 里有一句话,我读到的时候愣了一下,觉得这人挺实在。

原文是这么写的:得诚实地把预期摆正,每个 token 只激活约 3B 参数,所以这些模型聊天和写作像大模型,回忆事实却像小模型

这句话的分量比前面所有的数字都重。

它说的是一件很反直觉的事:你在手机上跑起来的那个 35B,写起东西来确实有大模型的样子,句子通顺、逻辑成段。可你要问它一个具体的事实,它的表现更接近一个 3B 的小模型。

因为回忆事实这件事,靠的是被激活的那部分参数里到底存了多少东西。总参数量再大,每次只调动三十亿,能捞出来的就是三十亿的量。

一个模型顶不顶用,看的不在它总共有多少参数,在它每次真正调动的那几个参数扛不扛得起你要它干的活。

我那张欠条还不了

说到这儿,得当面认一件事。

七月十九号我写过一篇,说我那个十三个主题的素材库检索该搬回本地。理由很硬:输入短、任务机械、数据是我自己的。我甚至在五月就查清了方案,本地挂个 Qwen 或者 Gemma,配一个代理,十来分钟能跑起来。

然后到今天也没搬。那篇结尾我把它写成了一张欠条。

所以刚看到 Swiftlet 那会儿,我心里冒出来的念头是:能力抬到这个量级了,这张欠条该还了吧。

读完那句诚实边界,我把这个念头收了回去。

素材库检索是干什么的?是从我十三个主题文件里,把跟这次选题相关的那几条真实经历、具体数字、当时的判断捞出来。这件事的核心动作就是回忆事实。

而这类架构恰恰在这一点上最弱。

所以能力确实抬上来了,抬上来的却不是我这张欠条需要的那一种。这怪不到 Swiftlet 头上。真正没想清楚的是我,我一直没搞明白「我要它干的活到底吃哪种能力」。

这张欠条我还是欠着,但欠的理由从「懒得动手」换成了「我选错了要等的东西」。等一个更大的端侧模型没用,我该等的是激活参数量更大、或者干脆是检索增强那条路。

你先量一下自己的机器

诚实边界摆在这儿:Swiftlet 我没实测过。上面全部来自读机制、读 README 的数据,再拿我自己三次端侧经历去对照。要我改判得等我真在自己机器上跑一遍,看看那个 7 到 11 在我这台上是多少。

给你留个今天就能做的动作,两步。

先查你机器的内存带宽,再拿激活参数量去除一除。别查总参数量,查名字里 A 后面那个数,现在很多模型直接把它写在型号里了。这一除,比翻一晚上教程更能告诉你能跑多大的。

再问自己一句这活吃哪种能力。要它写、要它聊、要它顺一段话,这类模型够用。要它准确记住某个具体的事实、某个数字、某条你三个月前写下的判断,它的水位就是那三十亿。

我五月在手机上跑 0.8B 的时候,判断逻辑是「内存够、模型小,就上最高保真的量化档」。今天回头看,那句话只想清楚了装得下这一层。装得下,跑得动,和干得了你那件活,是三件事。

最后想问问你:你在自己机器上跑本地模型,放弃线划在哪儿?是慢到几秒就受不了,还是压根不在乎速度、只要它别把事实记错?我这两条线是分开的,好奇你的是不是也分开。