其他
在 Apple Silicon Mac 上用…
当需要在 48GB+ 统一内存的 MacBook 上本地运行 Qwen3.5-397B-A17B 等超大 MoE 模型并通过 NVMe SSD 按需流式加载专家权重时使用。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 35/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 40/100 ×0.15
适用场景
在 Apple Silicon Mac 特定
解决思路
- 安装 Xcode Command Line Tools 与 Python 3.x(Python 仅用于权重提取)。
- 克隆仓库:`git clone https://github.com/danveloper/flash-moe`。
- 进入构建目录:`cd flash-moe/metal_infer`。
- 构建全部组件:`make`。
- 验证构建产物:`ls infer chat main`。
- 了解 Makefile 会用 Metal shader compilation 编译 `infer.m`、`chat.m`、`main.m` 与 `shaders.metal`。
- 提取非专家权重:`python3 extract_weights.py /path/to/Qwen3.5-397B-A17B-Instruct/`。
- 确认提取产物:`model_weights.bin`(约 5.5GB,运行时 mmap)、`model_weights.json`、`vocab.bin`、`tokenizer.bin`。
- 打包 4-bit 生产用专家权重:`python3 repack_experts.py /path/to/Qwen3.5-397B-A17B-Instruct/ metal_infer/packed_experts/`。
- 确认 `packed_experts/` 目录约 209GB,每个专家为单独文件 `layer_XX_expert_YYYY.bin`。
- 可选做 2-bit 重新量化:`python3 metal_infer/repack_experts_2bit.py metal_infer/packed_experts/ metal_infer/packed_experts_2bit/`。
- 确认 2-bit 产物为 `packed_experts_2bit/`,约 120GB,比 4-bit 节省约 89GB。
- 运行基础 4-bit 推理:`cd metal_infer` 后执行 `./infer --prompt "Explain quantum computing" --tokens 100`。
- 运行 2-bit 推理:`./infer --prompt "Explain quantum computing" --tokens 100 --2bit`。
- 输出逐层耗时:`./infer --prompt "Hello" --tokens 20 --timing`。
- 启动交互式聊天与 tool calling:`./chat`;它打开 TUI,默认使用 4-bit experts。
- 运行 MoE-only 基准:`./main`;它执行纯 expert forward-pass benchmark,报告不含 attention overhead 的 tokens/sec。
- 按模型结构实现/配置:60 层 transformer,其中 45 层 GatedDeltaNet 线性注意力、15 层标准 full attention;每层 512 experts,每 token 激活 K=4 + 1 个 shared expert;hidden dimension 为 4096。
- 按每层流水线组织执行:CMD3(prev) → CMD1: attention projections + delta-net(GPU)→ CPU flush results → CMD2: o_proj + norm + routing + shared(GPU)→ CPU softmax + topK routing → I/O 并行 pread K=4 experts(SSD)→ CMD3: expert forward + combine + norm(encode, DEFERRED)。
- 实现专家流式加载:每层只从 SSD 读取 top-K=4 激活专家;4-bit 下每个专家约 6.75MB。
- 用 GCD dispatch groups 并行加载专家:创建 `dispatch_group_t` 与 `dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)`。
- 对 `k < K_EXPERTS` 的每个 top-k expert id 用 `dispatch_group_async` 提交到 ioQueue。
- 在 I/O 任务中用 `snprintf` 构造路径 `packed_experts/layer_%02d_expert_%04d.bin`,`open(path, O_RDONLY)`,`pread(fd, expert_buffer[k], expert_size, 0)`,然后 `close(fd)`。
- 用 `dispatch_group_wait(group, DISPATCH_TIME_FOREVER)` 等待所有专家加载完成,再进入 GPU compute。
- 用 `pread()` 而不是 `mmap()` 读取专家文件;依赖 OS page cache 的 LRU,避免 cold data 的 per-page fault overhead。
- GatedDeltaNet recurrence update 使用 Accelerate BLAS,比 scalar 快 64%;每个 head 使用 128×128 float state matrix,共 64 heads。
- 对每个 head 取 state、Q、K、V 指针。
- 用 `cblas_sger(CblasRowMajor, 128, 128, beta[h], k, 1, v, 1, S, 128)` 做 `β·(k⊗v)` 外积更新。
- 用 `cblas_sscal(128 * 128, alpha[h], S, 1)` 做衰减 `S = alpha * S`。
- 用 `cblas_sgemv(CblasRowMajor, CblasNoTrans, 128, 128, 1.0f, S, 128, q, 1, 0.0f, output + h * 128, 1)` 计算 `o = S @ q`。
- 实现 `matvec_4bit_fma` kernel:用 `fma(nibble, scale*x, bias*x)` 替代 naive `(nibble * scale + bias) * x`,并预计算 `scale*x` 与 `bias*x`,把 dequant+multiply 融合到一条 FMA 指令。
- 实现 fused `swiglu` kernel:`gate[gid] = (g / (1.0f + exp(-g))) * up[gid]`。
- 实现 two-pass RMS normalization:`rms_norm_pass1` 做 sum of squares reduction,`rms_norm_pass2` 应用 normalization。
- 实现 GPU RoPE kernel,融合 Q deinterleave 与 K normalization:`rope_qk`。
- 实现 fused MoE combine + residual + sigmoid gate:`moe_combine_residual`。
- 生产默认使用 4-bit:质量优秀、完整 tool calling、JSON 正确、约 4.36 tok/s、磁盘约 209GB。
- 仅在速度测试时使用 2-bit:质量尚可但会破坏 JSON/tool calling(输出反斜杠 name 而不是引号 name),约 5.74 tok/s(warm cache 单 token 峰值约 7.05),磁盘约 120GB,并使用 `F_NOCACHE` 避免 page cache thrashing。
- 遵循硬件原则:Apple Silicon 上 GPU DMA 与 SSD DMA 共用内存控制器,串行 pipeline(GPU → SSD → GPU)是硬件最优。
- 构建失败时执行 `xcode-select --install`,并用 `xcrun -sdk macosx metal --version` 检查 Metal 编译器。
- 排查 OOM:引擎设计为约 6GB active(5.5GB `model_weights.bin` mmap、约 200MB Metal scratch buffers、其余约 42GB 作为专家数据的 OS page cache);用 `sudo memory_pressure` 和 `vm_stat` 检查统一内存占用。
- 排查慢性能:确认 SSD 需要约 17GB/s;运行 `./infer --prompt "Hello" --tokens 5 --timing` 找瓶颈;用 `diskutil info /` 确认 `packed_experts/` 在内置 SSD 而不是外置盘。
- 排查专家目录错误:默认路径为 `metal_infer/packed_experts/`(4-bit)和 `metal_infer/packed_experts_2bit/`(2-bit);确保在 `metal_infer/` 目录运行 `./infer --prompt "test"`。
- 工具调用损坏时改用 4-bit,不要用 2-bit;2-bit 量化会破坏 JSON 输出中的引号。
- 按内存安全要求实现:显式管理所有分配、不设无界缓存、专家数据不累积在 GPU 内存、`model_weights.bin` 只读 mmap 并由内核管理页、专家文件每步 open/read/close。
适用边界 · 注意事项
- 没有 Apple Silicon Mac、48GB+ 统一内存、1TB+ SSD 与约 210GB 可用空间时不要使用。
- 关键工作负载依赖 JSON/工具调用时不要用 2-bit 模式,应使用 4-bit。
- 不要尝试用 mmap、dispatch_io、F_RDADVISE 预取、自定义 Metal LRU 缓存、LZ4 专家压缩、时序专家预测、speculative early routing、MTP speculative decoding、spin-poll GPU wait、并行 SSD+GPU overlap 等优化;在 Apple Silicon 上会因页错误、内存控制器争用或缓存污染而变慢。