<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Exo on Luenci</title>
    <link>https://luenci.com/en/tags/exo/</link>
    <description>Recent content in Exo on Luenci</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Fri, 14 Aug 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://luenci.com/en/tags/exo/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Speaker| 当三台 Mac mini 跑起大模型之后：从部署踩坑理解 Model Infra</title>
      <link>https://luenci.com/en/posts/%E4%B8%89%E5%8F%B0-mac-mini-model-infra/</link>
      <pubDate>Fri, 14 Aug 2026 00:00:00 +0000</pubDate>
      <guid>https://luenci.com/en/posts/%E4%B8%89%E5%8F%B0-mac-mini-model-infra/</guid>
      <description>基于三台 Mac mini 的本地大模型部署实践，解释冷启动、TTFT、Prefill、Decode、KV Cache、多机分片与长上下文并发的工程边界。</description>
      <content:encoded><![CDATA[<p>最近一段时间，我一直在用三台 Mac mini 部署、组网并验证本地开源大模型：选模型、加载模型、提供 API，再看请求怎样进入多机分片，以及长上下文、多轮对话和并发下到底会发生什么。</p>
<p>一开始，我很自然地认为：上下文越大越好，三台 Mac mini 合起来跑一份尽可能大的模型也越好。后来发现，这两个判断只回答了“能不能跑”。长上下文会挤占 KV Cache 和运行时内存；多机分片会带来通信、调度和恢复成本，也不会让并发能力随着机器数量线性增长。</p>
<p>业务真正需要的不是一份很大、很复杂、却反应迟缓的模型，而是一项稳定、快速、延迟可预测的服务。第一次加载为什么慢？首 Token 和后续输出为什么是两种速度？KV Cache 为什么会失效？三台机器都在线，为什么请求还是会卡住，服务又为什么常常需要重启？本文基于一段三机现场复盘这些问题。</p>
<h2 id="本次复盘的三机环境">本次复盘的三机环境</h2>
<table>
  <thead>
      <tr>
          <th>节点</th>
          <th style="text-align: right">设备与统一内存</th>
          <th>当时角色</th>
          <th>备注</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>主节点</td>
          <td style="text-align: right">M4 Pro，64GB</td>
          <td>常用 API 入口</td>
          <td>对外 API 常用端口为 <code>52415</code></td>
      </tr>
      <tr>
          <td>工作节点 A</td>
          <td style="text-align: right">M4 Pro，48GB</td>
          <td>模型分片与推理</td>
          <td>参与协同计算</td>
      </tr>
      <tr>
          <td>工作节点 B</td>
          <td style="text-align: right">M4 Pro，48GB</td>
          <td>模型分片与推理</td>
          <td>参与协同计算</td>
      </tr>
  </tbody>
</table>
<p>这是一组历史现场配置。三台机器曾以 Exo <code>v1.0.71</code> 的 <code>MlxRing + Pipeline</code> 方式协同推理；入口节点不等于全部计算发生的位置，模型分片、缓存和通信压力仍要以实际 placement 为准。</p>
<h2 id="1-先有一把尺子大模型的快到底指什么">1. 先有一把尺子：大模型的“快”到底指什么</h2>
<p>讨论大模型速度时，不能只看“每秒多少 Token”。它解释不了为什么有些请求迟迟等不到首个输出，也解释不了为什么并发一上来，每个用户都觉得变慢。</p>
<p>从用户体验看，耗时分成冷启动和单次请求两部分：</p>
<ol>
<li><strong>首次加载（冷启动）</strong>：权重从磁盘、共享存储或远端目录进入运行时，模型实例建立，必要的分片和通信资源就绪。它只发生在模型实例首次建立、重建或从冷态恢复时，不属于每一轮对话，也不是标准 TTFT 的一部分。</li>
<li><strong>TTFT（Time To First Token，首 Token 延迟）</strong>：模型已就绪后，每次请求从发出到第一个输出 Token 抵达的时间。它受排队、上下文处理、缓存命中、prefill（预填充）、网络和调度影响。</li>
<li><strong>TPOT / TBT（每个输出 Token 的间隔）</strong>：每次请求在首 Token 之后，模型生成下一个 Token 的平均时间。它主要描述 decode 阶段的速度。</li>
</ol>
<h3 id="prefill模型开口前先把上下文算完">Prefill：模型开口前，先把上下文算完</h3>
<p>把一条请求交给模型时，里面可能已经有 system prompt、历史对话、项目资料和工具结果。模型不会像人一样“扫一眼”这些内容后立刻回答，而是要先把这整段输入依次经过所有层的计算，为每个 Token 建立后续注意力所需的状态。这段集中完成准备工作的过程，就是 prefill。</p>
<p>它完成之前，模型还不能生成第一个 Token；输入越长，需要计算的内容越多，用户等待首个输出的时间就越长。计算结果会以 KV Cache 的形式保留下来。如果下一轮请求仍保留相同前缀，模型可以复用这些已经算好的状态，只处理新增部分；缓存失效或换到另一份实例后，则需要重新 prefill。</p>
<p>与之相对，decode 是首 Token 出来之后的逐 Token 生成过程。prefill 主要受输入长度影响，decode 主要决定持续输出时的流畅度。把两者混成“模型速度”，会让后续的优化方向完全相反。</p>
<p>一条回答总共生成 <code>N</code> 个 Token 时，可以粗略写成：</p>
<p><code>端到端时延 ≈ TTFT + (N - 1) × TPOT</code></p>
<p>首 Token 很快、后续生成很慢，和首 Token 等很久、后续输出流畅，是两类问题。前者多半要看 decode、批处理和计算/通信带宽；后者要看排队、prefill、上下文长度和缓存。系统吞吐量是所有并发请求单位时间内完成的总 Token 数，也不能代替单个用户的体验。</p>
<p>因此，日志里持续出现 prefill 进度时，系统可能只是在处理很长的输入，并不一定已经死锁。</p>
<h2 id="2-一次本地大模型请求究竟经历了什么">2. 一次本地大模型请求，究竟经历了什么？</h2>
<p>先把一次请求的路径展开，后面的故障就更容易放回正确的位置。</p>
<div class="highlight"><div style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">
<table style="border-spacing:0;padding:0;margin:0;border:0;"><tr><td style="vertical-align:top;padding:0;margin:0;border:0;">
<pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 1
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 2
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 3
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 4
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 5
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 6
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 7
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 8
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679"> 9
</span><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#737679">10
</span></code></pre></td>
<td style="vertical-align:top;padding:0;margin:0;border:0;;width:100%">
<pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Agent 或用户输入
</span></span><span style="display:flex;"><span>  → API 服务与请求路由
</span></span><span style="display:flex;"><span>  → 模型是否已就绪？未就绪则从存储加载模型权重，并建立实例与分片
</span></span><span style="display:flex;"><span>  → 上下文拼装、Chat Template、分词
</span></span><span style="display:flex;"><span>  → 找到模型实例与实际计算节点
</span></span><span style="display:flex;"><span>  → 查询 KV Cache
</span></span><span style="display:flex;"><span>  → 未命中：prefill；命中：复用已有状态
</span></span><span style="display:flex;"><span>  → decode：逐 Token 生成
</span></span><span style="display:flex;"><span>  → 需要工具：执行工具、回填结果，再进入下一轮
</span></span><span style="display:flex;"><span>  → 不需要工具：流式返回最终输出
</span></span></code></pre></td></tr></table>
</div>
</div><p>这里要分清两件事。</p>
<p>第一，<strong>模型权重加载</strong>和<strong>请求的 prefill</strong>不是一回事。模型权重加载，是把模型已经训练好的参数从本地磁盘、共享存储或模型目录读入运行时；多机时，还要把这些参数按分片放到相应节点。它让模型从“尚未服务”变成“可以计算”。prefill 则发生在每一轮请求中：模型为当前输入的所有 Token 建立注意力状态。一个模型已经加载完成，第一次长上下文请求仍然可能很慢。若前缀缓存命中，系统只需从第一个新增 Token 开始处理；若不命中，则要重新处理失配位置之后的整段输入。</p>
<p>第二，<strong>API 入口</strong>和<strong>实际执行位置</strong>也不是一回事。多机集群常有一个统一入口，但权重层、缓存和计算可能分布在多台机器上。只盯着入口机器的 CPU、内存或日志，往往会错过真正承压的节点。</p>
<p>对 Agent 来说，这条链路会反复循环。工具调用的结果会回填进上下文，下一轮再查缓存、prefill、decode。它的速度不只取决于模型每秒生成多少 Token，也取决于这条循环能否稳定地跑下去。</p>
<h2 id="3-第一次部署模型加载为什么这么慢">3. 第一次部署：模型加载为什么这么慢</h2>
<p>本地部署里很容易把“模型目录已经存在”当成“模型已经可用”。实际上至少还有四个状态：模型文件是否在、进程是否启动、runner 是否就绪、真实请求是否已经返回。这里的 runner 指实际加载模型或模型分片、执行推理的进程。</p>
<p>在三机现场中，模型目录规范、离线变量、共享存储可见性和运行进程都曾成为问题。模型可能已经下载完成，但实际 Exo 进程仍指向旧目录；也可能三台机器都能看到目录，却在共享存储并发读取时出现抖动。把“文件存在”当作“模型已加载”，会让排障从一开始就偏离。</p>
<p>首次加载慢通常由几类工作叠加：读取权重、解析模型配置、在各节点建立实例、按拓扑放置分片，以及为推理通信准备资源。若模型大到需要跨机切分，任何一个节点的磁盘、网络或内存压力都会延长这条冷启动路径。</p>
<p>冷启动验收不能只看页面上有没有模型名称。至少要确认：进程是否监听、模型实例是否创建、各 runner 是否就绪、流式请求能否拿到结果。它们分别回答服务在不在、模型是否准备好、集群是否真的协同、用户是否真的能用。</p>
<h2 id="4-三台机器连起来之后系统不再只是一台更大的-mac">4. 三台机器连起来之后：系统不再只是一台更大的 Mac</h2>
<p>多机推理解决的是单机内存装不下的问题，也把一个进程变成了多条相互依赖的链路。</p>
<p>这段实验里，至少要分开看四层：</p>
<ul>
<li><strong>API 与界面层</strong>：统一入口、Dashboard、OpenAI 兼容请求。</li>
<li><strong>控制面</strong>：节点发现、心跳、选主和任务调度。</li>
<li><strong>推理数据面</strong>：节点间传递激活值、执行 collective、完成分片推理。</li>
<li><strong>模型存储面</strong>：本地 SSD、SMB 或 NAS 上的权重与清单。</li>
</ul>
<p>它们不一定走同一条网络，也不一定以同一种节奏失败。Thunderbolt 或 RDMA 可用，只能说明推理数据面可能通畅；控制面仍可能因为以太网或发现机制抖动而失联。反过来，Dashboard 能连上，也不能证明分片节点能完成一次 collective。</p>
<p>所以，三台机器在界面上都在线，实际请求却可能停在加载、prefill 或等待状态。此时应看模型实际放在哪些节点、runner 是否就绪、任务卡在哪个阶段，不能把入口节点当成所有计算发生的地方。</p>
<h2 id="5-为什么会慢把慢拆成不同问题">5. 为什么会慢：把“慢”拆成不同问题</h2>
<p>“慢”至少可能指四件事。</p>
<p><strong>一是冷启动慢。</strong> 模型实例尚未就绪，权重、分片或通信资源正在建立。这种慢发生在请求真正进入模型计算之前。</p>
<p><strong>二是 prefill 慢。</strong> 输入越长，模型需要为越多 Token 建立状态。长项目上下文、长 RAG 文档和多轮历史都会主要拉高 TTFT。尤其在缓存未命中时，系统必须重新处理整个前缀。</p>
<p><strong>三是 decode 慢。</strong> 首 Token 出来后，模型仍要自回归地一个 Token 一个 Token 生成。这里更受模型规模、量化、计算带宽、批处理和跨机通信影响。</p>
<p><strong>四是排队或队头阻塞。</strong> 一个长请求占据 runner 后，后来的短请求也可能被迫等待。三机联合分片并不自动等于三条独立的并发通道；如果它们共同服务一份模型，一次请求仍会占用多个节点的协作资源。</p>
<p>对于 Agent，还要把工具执行时间算进来。模型暂停等待本地命令、MCP 服务或外部工具返回时，缓存并不会因此永远保留；下一轮请求是否还能复用前缀，仍取决于缓存是否存活、是否被挤出，以及是否回到原来的计算实例。</p>
<p>这些区分会直接改变排障顺序。持续的 prefill 日志更像长输入计算；多个请求都没进入 runner，要先看调度和实例状态；首 Token 已经很快但流式输出稀疏，就该看 decode 和通信。一次“感觉很慢”，不能同时解释四类问题。</p>
<h2 id="6-kv-cache让多轮对话变快也让系统变脆弱">6. KV Cache：让多轮对话变快，也让系统变脆弱</h2>
<p>Transformer 在处理输入时，会为每层已处理 Token 保存注意力计算需要的 Key 和 Value。下一轮请求若仍以同一段前缀开始，系统可以复用这些状态，避免从头 prefill。这就是 KV Cache。它复用的不是“意思相近的历史”，而是已经计算过、并且前缀 Token 序列仍能对齐的注意力状态。</p>
<p>它对 Agent 尤其重要：system prompt、项目背景、对话历史和工具记录会在多轮中反复出现。缓存命中时，TTFT 会下降；缓存未命中时，系统又回到完整 prefill。</p>
<p>但缓存并不是一个抽象的“加速开关”。它有三个现实边界：</p>
<ol>
<li><strong>容量边界</strong>：在 Apple Silicon 的统一内存中，权重、KV Cache 和运行时空间共享同一份预算。上下文和并发增加时，缓存会与模型本身争夺空间。</li>
<li><strong>位置边界</strong>：在 Exo 这类多机环境里，缓存可绑定具体 runner 或 instance。统一 API 入口不代表不同实例之间共享缓存。</li>
<li><strong>一致性边界</strong>：上下文的前缀、Chat Template、工具调用记录或历史顺序发生变化，都可能使缓存无法复用。多轮状态一旦分叉，后续请求可能重新走完整 prefill，甚至在分布式同步上暴露问题。</li>
</ol>
<p>缓存也有<strong>存活边界</strong>：热缓存通常存在时间窗口，但真正的淘汰常常由内存压力决定，而不是由一个固定倒计时决定。高峰期或长上下文请求到来时，旧缓存可能在预期时间之前被挤出；下一轮再回来时，体感上就像模型“突然又变慢了”。</p>
<p>在历史现场里，可观察到请求级的 <code>cached_tokens</code>，但没有现成的全局“缓存还剩多少 GB、还能容纳多少会话”的仪表盘。这是一个很重要的边界：单次命中率能告诉我们该请求是否复用了前缀，却不能证明整个集群的缓存容量健康。</p>
<p>遇到 KV Cache 问题，不能只问“缓存为什么爆了”。至少要把下面三种情况分开：</p>
<ol>
<li><strong>容量不够，缓存被淘汰。</strong> 典型信号是内存接近上限、日志出现 cache eviction，或者在长上下文和高并发后原本能命中的会话突然全部变慢。此时应先缩短上下文、降低并发或释放其他模型实例，再观察缓存是否稳定。</li>
<li><strong>前缀变了，缓存没有命中。</strong> 典型信号是新请求仍落在同一实例，但 <code>cached_tokens</code> 明显下降或归零。应逐项对照 system prompt、历史消息、工具结果、Chat Template 和模型版本，找出第一个变化的位置。</li>
<li><strong>请求换了实例，原缓存不在这里。</strong> 典型信号是上下文没有变化，但请求被调度到另一份 instance 或另一组 runner。此时不是缓存内容错误，而是缓存仍留在原实例；需要检查请求路由、placement 和会话亲和策略。</li>
</ol>
<p>这三种情况的处理方式不同。先判定是哪一种，再改上下文、并发或路由；否则很容易用“清缓存再重试”掩盖真正的问题。</p>
<h2 id="7-为什么节点会不一致又为什么总需要重启">7. 为什么节点会不一致，又为什么总需要重启</h2>
<p>多机系统里的“节点不一致”，往往不是某台机器真的消失，而是不同层面对它给出了不同判断：控制面认为它过期，存储面仍可见，某个遗留 runner 还占着内存，客户端却仍在等待旧任务的结果。</p>
<p>这段 Exo 实验曾遇到过选主抖动、API 暂停、遗留 runner、任务取消记录干扰负载判断等现象。固定主节点可以在特定环境下缓解选主抖动，但它不是无代价的修复：主节点故障后，恢复会转为人工责任。</p>
<p>重启之所以看起来有效，是因为它会清空一部分暂态：旧进程、旧 runner、未完成任务、被占用的端口和内存状态。但重启不能修复版本参数混用、共享存储不稳定、RDMA 链路不可用或负载选择逻辑错误。把“重启后好了”当成根因分析，会让同一个问题在下一次压力下重演。</p>
<p>更可靠的做法是区分三种结论：已经在目标机验证的事实、日志或源码支持但尚未闭环的根因、以及只是为了恢复服务的临时绕过。把它们分开写，经验才经得起复查。</p>
<h2 id="8-从反复救火到可重复的排障方法">8. 从反复救火到可重复的排障方法</h2>
<p>经历这些故障后，我把检查顺序固定了下来。</p>
<p>第一步是确认<strong>真实运行环境</strong>：版本、checkout、实际进程、虚拟环境和模型目录。不要把另一台机器上的路径、旧版本的参数或历史截图当成当前事实。</p>
<p>第二步是确认<strong>服务与拓扑</strong>：进程是否监听、API 是否可达、节点是否被发现、模型实际放在哪里、runner 是否就绪。</p>
<p>第三步是确认<strong>数据路径</strong>：模型存储是否可读、网络协商是否正常、数据面通信是否真的可用。一个“已开启”的 RDMA 开关，不等同于所有端口和所有节点都能协同。</p>
<p>第四步才进入<strong>真实请求</strong>：分别测试流式与非流式、短上下文与长上下文、单轮与多轮、取消与并发。这样才能知道故障处在首次加载、prefill、decode、缓存、调度还是客户端协议。</p>
<p>最后，每次结论都要写清边界。模型、版本、节点拓扑和负载都会变化；比起保存一条看似永远有效的命令，更重要的是保留一套重新确认事实的检查顺序。</p>
<h2 id="9-长上下文并发的边界调度也无法把硬件完全吃满">9. 长上下文并发的边界：调度也无法把硬件完全吃满</h2>
<p>一个并发会话不是一个固定大小的任务。它会同时占用几种不同资源：长输入在 prefill 阶段集中消耗计算；已处理的上下文持续占用 KV Cache；持续生成时又主要消耗 decode 所需的计算和内存带宽；多机环境还要占用节点间通信。不同会话的输入长度、输出长度、缓存命中情况和结束时间都不同，因此很难像整齐的方块一样，恰好把一张卡、一台机器或一组分片节点填满。</p>
<p>这会带来几组无法同时满足的取舍：</p>
<ul>
<li>想提高批处理吞吐，通常要等待更多请求凑成批次，TTFT 就会变长；</li>
<li>想保留长上下文的 KV Cache，就会压缩能承载的新会话数量；</li>
<li>想把同一会话持续路由回原实例以复用缓存，就会削弱最平均的负载均衡；</li>
<li>想让所有请求都立即开始生成，长 prefill、持续 decode 和跨机通信又会相互争抢资源。</li>
</ul>
<p>调度能减少浪费：把相近请求放进同一批次，优先处理短任务，维持会话亲和路由，或限制单个会话的上下文和并发数。但它不能让有限的显存或统一内存无限容纳 KV Cache，也不能让同一组计算单元同时在 prefill、decode 和通信阶段保持最高效率。并发继续增加后，总吞吐量可能还会上升，单个会话的 TTFT、TPOT 和排队时间却会变差，缓存淘汰也会更频繁。</p>
<p>这不是某个框架“调度不够聪明”，而是长上下文推理的基本边界：高吞吐、低延迟、长上下文和高并发，不能在有限硬件上无限叠加。更强的芯片会把边界往外推，却不会取消这些取舍。</p>
<p>这也说明 Agent 的上下文组织和 Harness 会影响真实成本。请求格式稳定、前缀可复用、工具循环可预测时，缓存亲和和批处理才更容易发挥作用；任意长度的长上下文、频繁变化的前缀和不可预测的工具链，则会让理论吞吐很难落到实际服务上。跑测的目标不是证明硬件能被压到多满，而是找出服务开始失去可预测性的那条线。</p>
<h2 id="10-真实业务场景如何选择模型">10. 真实业务场景如何选择模型</h2>
<p>选模型不能只看参数规模或标称上下文长度。模型是否适合业务，至少要看四件事：能不能完成目标任务，长上下文下能不能保持有效理解，部署后首 Token 和持续输出是否够快，以及并发、多轮工具调用和重启之后能不能稳定服务。</p>
<p>公开榜单和基准测试可以用来初筛模型能力，例如通用推理、代码生成或软件工程任务上的表现；但它们替代不了业务验收。真正需要复测的是自己的提示词、工具协议、项目上下文和成功标准。上下文更长、参数更多的模型，未必比能力足够、响应更快、运行更稳定的模型更适合业务。</p>
<p>实际选择时，可以先用目标任务筛选能力，再确认真正需要的有效上下文，最后在目标硬件和目标并发下测试冷启动、TTFT、TPOT、吞吐、内存与恢复行为。业务需要的通常不是最大、最复杂的模型，而是一项稳定、快速、延迟可预测的模型服务。</p>
<h2 id="结语model-infra-是一套状态系统">结语：Model Infra 是一套状态系统</h2>
<p>这次本地大模型部署带来的最大变化，是不再把模型理解成一个下载好的文件，或一个已经监听端口的 API。</p>
<p>一次回答的背后，有权重何时进入内存、输入如何被编译为 Token、缓存能否复用、分片落在哪些节点、请求是否排队、工具结果如何回填，以及节点失败后状态如何恢复。它们共同决定模型是“跑起来”，还是“真的可以被持续使用”。</p>
<p>从这个角度看，Model Infra 不是离应用很远的底层名词。它就是每一次“为什么这么慢”“为什么缓存没了”“为什么三台机器在线却不能回答”“为什么重启后又好了”背后的共同语言。</p>
<p>当我们能把这些问题放回同一条请求旅程中，部署经历才不再是一串零散的坑，而会变成理解大模型系统的入口。</p>
<h2 id="参考文章与资料">参考文章与资料</h2>
<h3 id="写作来源与延伸阅读">写作来源与延伸阅读</h3>
<ul>
<li><a href="https://x.com/ashfold/status/2077294392059232269">不懂 Model Infra，写不好 Harness</a></li>
<li><a href="https://juejin.cn/post/7626665836176195635">2026 大模型部署框架终极选型指南：7 大框架全面对决</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/714128928">大模型性能指标相关文章（知乎）</a></li>
</ul>
<h3 id="性能与评测参考">性能与评测参考</h3>
<ul>
<li><a href="https://learn.microsoft.com/zh-cn/azure/databricks/machine-learning/foundation-model-apis/prov-throughput-run-benchmark">Microsoft：LLM 终结点基准测试</a></li>
<li><a href="https://docs.nvidia.com/nim/benchmarking/llm/latest/metrics.html">NVIDIA：LLM 推理基准指标定义</a></li>
<li><a href="https://huggingface.co/docs/leaderboards/main/index">Hugging Face：模型评测与排行榜</a></li>
<li><a href="https://github.com/LiveCodeBench/LiveCodeBench">LiveCodeBench：代码能力评测</a></li>
<li><a href="https://arxiv.org/abs/2310.06770">SWE-bench：真实软件工程问题评测</a></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
