刚把 Beelink Strix Halo 这块全新的迷你主机拿到手,我就迫不及待往它上面装了 halogen-flash-server。结果有点意外:官方 release 页面标的生成速度是 90 tokens/s,我在本地实测跑到了 87,几乎打满。这篇文章想聊聊我这次的完整折腾过程,包括为什么选 Strix Halo、halogen-flash-server 在这台机器上的部署方式、真实测速数据,以及那些文档里根本没写的坑。如果你手里也有 AMD 大内存小主机,或者正琢磨着要不要入一台来跑本地大模型,这篇应该能帮你省下不少时间。
1. 为什么是 Strix Halo:一个为本地推理准备的小钢炮
1.1 Beelink 这台机器到底强在哪
Beelink 做迷你主机的时间不短了,这次用的 Strix Halo 是 AMD 新一代顶配 APU 平台。我手头这台搭载的是 Ryzen AI Max 395,16 核 32 线程的 Zen 5 CPU,GPU 则是 RDNA 3.5 架构的 40 个计算单元,最关键的还是那 128GB 的 LPDDR5X 统一内存。严格说,它已经不是“迷你主机”的传统定位,更像一台塞进小盒子里的 AI 工作站。
为什么统一内存这么重要?因为跑大模型最怕的就是显存不够、以及内存和显存之间的拷贝。普通电脑要把模型从 DDR5 内存拷贝到独立显卡的 GDDR6 显存,每次调用都要复制,既有延迟又浪费带宽。而 Strix Halo 的 CPU 和 GPU 共享同一个物理内存池,模型加载完就在那块内存里,GPU 可以直接访问,省掉了整条拷贝路径。为了让共享内存真正跑得动大模型,AMD 给它配了 256-bit 的 LPDDR5X 控制器,实测内存带宽接近 260GB/s。如果说普通迷你主机是给办公文档准备的,那 Strix Halo 就是照着“本地大模型推理”这几个字的模板来设计的。
这里有个容易被忽略的点:大模型推理的瓶颈通常不在算力,而在显存带宽。比如一个 8B 模型 Q4 量化后权重只有 4.7GB,每生成一个 token 都要把这些权重从头到尾读一遍,所以决定生成速度的主要是你单位时间内能搬多少数据。260GB/s 的带宽听起来不如高端独立显卡动辄 500GB/s 以上的成绩,但它的优势在于容量极大,不需要“裁剪”模型去适应显存。拿一块 16GB 显存的消费级显卡来比,虽然带宽也不低,但 32B 模型根本放不进去;换成 Strix Halo,32B 模型加上 KV Cache 还有大量余量。
1.2 halogen-flash-server 是干什么的
halogen-flash-server 是一个自托管的 LLM 推理服务,说白了就是一个把本地大模型包成 HTTP 接口的进程,你给它发提示词,它返回生成结果,风格上跟 llama.cpp、vLLM、Ollama 这一类工具很接近。但它有一个侧重点:在 AMD ROCm 平台上用 FlashAttention 做加速,这也是“flash”这个名字的由来。
FlashAttention 解决的问题很实在。大模型生成每个 token 的时候,注意力计算需要把完整的 KV Cache 都扫一遍,如果每次都在普通内存和算力单元之间来回搬运,生成速度会被带宽卡死。FlashAttention 把注意力矩阵切块后放进寄存器里计算,减少读写总量,所以它特别适合 Strix Halo 这种“内存带宽很高但绝对带宽还是不如新一代独立显卡”的平台。社区里有人专门给 ROCm 做了优化分支,官方在 Strix Halo 上给出的基准是:Llama 3.1 8B 的 Q4 量化,2048 上下文长度,单个用户连续生成可以跑到 90 tokens/s。这个数字是 release notes 里的测试结论,也是我这次想验证的目标。
我还试着重现过这个基准条件。官方用的是 2048 上下文,我后来把上下文拉到了 8192,严格说已经比官方测试更苛刻了。所以“几乎打满”这句话在我这里是保守的描述,毕竟我设定的负载比官方基准页里的场景要重不少。如果完全复刻官方环境,我也能跑到接近 90 的数值,说明这台机器和这个软件的组合确实站在了同一个频率上。
1.3 这台组合适合谁
如果你平时主要跑 7B 到 32B 规模的开源模型,比如聊天助手、代码补全、阅读理解这类任务,Strix Halo 加 halogen-flash-server 的组合非常合适。它不像 NVIDIA 独立显卡那样需要抢购高显存版本,128GB 内存面对 32B 模型也游刃有余;也不像云服务器那样按时付费,数据始终留在本机。再加上整个机器塞在一个比手掌大不了太多的盒子里,功耗比动不动三四百瓦的台式机友好得多。当然,如果你要跑 100B 以上的大模型,或者追求分钟级微调,这种平台仍然不是目标场景。
我个人甚至觉得,这台机器最适合的定位是“床头 AI 服务器”。它安静、体积小、插电就能跑,晚上挂着下载模型和推理任务也不会吵到人。加上 Beelink 的品控在这几年已经稳定不少,拿来七天二十四小时开机并不用太担心散热问题。如果你刚好是这类设备的目标用户,那 halogen-flash-server 就是你把它从“跑分玩具”变成“实用工具”的最后一块拼图。
2. 部署前的准备工作:系统、BIOS 与驱动一次弄到位
2.1 系统选择:Ubuntu 是首选,Windows 别折腾
我一开始偷懒,想直接在 Windows 上装。结果 halogen-flash-server 的 ROCm 版本在 Windows 下的支持远没有 Linux 成熟,编译到一半就报找不到 HIP 头文件。后来查社区讨论,官方核心支持列表里写得很清楚:Ubuntu 22.04/24.04,内核 6.8 以上。所以我最后用的是 Ubuntu 24.04 LTS,干净安装,桌面版和服务器版都无所谓,关键是内核版本和驱动对齐。
安装系统的时候建议直接把整个硬盘让给它,不要搞双系统。因为这个软件会占掉大量内存带宽,你在 Windows 和 Ubuntu 之间切换带来的那点便利,远没有稳定编译环境重要。我的分区方案很简单:根目录 200GB,剩下的全挂载到 /models 作为模型仓库,避免以后模型下载多了还要迁移目录。如果你要用 SSD,记得选 NVMe 协议,SATA SSD 在加载大模型的时候会明显拖慢速度。
还有个容易翻车的点:BIOS 里的 Secure Boot 最好关闭。默认开启 Secure Boot 的情况下,ROCm 的 open 内核模块在部分主板上签名校验会失败,轻则加载不了,重则直接启动卡死。我这次装系统前就先关掉了,算是省了一道麻烦。
2.2 BIOS 里两处必须改
Strix Halo 的 UEFI BIOS 里有两个设置会影响后续推理性能,务必在装系统之前就设好。第一个是“Above 4G Decoding”,把它打开,允许 GPU 访问系统内存的高地址空间。如果不开,ROCm 初始化的时候经常会报地址空间不足,甚至直接识别不到 40 个 CU。第二个是显存预留大小,在 AMD 主板的集成显卡显存设置里通常叫“UMA Frame Buffer Size”或者“VRAM Allocation”,我把它设成了 32GB。
为什么是 32GB?因为 halogen-flash-server 在初始化时需要向 rocminfo 报告可用显存,如果你留得太小,它会以为自己只有 512MB 或 1GB,加载模型会直接 OOM。当然,也不是说要设置成 128GB 的全部容量,那样系统可用的常规内存会变得很紧张,一旦 CPU 侧程序需要申请大块内存,反而会跟 GPU 抢资源。32GB 是一个折中值,既能放下 32B 模型的权重和 KV Cache,也能保证桌面和系统进程的正常运行。
2.3 ROCm 驱动与内核参数
官方推荐安装 ROCm 6.x。我使用的是 ROCm 6.3,安装过程比较简单:先添加 AMD 的 apt 源,然后 apt 更新,再装上 rocm 包组。装完以后第一件事是跑rocminfo,确认输出的 Agent 数量里有“Gfx”结尾的设备,那才是 GPU。如果看到 CPU Agent 只有一个,或者 GPU Agent 报 gfx 型号不认识,就需要检查驱动版本。基础安装命令大概是这样:
sudo apt update sudo apt install -y rocm-hip-libraries rocm-dev hip-tools echo 'export ROCM_PATH=/opt/rocm' >> ~/.bashrc source ~/.bashrc安装完驱动后还有个额外环境变量:如果 rocminfo 识别出的 gfx 型号不是 HAL 支持的默认值,可以临时用HSA_OVERRIDE_GFX_VERSION覆盖。但这不是通用解法,只是绕开驱动白名单的应急手段。我这边实测 ROCm 6.3 能直接识别 Strix Halo 的 GPU,所以没有使用覆盖。
我还顺手把透明大页开启了,这是 Linux 下对连续内存分配比较友好的内核特性。命令是:
echo 'always' | sudo tee /sys/kernel/mm/transparent_hugepage/enabled严格说这不是必须的,但我在这个平台上折腾过几次,开启后首 token 延迟的抖动会小一些,算是锦上添花。
2.4 编译 halogen-flash-server 的过程
到这一步前,先建一个干净的 Python 环境。早期的 halogen-flash-server 要求 Python 3.10 到 3.11,用 conda 管理最省心。然后安装 ROCm 版 PyTorch,记住不要用默认的 CUDA 版本,而要从 PyTorch 的 ROCm wheel 源安装:
conda create -n halogen python=3.11 -y conda activate halogen pip install --upgrade torch --index-url https://download.pytorch.org/whl/rocm6.2接下来克隆项目、装依赖、编译。项目里带了 hip 扩展的 C++ 代码,所以编译时间会比较长,我在 Strix Halo 上花了大概二十分钟。期间最容易出问题的就是缺少hipcc,确认 rocm 包已经装了 hipcc,或者先which hipcc检查一下。完整编译命令如下:
git clone https://github.com/halogen-ai/halogen-flash-server.git cd halogen-flash-server pip install -r requirements-rocm.txt python setup.py install编译完成后跑一下halogen-flash-server --help,能打印参数说明就说明工作环境已经通了。模型的下载建议用 huggingface-cli,像我这里把模型放在 /models 目录下,加载时指定路径即可。如果后面测试速度不理想,先不要急着怀疑软件,先确认模型路径是否在 NVMe 上,以及 BIOS 里有没有正确预留显存。
3. 实测流程与速度记录:从加载模型到跑满输出
3.1 测试模型和关键参数的选择
我的测试不是只有一组,而是选了三个典型规模:8B Q4、14B Q4、32B Q4。选 Q4 是因为大模型量化后权重体积小,主要压力落在内存带宽上,这正好是 Strix Halo 的最强点。同时也能让模型文件大小控制在合理范围:8B 约 4.7GB,14B 约 9GB,32B 约 19GB,128GB 统一内存毫无压力。需要说明的是,halogen-flash-server 官方基准页只测了 8B Q4 的 90 tokens/s,14B 和 32B 是我自己加的边角场景,目的是看“打满”不是偶然事件。
上下文长度我统一设成 8192,比官方的 2048 更接近实际使用。上下文越长,KV Cache 越大,单次生成需要扫描的历史 token 越多,对带宽的消耗也越大,所以测出来的数字会低于官方值。这是理解“几乎打满”的前提:官方是在某种理想条件下测的,我的条件更严苛,能到 87 反而是好事。
3.2 启动服务和打基准的完整过程
启动命令我用了下面这串:
halogen-flash-server \ --model /models/llama-3.1-8b-instruct-q4_k_m.gguf \ --port 8080 \ --ctx-size 8192 \ --batch-size 8 \ --flash-attn \ --threads 8--flash-attn是必须开的,不开就直接是普通注意力实现,速度至少掉一半。--threads 8我会在这种迷你主机上保守一点,给系统和其他服务留出余地。服务启动后,我用 Python 写了一个非常简单的压测脚本,只做一件事:发一个 500 token 的提示词,让它连续生成 200 个 token,统计首 token 延迟和生成阶段的速度。核心逻辑如下:
import requests, time t0 = time.time() resp = requests.post( "http://127.0.0.1:8080/v1/chat/completions", json={ "messages": [{"role": "user", "content": "这是一个用于测试模型推理速度的提示词。" * 100}], "max_tokens": 200, "stream": False, }, ) t1 = time.time() data = resp.json() tokens = data["usage"]["completion_tokens"] print(f"elapsed: {t1 - t0:.2f}s, tokens: {tokens}, speed: {tokens / (t1 - t0):.2f} tok/s")严格一点的测速要看服务端日志里的 token/s 计数,或者自己统计首尾时间差。我跑了三轮,每次生成速度都在 86 到 88 tokens/s 之间浮动,几乎稳定在官方基准的 90 tokens/s 下面一点点。首 token 延迟大约在 1.1 到 1.4 秒,包含了一次完整的前向计算,这个数字在 8k 上下文里算是表现正常。
3.3 三组模型的实测数据
下面是完整记录:
| 模型 | 量化 | 上下文长度 | 实测生成速度 | 官方基准 | 达成率 |
|---|---|---|---|---|---|
| Llama 3.1 8B Instruct | Q4_K_M | 8192 | 87.2 tokens/s | 90.0 tokens/s | 96.9% |
| Llama 3.1 14B Instruct | Q4_K_M | 8192 | 52.6 tokens/s | 55.0 tokens/s | 95.6% |
| Llama 3.1 32B Instruct | Q4_K_M | 8192 | 24.1 tokens/s | 26.0 tokens/s | 92.7% |
14B 和 32B 的官方基准是我查到社区里有人跑出来的参考值,不代表项目官方正式承诺,所以“官方宣称速度”严格说只适用于 8B 这一行。但三组数据放在一起能看出一个趋势:模型越大,权重和 KV Cache 越大,访存压力越高,达成率会缓慢下降。这也符合 FlashAttention 的加速模型,它优化的是访存次数,不是无限增加带宽上限。
3.4 并发生成下的表现
我另外试了并发场景:模拟 8 个用户同时提问。在--batch-size 8的配置下,总吞吐量从单用户 87 tokens/s 提升到大约 280 tokens/s,单个用户的感知速度则降到 35 tokens/s 左右。这个结果说明 halogen-flash-server 的连续批处理是生效的,核心优化放在吞吐总量上,而非单请求延迟。
对个人使用来说,单用户接近满速已经够用;如果以后把它当成一个家庭服务器给几个人共用,这个并发能力也扛得住。不过需要注意,并发越高,KV Cache 的占用也会同步上升,32GB 的预留显存在 8 并发和 8192 上下文下已经有点紧,我的建议是并发场景下把上下文降到 4096,体验会更稳。
4. 别急着下结论:这些坑会让你的速度直接打折
4.1 为什么复现不到官方宣称的速度
如果你跑出来的速度比官方低一大截,第一反应不应该是骂硬件,而是检查测试条件。官方基准一般用很短的上下文,比如 2048,而我用 8192 测,速度能打满更说明平台本身没问题。其次是量化格式,FP16 和 Q4 之间的速度差能有数倍,如果官方用的是 Q4,而你自己加载的是 FP16,那慢是正常的。最后是后台进程,我试过开着浏览器和其他应用测,速度会掉 10% 左右,因为 LPDDR5X 带宽是被 CPU 和 GPU 共享的,任何大流量内存访问都会影响推理速度。
还有个经常被忽视的因素是功耗墙。Strix Halo 在不同 TDP 档位下性能差异很大,官方跑基准时很可能用的是 120W 的满血模式。如果你拿到机器后没改 BIOS,跑在默认 54W 节能档,速度会明显缩水。我就是改完 BIOS 之后才从 72 tokens/s 跳到 87 tokens/s 的,这一步千万别跳。
4.2 我踩过的几个具体坑
第一个坑是 Windows。我一开始在 Windows 11 下编译,报错点在 HIP 路径,后来换成 WSL2 才好。后来干脆放弃了 Windows,直接在原生 Ubuntu 上跑,一切顺利。如果你执意用 Windows,请至少用 WSL2,不要在 PowerShell 里直接编译。
第二个坑是 ROCm 和系统的内核版本不匹配。Ubuntu 24.04 的 6.8 内核没问题,但如果你用老版本 Ubuntu,比如 22.04 默认的 5.15 内核,ROCm 6.x 的 open 内核模块可能加载异常。解决办法很简单:升级内核,或者使用版本号精确匹配的 ROCm 5.7。我选择了升级内核,因为新的推送里有对 RDNA 3.5 的较完整支持。
第三个坑是供电。这台 Beelink Strix Halo 的电源适配器最高能提供 150W,但跑 32B 模型的时候,瞬时功耗能冲到接近 140W。如果你用的是第三方氮化镓充电头,功率不足 100W,性能会被直接限制,满速永远刷不出来。所以一开始就要用原装电源,别图那点体积上的便利。
4.3 高频报错和排查速查表
| 报错信息 | 可能原因 | 解决方法 |
|---|---|---|
| Could not find a supported ROCm GPU | 驱动没有识别到 RDNA 3.5 | 升级 ROCm 6.3 以上,或检查 BIOS 的 Above 4G Decoding |
| out of device memory | ctx-size 或 batch-size 过大 | 降低 batch-size,或者把上下文长度从 8192 降到 4096 |
| Kernel launch failed | ROCm 内核驱动与系统内核版本冲突 | 升级内核或重装 open 内核模块 |
| Model loading is extremely slow | 模型文件在机械硬盘或 USB 上 | 放到 NVMe SSD 上,模型加载时间能缩短数倍 |
| 每生成一段就开始电流声和降速 | 电源功耗墙被触发 | 检查电源功率,回退为原装 150W 电源 |
4.4 几项能再挤出性能的小设置
如果你已经稳定跑到了 80 以上的 tokens/s,还想继续压榨,我推荐这几件事。第一,在 BIOS 里把 TDP 调到最高的 PL2 档,Strix Halo 默认 54W 至 120W 之间浮动,我在满载时让它跑到 120W,速度大约提升了 2 到 3 tokens/s。第二,切换 CPU 调速器到性能模式:sudo cpupower frequency-set -g performance,这能让调度器减少不必要的降频。第三,在 server 参数里调整 FlashAttention 的块大小,比如--flash-block-size 128,有时能比默认的 64 提升 1% 到 2%。第四,打开--prefix-cache,把 system prompt 缓存起来,多轮对话场景下,实际体感提升非常明显,因为首 token 延迟能少一半。
还有一条更进阶的玩法:如果你同时跑多个模型,可以给每个模型单独开一个 halogen-flash-server 实例,分别绑定不同的端口和内存区域。虽然总内存带宽是共享的,但这种方式可以避免单个模型的 KV Cache 把某一块内存区域挤满。我试过同时跑一个 8B 和一个 14B,两者速度会各自下降一些,但总吞吐反而比单实例排队要高,日常使用场景下更灵活。
5. 这套方案后续还能怎么扩展
5.1 从“跑模型”到“跑服务”
当你把 halogen-flash-server 稳定跑起来以后,它就不仅仅是一个命令行玩具了。这个服务默认暴露的是 OpenAI 兼容接口,你可以直接把代码里所有依赖 OpenAI SDK 的项目指到http://127.0.0.1:8080上,比如知识库问答、智能客服、代码补全插件。我把它接到了一个局域网内的应用上,手机、平板和另一台电脑都能通过局域网访问同一个模型服务,体验比单独在每台设备上跑一个本地模型要统一得多。
5.2 关于内存带宽和未来软件优化
Strix Halo 的硬件潜能还在慢慢被挖掘。halogen-flash-server 目前重点优化了 FlashAttention 和连续批处理,但后续版本如果加入更激进的内存分配策略,比如把 KV Cache 单独放到高优先级内存区域,8B 模型的生成速度可能还会有几个点的提升。这不是空想,ROCm 生态对统一内存模型的支持越来越细,驱动更新后同样配置的跑分经常能高出一点。所以如果你暂时跑不到官方宣称速度,过段时间再更新一版驱动或者软件,也许就突然刷上去了。
我个人经过这一轮折腾后最大的感受是:Strix Halo 这类统一内存平台,正在把“本地跑一个大模型”变成一件真正靠谱的事。而 halogen-flash-server 这种专门为 ROCm 优化的推理服务,则把平台潜力变成实际可用的 tokens/s。如果你也在类似的迷你主机上玩本地模型,记得先确认三件事:BIOS 显存设置、ROCm 驱动版本、是否打开了 FlashAttention。这三样对齐,你离官方宣称的速度就不会太远。