阿牛字幕 0.7.1:CPU 核心用的越多,反而越慢,坑填了,聊聊为什么
把推理线程从 10 改成 4,M4 上转写快了 25%。核不是用得越多越好。
一个朋友跟我反馈:他用阿牛字幕,i9-12900HX,跑 Fun-ASR-Nano,只有 1.8 倍速。
我愣了一下。因为我那台 2017 年的 iMac(i5-7500),跑同样的东西是 1.5 倍速。
一颗 2022 年的旗舰移动 CPU——8 个性能核加 8 个能效核——只比一颗九年前的入门四核快 20%?这不对劲。硬件差距一定是被什么东西吃掉了。
0.7.0 就是这个"什么东西"。查完的结论是:问题出在"用几个核"上,而且不是越多越好。
我们从 0.6.0 开始,讲讲这几个版本踩的性能的坑。
一、先把几台机器摆在一起
| CPU | 上市 | 核心构成 | 逻辑线程 | 0.6.x 固定线程 | 0.7.0 逻辑核 | 0.7.1 性能核 |
|---|---|---|---|---|---|---|
| Intel i5-7500 | 2017 | 4 个 P 核(无超线程) | 4 | 4 | 4 | 4 |
| Apple M1 | 2020 | 4 P + 4 E | 8 | 4 | 8 | 4 |
| Intel i9-12900HX | 2022 | 8 P(16 线程)+ 8 E | 24 | 4 | 24 | 8 |
| Apple M4 | 2024 | 4 P + 6 E | 10 | 4 | 10 | 4 |
问题一眼就出来了:i9-12900HX 的 24 个线程里,0.6.x 只用了 4 个——8 个性能核只用了一半,8 个能效核全闲着。
而 i5-7500 一共就 4 个核,用 4 个,正好用满。
于是在软件眼里,这两台机器的算力是一样的(都是 4 线程),差距只剩单核性能。这就是"i9 只快两成"的全部原因,跟 CPU 本身一点关系都没有。
二、原因:FunASR 里写死的那个 4
翻 FunASR 源码,找到这么一行:
# funasr/auto/auto_model.py
def _resolve_ncpu(config, fallback=4):
value = config.get("ncpu", fallback) # ← 不传就是 4
AutoModel 初始化时会执行 torch.set_num_threads(_resolve_ncpu(kwargs, 4))。也就是说:不显式传 ncpu,推理线程就被定死成 4,跟你机器上有几个核毫无关系。
这不算 FunASR 的错——作为通用推理框架,它得假设最差情况,用一个保守数字兜底是合理的。
三、0.7.0 修改就把自己坑了
0.7.0 修法非常直接:检测本机核数,喂给 ncpu。
ncpu = os.cpu_count() # 4 核机器 → 4,24 线程机器 → 24
很自然对吧?核多线程多,跑得快。我甚至把它写进了 0.7.0 的发布说明:「推理线程数自适应,不再固定 4 核,改为按本机 CPU 核数设置。核多的机器,转写更快。」
这句话说对了一半,也埋了一个坑。
写完之后读文档时,被 AI 提醒了一句:用所有核心,可能不是个好策略。
当时没有在意,直到遇到尊贵的 i9-12900HX 和我 9 年前的 i5 性能差不多,才意识到,这个提醒,可能比想象的严重。
于是,重新回到核心问题,测试。
四、实测:线程数超过物理核,反而更慢
拿本机那台 4 核 i5-7500,同一段 8 秒音频、同一个模型,只改推理线程数,每档跑 5 次取中位数:
| 线程数 | 墙钟耗时 | 相对 1 线程 |
|---|---|---|
| 1 | 1.073s | 1.00x |
| 2 | 0.658s | 1.63x |
| 3 | 0.505s | 2.12x |
| 4 | 0.443s | 2.42x |
两个信号:
- 4 个核只换来 2.42 倍。 每加一个核,收益都在衰减——第 4 个核只贡献了 +14%;
- 累计 CPU 时间从单线程的 1.02 秒涨到 1.48 秒,+45%。多线程本身是有成本的。
接着把线程数开到物理核数以上(4 核开 5/6/8 线程,相当于往每个核里塞一个半到两个线程):
| 线程数 | 超订倍数 | 墙钟耗时 | 相对 4 线程 |
|---|---|---|---|
| 4 | 1.0x | 0.429s | — |
| 5 | 1.25x | 0.573s | -25% |
| 6 | 1.5x | 0.546s | -22% |
| 8 | 2.0x | 0.511s | -16% |
只多开一个线程,就慢了 25%。 一台 4 核机器上就已经这么敏感了,24 线程的 i9 上会怎样,可想而知。
为什么会这样
推理框架里的算子(矩阵乘、归一化、激活……)是分片并行 + barrier 同步的:一个算子按线程数切成 N 份,每个线程算一份,算完在 barrier 上等齐,才能进下一个算子。
于是有这么一条:
一个算子要多久,不取决于大家平均多快,取决于最慢的那一片有多慢。
线程数超过真实算力之后,多出来的线程拿不到执行单元,却还是被分了一份活。它算得慢,所有人就得等它。并行度越高,这个"拖后腿"的效应越明显。
超线程和 E 核,是同一个问题的两个版本
- 超线程:两个逻辑线程共享同一套物理执行单元(尤其是浮点/向量单元)。矩阵乘这类密集计算根本拿不到 2 倍,通常只有 0 ~ 15%,甚至负收益。
- E 核(能效核):它是货真价实的核,但单核吞吐只有 P 核的 1/3 ~ 1/2。放进同一个 barrier 里,它就成了那个"最慢的分片"。
所以在大小核机器上,"用满逻辑核"是双重踩坑:先被超线程稀释一遍,再被 E 核拖一遍。
M4 上的验证:10 线程 → 4 线程,快 25%
最后在一台 M4(4 个 P 核 + 6 个 E 核,10 个逻辑核)上做了严格 A/B:
- A:用满 10 线程(4 个 P 核 + 6 个 E 核)
- B:只用 4 个 P 核
同一台机器、同一个视频、同一个模型,4 线程比 10 线程快 25%。
这也说明了 0.7.0 在大小核机器上是倒退的:它把线程数从 4 改成了 10(M4)、24(i9-12900HX),方向完全反了。
五、0.7.1 的做法:找"性能核",而不是"核"
结论很清楚:要的是性能核的数量,不是核的数量。
0.7.1 按平台分别探测:
| 平台 | 取法 | 例子 |
|---|---|---|
| macOS(Apple Silicon) | sysctl 读 hw.perflevel0.logicalcpu(性能核) |
M4 → 4 |
| macOS(Intel) | sysctl 读 hw.physicalcpu(没有大小核之分;physicalcpu 是物理核数,已排除超线程) |
i5-7500 → 4 |
| Linux | 按 cpufreq/cpuinfo_max_freq 只数最高频那一档(P 核),并用 core_cpus_list 排掉超线程 |
8P + 8E → 8 |
| Windows | 调 GetLogicalProcessorInformationEx,按 EfficiencyClass 只数性能核 |
i9-12900HX → 8 |
三条原则:
- 不设上限。 机器上有多少性能核就用多少——M4 给 4,M2 Pro 及以上给 6、8、10……不人为截断。
- 探测失败就退回 4。 和 FunASR 原本的兜底一致。宁可保守,不赌。
- 加一道合理性校验。 性能核数不可能超过逻辑核数,超过就判定为解析异常、直接走兜底——避免识别出错时把线程数设成离谱的值。
六、哪些机器会变快,哪些没变化
先把话说明白,免得升级之后觉得"没感觉":
| 机器 | 变化 |
|---|---|
| i9-12900HX 这类 8 个 P 核的 | 4 → 8 线程,8 个性能核全部用上 |
| M2 Pro / M4 Pro 这类性能核多于 4 个的 | 4 → 全部性能核(6 个、8 个、10 个……) |
| M1 / M4 / i5-7500 这类性能核正好 4 个的 | 和 0.7.0 一样是 4,感受不到区别 |
| 没有超线程、没有 E 核的老机器 | 无变化 |
换句话说:0.7.1 修的是 0.7.0 在大小核机器上踩的坑,普通四核机器不受影响。
具体能快多少,取决于你的 CPU 和视频内容。我们只在 M4 上做了严格的 A/B 对比(+25%);i9-12900HX 那台机器是把"只用一半 P 核"变成"全部用上",方向明确,但数值得等更多机器反馈。
七、顺带:逐字时间戳不是元凶
0.7.0 刚加了逐字时间戳(SenseVoice 走 CTC 强制对齐),我一度怀疑是它拖慢了转写。顺手量了一下:整片只多 5% ~ 7%,其中最大的一笔是 FunASR 内部对同一份 encoder 输出重复算了一次大矩阵投影(每段约 30ms)。
它够不上主要矛盾,所以 0.7.1 没动它。真正吃掉性能的,从头到尾都是线程数。
升级说明
- 建议直接下载覆盖安装。FunASR、Python 运行时依旧全部随包内置,无需手动安装依赖
- 本次只改了推理线程数的取法,转写结果结构没有任何变化,缓存全部保留,旧文件不需要重新转写
- 如果你的 CPU 性能核多于 4 个(i9 / i7 的 HX、H 系列,M2 Pro 及以上),升级后转写会明显更快;四核机器表现不变
写在最后
这个坑让我记住一件事:"把资源用满"不是优化,是本能。 真正的优化得先弄清楚资源到底是怎么被用掉的——超线程不是免费的加倍,"核心数"这个词在大小核时代也已经不准确了。
那颗 i9-12900HX 的 1.8 倍速,最后不是硬件不够,是软件没让它上场。
免费使用,本地运行,下载即用。
👉 官网下载体验:https://thinking.vip/a-niu-subtitle
阿牛字幕 生成字幕,粗剪视频

