<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://rightson.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://rightson.github.io/" rel="alternate" type="text/html" /><updated>2026-11-07T12:33:06+08:00</updated><id>https://rightson.github.io/feed.xml</id><title type="html">Scott Chen | 談科技、論價值</title><subtitle>從網路、晶片設計與 AI 系統的運作機制出發，推演產業結構、公司策略與資本市場的走向。</subtitle><author><name>Scott Yo-Ru Chen</name></author><entry><title type="html">Themis 用同一路徑的後續封包判斷 RDMA 是否真的掉包</title><link href="https://rightson.github.io/networking/2026/11/04/themis-rdma-path-nack-validation.html" rel="alternate" type="text/html" title="Themis 用同一路徑的後續封包判斷 RDMA 是否真的掉包" /><published>2026-11-04T18:55:04+08:00</published><updated>2026-11-04T18:55:04+08:00</updated><id>https://rightson.github.io/networking/2026/11/04/themis-rdma-path-nack-validation</id><content type="html" xml:base="https://rightson.github.io/networking/2026/11/04/themis-rdma-path-nack-validation.html"><![CDATA[<p>分散式訓練每進入一輪 AllReduce，各機器都要送出一批梯度、接收其他機器的資料，等最後一段傳完才能繼續。假設兩台伺服器之間有八條可走的路，交換器用 ECMP 對每條連線雜湊選路：八條路在拓樸上都能通，卻可能有幾條同時塞進多條大流，其他路還很空。一條繁忙上行就足以延後整輪同步。把同一條連線的封包逐包分散，可以把閒置頻寬用起來；快路徑的後送封包也因此會超車。</p>

<p>EuroSys 2026 的 <a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=2">Themis 論文</a> 把這個問題拆成兩半。既有網卡可以把先到的資料寫到正確位置，但看見序號缺口時，仍可能把正常失序當成掉包。Themis 讓目的機架交換器修正「何時請求重傳」：它把目的端缺口跟原定路徑的進度比對，讓正常失序繼續前進，等到有足夠線索才送出 NACK。網卡仍負責資料寫入、重傳與完成通知。</p>

<p><img src="/images/networking/2026-11-04/themis-packet-path.svg" alt="資料沿兩條上行路徑抵達目的交換器，重傳請求反向經交換器判斷" /></p>

<p><em>依據 <a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=4">Themis §3–4</a> 重繪。上半部走資料，下半部走 NACK；路徑選擇在來源端，缺口判斷在目的端。</em></p>

<h2 id="資料可以先寫進記憶體網卡還是會誤判掉包">資料可以先寫進記憶體，網卡還是會誤判掉包</h2>

<p>以論文採用的 RDMA Write 與 Direct Data Placement 模式為例，資料封包帶有足以定位目的記憶體的資訊。接收網卡看到較晚序號先到，可以把它寫進應有的位置，同時在位元圖記下這一包已到。網卡保存下一個預期的序號 ePSN；如果預期 100，先收到 101，101 的寫入與 100 是否已到是兩件事。等 100 補齊，接收端才把連續接收的進度推到下一個缺口。既有的 <a href="/networking/2026/10/28/eunomia-dynamic-bitmap-rdma-reordering.html">Eunomia 分析</a> 說明了位元圖如何支撐這種分工；這次要解的是另一個問題：在網卡已能容忍失序時，誰能判斷應不應該重傳？</p>

<p><a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=3">論文 §2.3</a> 描述的既有選擇性重傳機制，會在看見失序時對當前 ePSN 送出一次 NACK。單一路徑維持順序時，這個判斷通常合理；逐包分流之後，快路徑上的 101 先到，只能說慢路徑上的 100 還沒到。把 NACK 直接送回去，來源網卡除了多送一包，還可能進入較慢的傳送階段；即使無掉包，也可能同時浪費頻寬與傳送端資料路徑的處理時間。反過來，若交換器一概丟棄 NACK，100 真掉時，網卡通常也不會為同一缺口再發一次，只能等傳送端逾時。兩端都看得見序號，卻都缺少將序號與實際選路對起來的資訊。</p>

<h2 id="交換器用路徑進度把遲到與掉包分開">交換器用路徑進度把遲到與掉包分開</h2>

<p>假設有兩條等價路徑，正常時同一路徑維持順序。來源交換器按 PSN 除以二的餘數選路，偶數走 A、奇數走 B。目的交換器看到缺口 100，即使從未見過 100，也能算出它原定走 A。更大的 Clos 拓樸中，<a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=5">論文 §4.1</a> 以可預測的標頭改寫控制選路；教學用的餘數式代表共同映射，實際部署還須確定雜湊、埠配置與兩端路徑編號能對上。</p>

<p>目的交換器維護兩份不同的紀錄：每條連線的代理位元圖，記下哪些封包已經向 RNIC 送出；每條路徑的最大序號，記下該路最新送出的封包。當 NACK 回到交換器，先查它指的包是否已經送往網卡；如果已送，這個請求多半已過時，便攔住。如果尚未送出，再比對原定路徑是否已送出較晚的包。同一路徑保持順序時，A 的 102 已通過而 100 還沒出現，就有理由讓 NACK 回源。若目前只有 B 的 101 到達，則先留下缺口，等後續封包判定。</p>

<p><img src="/images/networking/2026-11-04/themis-nack-decision.svg" alt="目的交換器依序檢查已送位元與同一路徑進度，分為攔截、回送與暫存" /></p>

<p><em>依據 <a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=7">Themis 圖 6、7</a> 重繪。代理位元圖回答「是否已送出」，路徑進度回答「原定路徑是否已走過缺口」。</em></p>

<p>把這套規則走一次。101 從 B 先到，RNIC 把它寫入目的緩衝區並送出 NACK(100)。目的交換器的位元圖尚未標 100，A 也還沒出現比 100 大的封包，於是留下 100 與重建請求所需資訊，丟棄原來的 NACK 封包。若接著是 A 的 100 抵達，暫存請求就清除；101 的資料早已到位，接收端可以繼續推進。若接著抵達的是 A 的 102，交換器用後續封包建立一份新的 NACK(100) 回送，來源網卡重送 100，網卡收到後才推進接收進度。兩種分支下，目的交換器都沒有扣住 101 的資料等 100。</p>

<p>暫存一個缺口就夠用，是因為論文的 RNIC 在同一條連線上只對目前最前面的缺口發 NACK；若新 NACK 指向更後面的缺口，舊缺口已由接收端跨過。這也限制了適用範圍：改用會為多個缺口同時發出請求的傳輸機制時，就不能直接照抄單一暫存欄位。若整輪傳送在缺口之後沒有同路封包，或剩餘封包也全失，交換器拿不到這項證明，傳送端的逾時仍是最後一條恢復路徑。<a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=6">Themis §4.2–4.3</a></p>

<h2 id="每增加一條路徑都要付出一筆交換器狀態">每增加一條路徑，都要付出一筆交換器狀態</h2>

<p>把路徑進度放在交換器上，代價跟跨機架連線數、傳送視窗與路徑數一起成長。假設每條連線保存一份 512 位元的邏輯位元圖，以及每條路徑 24 位元的最大 PSN。八條路徑時，每連線裸資料為 64 + 24 = <strong>88 bytes</strong>；128 條路徑時為 64 + 384 = <strong>448 bytes</strong>。每機架若有 16 張網卡、每張 512 條跨機架連線，則下界分別約 <strong>0.69 MiB</strong> 與 <strong>3.5 MiB</strong>。這個假設算例還沒有算暫存 NACK、視窗基準、避免壞路徑的計數器、配置對齊或跨管線副本。實作的位元圖也可能比邏輯視窗更長。若記憶體只以總量計帳，很容易漏掉特定管線的 SRAM 或處理階段先用完的情況。</p>

<p>另一筆代價是等多久才確認掉包。假設一條 QP 穩定送出 100 Gb/s 有效資料、每包 4 KiB、等距輪轉，八條路徑上，同一路徑相鄰兩包的送出間隔約 <strong>2.62 µs</strong>；128 條路徑時約 <strong>41.94 µs</strong>。這只是傳送端間隔，實際判定還要加排隊、傳播與控制封包回程。連線若只有 25 Gb/s，兩個值再乘四；短傳輸的最後幾包甚至沒有下一包可等。把更多路徑納入固定輪轉有機會改善容量分散，卻會稀釋各路徑提供後續線索的頻率。真正適合的路徑數應由突發流量、單一 QP 速率與尾端掉包的代價共同決定。</p>

<p>論文原型把來源邏輯放在 ingress、目的邏輯放在 egress，等資料離開佇列、準備送往網卡時才更新代理狀態。這個位置很重要：若在入列時就標記「已送」，封包仍可能在交換器內等待或掉落，交換器卻已經把真 NACK 擋掉。Tofino2 有多條彼此獨立的管線，資料與反向控制封包若走到不同管線，就未必讀得到同一份狀態。論文把控制封包送回與資料共用狀態的 egress，再鏡射到真正的出口。這增加內部處理工作，所以評估容量時要同時看資料 p99、鏡射量和管線資源，而非只看交換器標稱頻寬。<a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=8">Themis §5、表 1</a></p>

<h2 id="壞路徑要更快繞開單一路徑上的判斷也會變弱">壞路徑要更快繞開，單一路徑上的判斷也會變弱</h2>

<p>若 A 路徑完全失效，就不會有 A 的後續封包來證明 100 掉了。Themis 觀察後續封包與暫存缺口的序號距離；差距超過門檻時，即使欠缺同路線索，也回送一個帶路徑避讓訊號的 NACK。來源端先讓本來要走 A 的一批封包改走其他路徑，避讓計數用完後才重新嘗試。正常重傳也可改走替代路徑，減少同一包連續掉在同一段鏈路上的機會。<a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=8">Themis §4.4</a></p>

<p>這裡的取捨是：讓系統在壞路徑上繼續等，會拖長訓練尾延遲；提早繞開則會破壞序號到路徑的一一對應，讓少量本來只是遲到的封包也被重傳。排隊造成的暫時慢路徑也可能越過同一門檻。上線時可先在單一訓練池做對照，把單路慢化、短時斷線、往返控制封包掉落以及最後一包掉落分開注入；一起觀察錯誤 NACK 比例、逾時比率、重新加入路徑後的尾延遲和訓練每步耗時。未來 1 個月的試部署中若只有平均頻寬上升，p99 collective 時間與逾時卻沒有改善，就應縮小噴灑路徑範圍，或讓該工作回到較保守的選路。</p>

<h3 id="把等待拆成資料排隊與控制三筆帳">把等待拆成資料、排隊與控制三筆帳</h3>

<p>可以拿同一個兩路案例比較緩衝空間。假設慢路比快路多等 20 µs，快路此刻正以 100 Gb/s 把同一條連線的資料送到目的交換器。若交換器必須照順序交付，單一缺口背後就可能先累積約 250 kB，也就是約 61 個 4 KiB 封包。這是有效資料量上限的簡化估算，還沒算每包的標頭與交換器內部單位。如果有 32 條連線同時進入這種狀態，而且每條都符合相同到達速率與差值，逐條相加是約 8 MB；實際能否同時達到還受限於入口和出口總頻寬，不能把這個相加值當成實測。Themis 的交換器只保存序號資訊，先到的資料交給網卡落地；即使控制狀態只占數百 bytes，也仍要確認主機緩衝區、RNIC 位元圖與回覆時點能吸收失序。減少的是交換器等待中的 payload，整條路徑的等待時間並沒有憑空消失。</p>

<p>同一條 100 Gb/s 連線若每一千包出現一次誤重傳，每包都是 4 KiB，單看多送的封包，有效頻寬損失約 0.1%。這個數字可能遠小於工作完成時間的損失，因為 NACK 還會干擾傳送端的流水線和速率。相反地，若抑制了所有 NACK，資料頻寬圖可能很好看，但掉一個尾包就可能讓整批等待 RTO。論文實體測試用 4 ms 的 RTO；只要有一次完整逾時，單看時間就約等於在 100 Gb/s 傳送 50 MB 的時間。測試時因此要分開統計「重傳了多少 bytes」和「一輪多等多久」，才看得出改善是否來自減少誤重傳、縮短真掉包的等待，或只來自路徑分散。</p>

<h3 id="避免把交換器看見的進度當成網卡已完成">避免把交換器看見的進度當成網卡已完成</h3>

<p>以一個網卡到 ToR 的短鏈路錯誤為例，目的交換器可能已把 100 標記為送出，網卡卻沒收到。隨後 101 觸發的 NACK 可能被當成過期請求，這時真正可靠的最後保護仍在端點。驗證時可把掉包位置從 spine 鏈路移到目的網卡前，再比較兩種情境的 NACK 過濾率與 RTO 次數。這能確認交換器正在解的是哪一段路徑，以及哪一段要靠鏈路錯誤監控、端點計數器或較保守的選路。若實際部署做不到把每路進度與 QP 生命週期正確對上，應先讓同一條連線回到既有路徑策略，再修正狀態初始化、清除及路徑變更時的對照方式；不宜在正常流量下等待偶發尾延遲替系統指出錯誤。</p>

<h2 id="原型證明了哪一段還要自己量哪一段">原型證明了哪一段，還要自己量哪一段</h2>

<p><a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=9">EuroSys 2026 論文 §6</a> 的實體測試使用八張 ConnectX-7、兩台 Tofino2（虛擬成四個 ToR 與兩個 spine）與 100 Gb/s 鏈路。每張網卡向同群下一站執行 256 MB RDMA Write，量最慢流的完成時間。與同樣在交換器逐包分流的 RNIC 選擇性重傳對照，在啟用 DCQCN 的設定下，作者報告最慢流完成時間縮短 <strong>46.5%–77.8%</strong>。這證明在這套網卡、鏈路與流量條件下，過濾誤重傳的效果能穿過真實的網卡與交換器資料路徑；還沒有直接量到大型訓練叢集的 GPU 閒置時間。</p>

<p>同篇論文用 256 NIC、200 Gb/s 的 NS-3 模擬補上 collective 比較。相對於 RNIC 選擇性重傳配自適應路由，作者報告最慢一組 <strong>AllReduce</strong> 完成時間縮短 <strong>22.7%–35.4%</strong>，<strong>AllToAll</strong> 縮短 <strong>29.3%–47.3%</strong>。最慢組的完成時間會影響同步訓練，但加速比例還取決於原本有多少時間卡在通訊。假設每步原為 100 ms，其中 40 ms 是完全未與計算重疊的 collective，若該段縮短 30%，每步變成 88 ms，時間下降 12%，步數吞吐約增加 13.6%；若大部分通訊原已被計算掩蓋，整步收益會更小。這個換算是條件式估算，與原型量測分開。</p>

<table>
  <thead>
    <tr>
      <th>做法</th>
      <th>最適合的條件</th>
      <th>主要成本</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>ECMP 或 flowlet 選路</td>
      <td>連線本來就夠多，或長流內有足夠空檔改道</td>
      <td>在同步的大流量突發下，可能仍有幾條上行過載</td>
    </tr>
    <tr>
      <td>ConWeave 在目的 ToR 重排</td>
      <td>既有網卡需要較有序的封包流，且目的交換器有緩衝空間</td>
      <td>等待時要保留實際資料；流量大時需驗證佇列與緩衝壓力</td>
    </tr>
    <tr>
      <td>Themis 驗證 NACK</td>
      <td>網卡已能接收失序資料，且兩端交換器可控制選路</td>
      <td>每條連線的位元圖與路徑進度、管線處理和故障下的誤判成本</td>
    </tr>
    <tr>
      <td>端點原生多路徑傳輸</td>
      <td>有條件換網卡或調整傳輸層，能讓端點掌握整體路徑資訊</td>
      <td>硬體／韌體改造，與混用既有網卡的驗證成本</td>
    </tr>
  </tbody>
</table>

<p>2023 年的 <a href="https://www.comp.nus.edu.sg/~lijl/papers/conweave-sigcomm23.pdf">ConWeave</a> 已把保持有序送達的工作移到目的 ToR。Themis 再往前問：當網卡能自己放置失序資料，交換器是否只需保存判斷缺口的資訊？這兩種作法的差別會反映在容量規劃：前者要先量等候中的資料量；後者要先量活躍跨機架 QP、每路回報速度，以及有多少 NACK 因為無法判斷而落入逾時。若叢集的主要瓶頸是大量持續掉包、低速短流或不穩定路由，應先確認 Themis 的選路假設在現場成立，再把論文的改善幅度放進訓練容量估算。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>本文討論的是論文採用的 RNIC 模式與可程式化交換器。位元圖是交換器送往 RNIC 的代理紀錄，並非網卡已寫入記憶體的獨立證明；主機側鏈路與網卡丟包需要另行驗證。同路徑維持順序是主要判定前提；繞路、鏈路聚合或雜湊變更時須重新驗證。兩組假設算例使用十進位 Gb/s 與二進位 KiB、MiB，沒有模擬實際 ASIC 管線或訓練作業。</p>

<h2 id="參考資料">參考資料</h2>

<ul>
  <li><a href="https://cse.hkust.edu.hk/~kaichen/papers/themis-eurosys26.pdf#page=5">Xiangzhou Liu 等人，Themis，EuroSys 2026，§4–6</a></li>
  <li><a href="https://conferences.sigcomm.org/events/apnet2025/apnetprogram.php">APNet 2025 技術議程，Reinventing RDMA</a></li>
  <li><a href="https://www.comp.nus.edu.sg/~lijl/papers/conweave-sigcomm23.pdf">CH Song 等人，ConWeave，SIGCOMM 2023</a></li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="networking" /><summary type="html"><![CDATA[Themis 讓兩端機架交換器以封包序號選路、暫存並驗證重傳請求，使既有網卡能分散流量；代價是交換器狀態與對路徑順序的依賴。]]></summary></entry><entry><title type="html">多組 SerDes 配置如何交給整合團隊，Marvell SDC Creator 的三段生成流程</title><link href="https://rightson.github.io/ic-design-platform/2026/11/02/marvell-sdc-creator-configured-ip-handoff.html" rel="alternate" type="text/html" title="多組 SerDes 配置如何交給整合團隊，Marvell SDC Creator 的三段生成流程" /><published>2026-11-02T18:56:51+08:00</published><updated>2026-11-02T18:56:51+08:00</updated><id>https://rightson.github.io/ic-design-platform/2026/11/02/marvell-sdc-creator-configured-ip-handoff</id><content type="html" xml:base="https://rightson.github.io/ic-design-platform/2026/11/02/marvell-sdc-creator-configured-ip-handoff.html"><![CDATA[<p>一個 SerDes IP 可以同時支援 Ethernet、PCIe 與測試模式，但放進特定 SoC 後，真正啟用的時脈、資料寬度、頻率和實例位置只占其中一部分。IP 團隊交出一份通用模板有其合理性：同一份材料能服務多個客戶與晶片版本。整合工程師接手後，仍要逐項選出本次模式，刪除未使用的時脈，並把文件中的限制換成可供 synthesis、APR 與 STA 使用的 SDC。</p>

<p>這種工作量會隨介面數、配置與版本一起成長。Marvell 的 Patricia Fong 在 <a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=1">WISH 2024 原始論文</a>中，公開 SDC Creator 的具體方法：以 5 nm SoC 的可配置 56G SerDes 為示範，把 IP 文件、可選模板和晶片配置轉成 SDC，另把已有 SDC 轉成供設計審查使用的文字。這篇研究的工程主題，是 IP 規格如何交到 SoC 整合流程；它也說明生成速度與最終交付速度之間，還隔著哪些工作。</p>

<figure>
<a href="/images/ic-design-platform/2026-11-02/sdc-ip-handoff.svg"><img src="/images/ic-design-platform/2026-11-02/sdc-ip-handoff.svg" alt="IP 團隊提供規格與可選模板，SoC 團隊提供模式、時脈及實例配置，SDC Creator 產生候選 SDC，再由工程師與既有時序工具檢查後交給 synthesis、APR 和 STA。" width="700" height="900" /></a>
<figcaption>圖一：依據 <a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=2">Marvell 論文第 2–6 頁</a>整理；底部的設計版本配對與工具檢查，是整合端需要安排的工作，沒有表示 Marvell 已公開完整的內部發布平台。</figcaption>
</figure>

<p>沿圖往下看，兩個團隊提供的資料回答不同問題。IP 文件界定允許的用法，SoC 配置選定這次實際使用的組合；生成工具負責把兩者接起來，實體設計工具則檢查這個組合在目前設計中產生的效果。</p>

<h2 id="通用模板與特定晶片之間還有一份配置要交付">通用模板與特定晶片之間，還有一份配置要交付</h2>

<p>論文把輸入分成三類。第一類是自然語言文件，包含 user guide、design specification、時脈與接腳表；第二類是可能存在的通用 SDC 模板；第三類是設計資訊，包括時脈配置、階層名稱、接埠數、模式、工作條件和 signoff 所用的 margin。<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=2">原文第 2–3 頁</a></p>

<p>資料格式不同，維護責任也不同。規格敘述一個 IP 能做什麼，配置檔敘述這顆晶片選了什麼。工具需要同時知道「此模式最高允許多少頻率」與「本實例設定多少頻率」，才能比較設定是否落在允許範圍。單看文件容易產生過度完整的模板，單看配置又會失去允許範圍與例外條件。</p>

<p>原文的 clock configuration CSV 特別保留所有可能的時脈，以 period 等於零表示本次未使用。這個值在流程中帶有選擇語意：它要求生成器略過該時脈，接收端也應確認最後輸出沒有把它重新建立。對一顆具有多組介面實例的 SoC，這項規則能讓一份 IP 規格搭配多份配置使用，避免每個專案各維護一份已分岔的完整模板。</p>

<p>一條完整的交付路徑可以拆成下表。表中的資料責任是依公開方法推導的參考安排；組織名稱與簽核系統仍由採用團隊自行決定。</p>

<table>
  <thead>
    <tr>
      <th>工作位置</th>
      <th>輸入與可修改內容</th>
      <th>交出的材料</th>
      <th>接收端要回答的問題</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>IP 規格與模板</td>
      <td>模式、時脈範圍、訊號例外與版本</td>
      <td>文件、可選模板、允許值</td>
      <td>規格是否完整描述這次模式</td>
    </tr>
    <tr>
      <td>SoC 配置</td>
      <td>實例路徑、啟用時脈、period、margin</td>
      <td>clock／design configuration</td>
      <td>所選組合是否與 RTL 和 netlist 一致</td>
    </tr>
    <tr>
      <td>文件檢索與生成</td>
      <td>文件切片、檢索結果、配置與問題</td>
      <td>時脈清單、候選 SDC</td>
      <td>選中了哪些資料，漏了哪些項目</td>
    </tr>
    <tr>
      <td>整合審查</td>
      <td>配置、候選 SDC、設計物件</td>
      <td>修正後 SDC、問題清單與文字說明</td>
      <td>命令是否作用於正確物件及模式</td>
    </tr>
    <tr>
      <td>Synthesis／APR／STA</td>
      <td>設計、library、工作條件與已審查 SDC</td>
      <td>設計結果與時序報告</td>
      <td>約束是否完整，結果是否滿足專案要求</td>
    </tr>
  </tbody>
</table>

<p>這裡也保留了 RTL、功能驗證、DFT 與實體設計的分工。SDC 產生器接入的是約束交接；測試模式是否真的可達、reset 是否正確、scan 與 functional clocks 如何切換，仍要由對應設計與驗證工作提供答案。把測試模式選錯後再產生完整 Tcl，只會更快交出一套不適用的條件。</p>

<h2 id="三段生成把資料選擇和命令撰寫分開">三段生成把資料選擇和命令撰寫分開</h2>

<p>Marvell 公開的平台位於 virtual private cloud，使用 Python、LangChain、向量資料庫、embedding 與模型層。架構圖列出 Chroma 與 Mistral，但沒有給出足以重現全部結果的模型版號、完整參數和文件集合。能直接研究的是資料流及三段呼叫的安排。<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=4">原文第 4–6 頁</a></p>

<p>第一段先向 clock configuration 檢索，整理每個有效時脈的名稱、period 和 uncertainty。第二段把這份結果與 design configuration 的檢索內容串接，生成 <code class="language-plaintext highlighter-rouge">create_clock</code> 和 <code class="language-plaintext highlighter-rouge">create_generated_clock</code>。第三段再沿用第一段的結果，生成 <code class="language-plaintext highlighter-rouge">set_clock_uncertainty</code>，最後把第二、三段輸出合併。</p>

<p>第三段有一個容易忽略的特點：原文寫明它沒有再連接 retriever 或向量資料庫，而是透過前段結果與內部提示接續工作。因此，第一段整理出的清單成了共同輸入；如果這裡遺漏某個啟用時脈，後面兩段都可能一起遺漏它。把同一個清單傳給兩個呼叫，能減少各段自行重新選資料造成的分歧，也會讓前段錯誤同時傳播。</p>

<p>這解釋了分段方法的取捨。單次長提示把全部工作交給模型，實作較短，卻難以定位錯誤究竟發生在資料選擇、單位轉換或 Tcl 生成。三段方法留下可檢查的中間結果，但團隊要維護呼叫之間的資料格式、上下文與版本。增加呼叫數量帶來的是可定位性，同時增加延遲、模型費用與一致性工作。</p>

<p>2020 年的 <a href="https://arxiv.org/abs/2005.11401">RAG 原始研究</a>把參數化生成模型與外部檢索記憶結合，讓回答可利用模型之外的資料。SDC Creator 延續這種分工，但工程問題更尖銳：文件中一段語意相近的文字，可能屬於另一個 operating mode。相似度檢索能找到相關段落，配置是否適用仍需要另外核對。這項差異使「檢索到」與「可用於本實例」成為兩個要分開測量的結果。</p>

<p>參考設計可以在第一段之後增加一份結構化清單，每項固定記錄文件版本、時脈名稱、啟用狀態、period 單位、實例路徑，以及尚待工程師回答的欄位。模型適合抽取分散敘述與提出候選關係，精確數值的換算和已知配置規則則交給確定性的程式。這樣能把語言模型的彈性保留在文件理解，把可明確計算的部分變成可重跑的檢查。</p>

<h2 id="六個時脈的示範能檢查到哪一層">六個時脈的示範，能檢查到哪一層</h2>

<p>原文配置示範列出六個有效時脈，period 分別包含 10,000、2,000、1,000、20,000 與 500 ps；兩個 10,000 ps 時脈位於不同 side。第 7–8 頁展示時脈及 uncertainty 輸出，第 9–10 頁再展示由 SDC 轉成自然語言的審查路徑。<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=7">原文第 3、7–10 頁</a></p>

<p>以單位轉換為例，10,000 ps 是 10 ns，對應 100 MHz；500 ps 是 0.5 ns，對應 2 GHz。這兩個換算只用來檢查配置的量級。SDC 命令中的數字要採目前工具與 library 的時間單位；把 ps 數值直接填到以 ns 解讀的環境，會造成一千倍的差距。可讀的註解與正確 Tcl 語法都攔不住這種錯誤。</p>

<p>另一個檢查是物件對應。文件稱為某個 clock pin，整合後的 netlist 可能把它放進不同的階層。工程師應比對查詢到的物件數、實際 pin 名稱與時脈關係，確認生成器沒有把查無物件的查詢當作成功。這類檢查要連到設計資料，單靠重新閱讀生成的說明文字，容易讓同一項假設在兩種格式中重複出現。</p>

<p>公開的 <a href="https://github.com/parallaxsw/OpenSTA/blob/bebcb14c250dbd96203a8fa39ee39a3bc1997022/sdc/Sdc.tcl">OpenSTA SDC 命令實作</a>提供可參照的命令處理方式：<code class="language-plaintext highlighter-rouge">create_clock</code>、<code class="language-plaintext highlighter-rouge">create_generated_clock</code>、uncertainty 與 path exceptions 各自有參數及設計物件處理。它可用來建立開源對照實驗，商用工具的支援集合、library 和 signoff 方法仍按專案核對。團隊可以先檢查 Tcl 與物件，再檢查時脈完整性和 exception 的作用範圍，最後才比較 timing 結果。</p>

<p>反向文字生成的好處，是讓 IP、SoC 與時序工程師能用同一份可讀敘述討論頻率、waveform、margin 和關係。它也能指出文件缺少哪些資訊，讓 IP 團隊補回規格。審查時最好保留原始配置與工具報告作獨立參照，避免生成 SDC 和解釋 SDC 的兩個步驟共享同一個錯誤。</p>

<p>這些檢查可以放進一個具體的變更案例。假設同一顆 SoC 的第二版只改了其中一組 SerDes 的工作模式，原本停用的時脈改成啟用，實例位置也因頂層重構而改名。參考流程先對配置表做差異比較，列出新增的有效時脈及被替換的階層，再讓生成器處理這組實例。接收端會看到一份可預期的變更清單，方便檢查新增時脈是否真的出現、舊路徑是否還殘留在輸出中。</p>

<p>若一律用全文重新生成，沒有變動的其他實例也可能出現格式與命名差異，審查者需要從大量文字中找出實質變更。相反地，完全沿用舊輸出又會漏掉新的模式。按實例與配置保存中間結果，能讓重查工作跟著設計變更移動；代價是平台必須追蹤這份結果使用了哪個文件、哪份配置與哪次設計物件清單。此處是可實作的參考安排，原文只公開生成與審查的主要路徑。</p>

<p>錯誤也可以按發生位置處理。找不到文件中的限制時，先回到規格補資料；找得到規格卻對不上階層時，修正設計配置；命令可載入但時脈關係不符預期時，再由時序工程師處理語意。將這三種問題都丟回模型重新回答，會把原本可定位的問題變成多次隨機修改，也增加工具重跑的成本。平台應讓每次修正都回到負責的資料來源，再產生新的候選版本。</p>

<figure>
<a href="/images/ic-design-platform/2026-11-02/sdc-chain-review.svg"><img src="/images/ic-design-platform/2026-11-02/sdc-chain-review.svg" alt="第一段整理有效時脈，第二段加入設計配置產生 clock 命令，第三段沿用第一段結果產生 uncertainty；合併後分別核對來源配置、設計物件與工具報告，文字說明供人工審查。" width="700" height="940" /></a>
<figcaption>圖二：上半部依據<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=6">原文第 6 頁</a>的三段串接整理；下半部為參考設計，加入來源清單、物件數與工具報告的獨立核對。箭頭沒有表示執行時間比例。</figcaption>
</figure>

<h2 id="兩分鐘生成之後審查時間會決定交付收益">兩分鐘生成之後，審查時間會決定交付收益</h2>

<p>論文報告該範例的 SDC 生成少於兩分鐘，並把人工撰寫描述為需要多個小時。這是生成階段的 reported result；要評估團隊是否值得導入，還需把文件整理、配置建立、人工修正與 EDA 工作分別計帳。<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf#page=6">原文第 6 頁</a></p>

<p>以下是假設算例，用來看重用次數和審查成本的關係。假設人工每份配置需要 4 小時，包含 2 小時撰寫、1 小時審查及 1 小時工具工作。生成方案先投入 40 小時整理文件與配置格式，每份再花 2 分鐘生成、1.5 小時審查修正和相同的 1 小時工具工作。處理 <code class="language-plaintext highlighter-rouge">N</code> 份配置時，總工作量分別為：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>人工總時數 = 4 × N
生成方案總時數 = 40 + (2/60 + 1.5 + 1) × N
</code></pre></div></div>

<p>兩式以人時與工具等待可相加的簡化模型計算，並假設這些工作依序完成。生成方案每份省下約 1.467 小時，到第 28 份配置才開始回收前置投入；10 份時人工約 40 小時、生成方案約 65.33 小時，50 份時則約為 200 與 166.67 小時。若審查時間升到 3 小時，生成方案每份反而約 4.033 小時，再多的重用次數也難以回收這筆前置投入。</p>

<p>這個模型的用途是找敏感參數。模型每次快一分鐘，在 50 份配置中合計只省約 0.83 小時；每份審查少半小時，則合計省 25 小時。對這組假設，優先改善配置完整性、物件對應與錯誤定位，比繼續壓縮生成延遲更有效。若多個專案能同時審查，工作量與曆時又會分離，需另外計算排隊和人力瓶頸。</p>

<table>
  <thead>
    <tr>
      <th>合理方案</th>
      <th>適用情境</th>
      <th>主要代價</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>工程師客製 SDC</td>
      <td>少量特殊配置，規格常變且需要大量判讀</td>
      <td>每份重做，知識容易留在個人手上</td>
    </tr>
    <tr>
      <td>結構化資料與確定性模板</td>
      <td>模式規則穩定，可把選擇與計算明確編碼</td>
      <td>前期需整理 schema、例外及測試資料</td>
    </tr>
    <tr>
      <td>RAG 加分段生成</td>
      <td>規格分散在多份文件，需要抽取與轉換敘述</td>
      <td>檢索適用性、前段錯誤傳播及人工修正</td>
    </tr>
  </tbody>
</table>

<p>三者也可組合使用。規則已穩定的時脈 period 和 hierarchy mapping，適合以程式產生；文件中尚未結構化的條件，才交由檢索與模型提出候選。若導入後多數時間仍耗在重建同一張配置表，把這張表整理成正式輸入，通常比增加更多模型呼叫更有直接效果。</p>

<p>選擇方案時還要計入責任移動。IP 團隊把模板交出去後，可以減少各專案重複詢問，卻需更有紀律地維護模式說明與版本差異；SoC 團隊獲得較快的初稿，同時承擔配置資料的正確性；CAD 團隊則新增檢索、模型與工具銜接的維護工作。生成服務若由外部供應商提供，文件存放位置、模型存取與版本更新也會影響長期維護。採用者應以自己的資料權限與工具環境決定部署方式，原文的私有雲架構只提供一種公開案例。</p>

<p>收益會隨專案成熟度改變。在新 IP 導入初期，文件缺口和模式判讀通常較多，人工審查可能主導總時間；模式逐漸穩定後，結構化配置與模板的重用價值增加。若產品改版持續新增例外，則需重新評估前置整理成本。這使導入評估應涵蓋至少一次真實的規格變更，單次對固定文件產生一份漂亮 SDC，只能量到最窄的一段工作。</p>

<h2 id="與-rapidwright-比較重用的物件已經不同">與 RapidWright 比較，重用的物件已經不同</h2>

<p>先前的 <a href="/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff.html">RapidWright 模組交接文章</a>處理已完成局部實體實作的 DCP 與 metadata 重用；<a href="https://www.rapidwright.io/docs/PreImplemented_Module_Flow.html">官方預先實作流程</a>把局部建庫與系統組合分開。SDC Creator 則從文件和配置產生設計約束。兩者都把重複工程搬到可保存的材料上，但可以固定的內容不同。</p>

<p>RapidWright 保存的局部解已帶著實體條件，重用收益受相容位置、介面與全域連線影響。SDC Creator 保存的是規格到配置的轉換方式，收益受文件完整性、模式數與審查成本影響。一份可讀的 IP 規格，還需要經過配置選擇；一份可用的局部 DCP，還需要通過系統組合。比較兩家公司方法時，應分別衡量這些剩餘工作，才能找到真正可以移用的工程分工。</p>

<p>未來三個月的導入實驗，可固定一組文件與設計版本，比較人工、模板、RAG 三條路在相同配置集合上的總工時。測試集合應包括未啟用時脈、錯誤單位、改名階層、互斥模式，以及少量規格缺漏的案例；保留每次中間清單和人工修正，統計漏掉的有效時脈、誤建時脈、查無物件與不適用例外。如果模型的生成速度提高，人工修正卻持續增加，就應先縮小生成範圍，回到配置與模板的整理。</p>

<p>這條工作線也接回 <a href="/ic-design-platform/2026/10/26/marvell-3dic-physical-signoff-handoff.html">Marvell 3DIC 實體 signoff</a>：前段需要把 IP 的模式及限制交清楚，後段需要把不同 die 與封裝的實際連接組起來。共同能借鏡的是交付物要攜帶接收端需要的資訊；從文件抽取到實體連接，各階段仍使用不同的檢查方法。下一個具體問題，是規格變更後如何找出真正受影響的時脈與配置，讓重查範圍跟著變更內容縮小。</p>

<h2 id="證據範圍">證據範圍</h2>

<ul>
  <li>Marvell 主要來源為 Patricia Fong（Marvell）等人的 WISH 2024 十頁論文，頁面日期為 2024-10-23。它提供 5 nm／56G SerDes 示範、三段呼叫與輸出畫面；沒有公開完整程式、全部文件、模型版號、測試母體或整體量產導入規模。</li>
  <li>少於兩分鐘與人工多小時是原文對生成階段的描述；本文沒有把它換算成已證實的整體專案加速倍數、良率提升或首次投片成功率，也沒有執行商用 EDA、STA 或 PPA 實驗。</li>
  <li>結構化中間清單、獨立檢查與導入實驗屬參考設計；40 小時前置投入及各項審查工時是假設。附程式只重算成本模型，沒有驗證生成 SDC 的電路正確性。</li>
  <li>OpenSTA 為公開命令處理方式的對照，不能替代專案指定的商用工具、library、工作條件及 signoff 規則。自然語言反向說明也不能獨立證明原始 SDC 完整或正確。</li>
  <li>圖一依原文資料流整理，圖二的獨立核對部分是參考安排；兩張圖都不代表 Marvell 已公開的完整內部平台。</li>
</ul>

<h2 id="references">References</h2>

<ol>
  <li>Patricia Fong（Marvell）等，2024-10-23，<a href="https://designthesolution.org/wp-content/uploads/2024/10/fong_trinko-mechler_ai_hw_sdc_creator_wish_nov2024.min_.pdf">SDC Constraint Automation for Interface IP using Generative AI</a>。第 2–3 頁輸入與配置，第 4–6 頁架構及串接，第 7–10 頁輸出與審查。</li>
  <li><a href="https://arxiv.org/abs/2005.11401">Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks</a>，2020 年原始研究；用於說明生成與外部檢索資料的分工。</li>
  <li>AMD Research，<a href="https://www.rapidwright.io/docs/PreImplemented_Module_Flow.html">A Pre-implemented Module Flow</a>。比較資料重用的物件與剩餘整合工作。</li>
  <li>Parallax Software，<a href="https://github.com/parallaxsw/OpenSTA/blob/bebcb14c250dbd96203a8fa39ee39a3bc1997022/sdc/Sdc.tcl">OpenSTA Sdc.tcl</a>，固定 commit 的命令處理實作。</li>
  <li><a href="/examples/sota-r2g-cad/2026-11-02/sdc_handoff_cost.py">可重跑成本算例</a>與<a href="/examples/sota-r2g-cad/2026-11-02/sdc_handoff_cost.json">計算結果</a>，僅為假設模型。</li>
</ol>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="ic-design-platform" /><summary type="html"><![CDATA[Marvell 以文件檢索、時脈配置和串接生成產生特定 SoC 的 SDC，再轉成文字供工程師審查；把未使用時脈、實例路徑和時間單位先整理清楚，才能把省下的撰寫時間保留到實體設計交接。]]></summary></entry><entry><title type="html">OpenAI 如何用精確計數演算法挑戰二十七年的 ETH 假說</title><link href="https://rightson.github.io/ai-frontier/2026/10/31/openai-eth-refutation-algorithm-explained.html" rel="alternate" type="text/html" title="OpenAI 如何用精確計數演算法挑戰二十七年的 ETH 假說" /><published>2026-10-31T16:55:11+08:00</published><updated>2026-10-31T16:55:11+08:00</updated><id>https://rightson.github.io/ai-frontier/2026/10/31/openai-eth-refutation-algorithm-explained</id><content type="html" xml:base="https://rightson.github.io/ai-frontier/2026/10/31/openai-eth-refutation-algorithm-explained.html"><![CDATA[<p>一個有數百萬個布林變數的設計驗證問題，往往讓工程師在「有沒有解」與「多久才能知道」之間做取捨。SAT solver 透過子句學習、傳播與啟發式搜尋，已能解決許多工業問題；但在理論上，某些輸入是否必須耗費指數級時間，始終是另一個問題。</p>

<p>2026 年 10 月 26 日，OpenAI 公開論文 <em>The Exponential Time Hypothesis is False</em>，宣稱為任意固定子句寬度的 k-SAT 找到次指數時間的確定性精確計數演算法。Anthropic 隨後發表 Claude 獨立提出的 3-SAT 論證。兩份成果都附上 Lean 形式化，並引發理論電腦科學界的公開檢視。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=2">OpenAI 論文 §1</a>、<a href="https://openai.com/index/building-scientific-understanding-with-academic-communities/">OpenAI 公告</a>、<a href="https://github.com/anthropics/formal-math/blob/main/eth/README.md">Anthropic 原始說明</a>。</p>

<p>沿下圖先抓住整條論證的因果鏈：原始問題是精確計數；演算法先把依賴變成可以分離的結構，再以代數工具回推原始答案。後面每一章會拆開其中一段。</p>

<p><img src="/images/ai-frontier/2026-10-31/eth-proof-roadmap.svg" alt="從 k-CNF 的滿足解計數開始，經過代數轉換、共享線性摘要與局部分組，再利用插值及張量收縮取得次指數時間的論文推導路徑" /></p>

<p>圖一：依據 <a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=7">OpenAI 論文 §2–6 與 Appendix D</a>整理的概念路徑。方塊表示數學構造間的關係，並非可直接照順序串接的程式模組。</p>

<h2 id="eth-假設了什麼樣的計算極限">ETH 假設了什麼樣的計算極限</h2>

<p>先用最小的邏輯式理解 SAT。布林變數只有 0 與 1；<code class="language-plaintext highlighter-rouge">∨</code> 表示 OR，<code class="language-plaintext highlighter-rouge">∧</code> 表示 AND，<code class="language-plaintext highlighter-rouge">¬</code> 表示 NOT。下面的公式有三個變數：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>F(a,b,c) = (a ∨ b) ∧ (¬a ∨ c)
</code></pre></div></div>

<p>若 <code class="language-plaintext highlighter-rouge">a=0</code>，第一個子句強制 <code class="language-plaintext highlighter-rouge">b=1</code>，<code class="language-plaintext highlighter-rouge">c</code> 有兩種選擇；若 <code class="language-plaintext highlighter-rouge">a=1</code>，第二個子句強制 <code class="language-plaintext highlighter-rouge">c=1</code>，<code class="language-plaintext highlighter-rouge">b</code> 也有兩種選擇。因此，八種指派中恰有四種滿足公式，寫成 <code class="language-plaintext highlighter-rouge">#F=4</code>。</p>

<p>SAT 只問 <code class="language-plaintext highlighter-rouge">#F&gt;0</code>；<strong>#SAT 要求回傳精確的 <code class="language-plaintext highlighter-rouge">#F</code></strong>。計數結果包含可滿足性資訊，所以一個可精確計數的演算法也能回答 SAT。對一般公式逐一檢查 <code class="language-plaintext highlighter-rouge">n</code> 個變數，最多要面對 <code class="language-plaintext highlighter-rouge">2^n</code> 種指派；每增加一個變數，搜尋空間便加倍。</p>

<p>3-CNF 是每個子句至多三個 literal 的合取式。1999 年提出、於 2001 年系統化發表的 <strong>Exponential Time Hypothesis（ETH，指數時間假說）</strong>，主張 3-SAT 在最壞情況下沒有 <code class="language-plaintext highlighter-rouge">2^{o(n)}</code> 時間的演算法。<a href="https://www.sciencedirect.com/science/article/pii/S0022000000917276">Impagliazzo–Paturi</a>、<a href="https://cseweb.ucsd.edu/~paturi/myPapers/pubs/ImpagliazzoPaturiZane_2001_jcss.pdf">Impagliazzo–Paturi–Zane</a>。</p>

<p>這裡必須分清三個量級：</p>

<table>
  <thead>
    <tr>
      <th>時間量級</th>
      <th>例子</th>
      <th>演算法上的意思</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>指數時間</td>
      <td><code class="language-plaintext highlighter-rouge">2^n</code>、<code class="language-plaintext highlighter-rouge">1.3^n</code></td>
      <td>指數仍是 <code class="language-plaintext highlighter-rouge">Θ(n)</code>，改善底數依然符合 ETH</td>
    </tr>
    <tr>
      <td>次指數時間</td>
      <td><code class="language-plaintext highlighter-rouge">2^{n/√log n}</code></td>
      <td>指數除以隨 <code class="language-plaintext highlighter-rouge">n</code> 成長的因子，屬於 <code class="language-plaintext highlighter-rouge">2^{o(n)}</code></td>
    </tr>
    <tr>
      <td>多項式時間</td>
      <td><code class="language-plaintext highlighter-rouge">n^3</code></td>
      <td>比次指數更強的效率主張，足以涉及 P 與 NP 的核心問題</td>
    </tr>
  </tbody>
</table>

<p>以 1999 年 Schöning 的隨機區域搜尋為例，其 3-SAT 時間界約為 <code class="language-plaintext highlighter-rouge">poly(n)·(4/3)^n</code>，已大幅優於暴力搜尋，但仍維持 <code class="language-plaintext highlighter-rouge">2^{Θ(n)}</code> 的形式。<a href="https://ieeexplore.ieee.org/document/814612">Schöning, FOCS 1999</a>。ETH 就是在這條改良演算法的歷史之上，提出「是否存在無法跨越的指數下界」。</p>

<h2 id="openai-宣稱跨越了哪一道牆">OpenAI 宣稱跨越了哪一道牆</h2>

<p>OpenAI 論文的 Theorem 1.1 對每個<strong>固定</strong> <code class="language-plaintext highlighter-rouge">k≥2</code>，給出一個可精確計算 k-CNF 滿足解數量的確定性演算法。以 <code class="language-plaintext highlighter-rouge">n</code> 個變數與 <code class="language-plaintext highlighter-rouge">m</code> 個子句表示，論文摘要把時間界概括為：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>T(n,m) = (n+m)^{O_k(1)} · 2^{n/(log n)^{1/2+o(1)}}
</code></pre></div></div>

<p>主文更明確地陳述一般情況為 <code class="language-plaintext highlighter-rouge">poly_k(n,m)·2^{O_k(n log log n / √log n)}</code>；若 <code class="language-plaintext highlighter-rouge">m≤Dn</code>，可得到 <code class="language-plaintext highlighter-rouge">poly(n,m)·2^{O_{k,D}(n/√log n)}</code>。對固定 <code class="language-plaintext highlighter-rouge">k</code>、固定 <code class="language-plaintext highlighter-rouge">D</code>，這些指數都是 <code class="language-plaintext highlighter-rouge">o(n)</code>。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=2">論文 Theorem 1.1</a>。</p>

<p>原理很直接：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(n / √(log n)) / n = 1 / √(log n) → 0
</code></pre></div></div>

<p>因此，若演算法及其時間分析都成立，3-SAT 就具有 <code class="language-plaintext highlighter-rouge">2^{o(n)}</code> 演算法，與 ETH 直接矛盾。<strong>論文攻擊的是最壞情況的漸近成長率</strong>；複雜度符號中的常數、前置成本及大規模構造，都與實際執行時間有關。</p>

<h2 id="把滿足解改寫為可以運算的多項式">把滿足解改寫為可以運算的多項式</h2>

<p>第一個技術轉折，是把「滿足所有子句」改寫成代數求和。對一個 OR 子句，例如 <code class="language-plaintext highlighter-rouge">a∨¬b∨c</code>，定義滿足指示多項式：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Φ(a,b,c) = 1 − (1−a)b(1−c)
</code></pre></div></div>

<p>當 <code class="language-plaintext highlighter-rouge">a,b,c∈{0,1}</code> 時，子句成立就有 <code class="language-plaintext highlighter-rouge">Φ=1</code>，否則 <code class="language-plaintext highlighter-rouge">Φ=0</code>。把所有子句相乘，只有同時滿足全部子句的指派會留下 <code class="language-plaintext highlighter-rouge">1</code>：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#F = Σ_{x ∈ {0,1}ⁿ} Π_{e∈F} Φ_e(x)
</code></pre></div></div>

<p>這個等式完全精確，卻仍含有 <code class="language-plaintext highlighter-rouge">2^n</code> 個求和項。其用途是讓布林條件進入<strong>線性代數、多項式變形與插值</strong>的世界。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=8">論文 §2.2，式 (2.2)</a>。</p>

<p>假如所有子句天然分成幾群，且任一子句只使用其中一群的變數，計數便可分開做，再把群的答案相乘。例如 <code class="language-plaintext highlighter-rouge">(a∨b)∧(c∨d)</code> 的兩群各有三種合法指派，所以總共有 <code class="language-plaintext highlighter-rouge">3×3=9</code> 種。暴力枚舉全部四個變數需要考慮 16 種指派；兩群各枚舉四種，合計只需要八次局部指派檢查。一般化到 <code class="language-plaintext highlighter-rouge">r</code> 個、每群大小至多 <code class="language-plaintext highlighter-rouge">2n/r</code> 的群組，枚舉上界約為 <code class="language-plaintext highlighter-rouge">r·2^{2n/r}</code>。</p>

<p>但是實際公式大量交錯共享變數。硬把公式切群，跨群子句會使「各群計數相乘」失效。<strong>論文的主要構造，就是讓原本耦合的公式在特定代數變形下可以分群處理。</strong></p>

<h2 id="共享線性摘要如何切斷跨群依賴">共享線性摘要如何切斷跨群依賴</h2>

<p>先看一個可手算的假設算例：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>G = (a ∨ b) ∧ (b ∨ c) ∧ (c ∨ d)
</code></pre></div></div>

<p>把變數分成左群 <code class="language-plaintext highlighter-rouge">{a,b}</code>、右群 <code class="language-plaintext highlighter-rouge">{c,d}</code>。中間的 <code class="language-plaintext highlighter-rouge">(b∨c)</code> 連接兩群，所以直接把兩群的解數相乘會出錯。改為先固定共用狀態 <code class="language-plaintext highlighter-rouge">b</code>，局部問題就能分開：</p>

<table>
  <thead>
    <tr>
      <th>固定的 <code class="language-plaintext highlighter-rouge">b</code></th>
      <th style="text-align: right">左群可行指派</th>
      <th style="text-align: right">右群可行指派</th>
      <th style="text-align: right">乘積</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0</code></td>
      <td style="text-align: right">1（<code class="language-plaintext highlighter-rouge">a=1</code>）</td>
      <td style="text-align: right">2（<code class="language-plaintext highlighter-rouge">c=1</code>，<code class="language-plaintext highlighter-rouge">d</code> 任意）</td>
      <td style="text-align: right">2</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">1</code></td>
      <td style="text-align: right">2（<code class="language-plaintext highlighter-rouge">a</code> 任意）</td>
      <td style="text-align: right">3（<code class="language-plaintext highlighter-rouge">c∨d</code>）</td>
      <td style="text-align: right">6</td>
    </tr>
    <tr>
      <td>合計</td>
      <td style="text-align: right"> </td>
      <td style="text-align: right"> </td>
      <td style="text-align: right"><strong>8</strong></td>
    </tr>
  </tbody>
</table>

<p>這個例子的關鍵操作，是把原本跨群的相依，轉成少量共用量的枚舉。真正的演算法把共用量推廣成<strong>線性測量</strong> <code class="language-plaintext highlighter-rouge">y_g=C_g x_g</code>，其中 <code class="language-plaintext highlighter-rouge">x_g</code> 是第 <code class="language-plaintext highlighter-rouge">g</code> 群的變數向量、<code class="language-plaintext highlighter-rouge">C_g</code> 是整數矩陣。固定所有 <code class="language-plaintext highlighter-rouge">y_g</code> 後，變形後的每個子句可由其中一群的局部變數，以及其他群已固定的摘要值計算。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=10">論文 §2.4，式 (2.5)–(2.6)</a>。</p>

<p><img src="/images/ai-frontier/2026-10-31/eth-shared-summary.svg" alt="一條跨越左右變數群的子句讓計數無法直接相乘；固定共享測量後，各群局部加總，再將每種測量的乘積加總" /></p>

<p>圖二：依據 <a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=10">OpenAI 論文 §2.4</a>整理的計數分離機制；<code class="language-plaintext highlighter-rouge">b</code> 的小例子用於直覺說明，與論文正式構造使用的線性摘要不同。</p>

<p>其數學形式可以讀成：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>H(t) = Σ_y Π_{g=1}^r [Σ_{x_g:C_g x_g=y_g} A_g(x_g;y)]
</code></pre></div></div>

<p>括號內先算一群；群與群的結果相乘；最後加總所有共用測量。演算法時間主要受兩項控制：<strong>每群要枚舉多少局部指派</strong>，以及<strong>共享測量有多少種可能值</strong>。測量維度如果跟 <code class="language-plaintext highlighter-rouge">n</code> 一樣大，枚舉摘要仍可能回到原本的指數規模，所以低維摘要才是關鍵。</p>

<h2 id="用低次多項式插值取回原始答案">用低次多項式插值取回原始答案</h2>

<p>第二個技術轉折更精巧：論文在參數 <code class="language-plaintext highlighter-rouge">T</code> 上建立一族變形公式 <code class="language-plaintext highlighter-rouge">H(T)</code>，要求 <code class="language-plaintext highlighter-rouge">T=0</code> 時恢復原始問題，也就是 <code class="language-plaintext highlighter-rouge">H(0)=#F</code>；而在 <code class="language-plaintext highlighter-rouge">T=1,2,…,Q</code> 時，變形公式具有上一節所需的分群與摘要結構。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=9">論文 §2.3–2.5</a>。</p>

<p>想像一個簡單的二次多項式 <code class="language-plaintext highlighter-rouge">h(T)=u+vT+wT²</code>。即使 <code class="language-plaintext highlighter-rouge">T=0</code> 不容易直接求值，只要在其他位置取得足夠資訊，就能用插值反推常數項 <code class="language-plaintext highlighter-rouge">u=h(0)</code>。一般情況的困難是：若 <code class="language-plaintext highlighter-rouge">H</code> 的次數太高，直接蒐集所有插值點也會花很大代價。</p>

<p>OpenAI 的方法讓每個變數出現位置使用低次的<strong>替代線性形式</strong>，再在容易計算的點讀取若干個 Taylor 係數；這類利用函數值及導數資訊的恢復方法，稱為 <strong>Hermite interpolation</strong>。若 <code class="language-plaintext highlighter-rouge">H</code> 的次數上限為 <code class="language-plaintext highlighter-rouge">3nR</code>，以 <code class="language-plaintext highlighter-rouge">Q</code> 個容易處理的點分攤，直觀上每點需要的局部係數數目約與 <code class="language-plaintext highlighter-rouge">nR/Q</code> 同階。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=11">論文 §2.5，式 (2.4)、(2.7)–(2.9)</a>。</p>

<p>要同時達成「易於分群」與「替代式次數低」，論文 §4 以矩陣的低秩結構、適當的分組與多項式係數構造，使其他群對某個子句的影響可以用少量測量表示。這不是單靠插值就能加速：<strong>可插值的低次族與可分離的局部計數必須同時成立</strong>。前者負責把答案取回，後者負責降低每個取樣點的成本。</p>

<p>論文 §2.6 把成本拆成三項：取得 Taylor 資料所需的局部修正、枚舉共用測量、枚舉單一變數群。參數 <code class="language-plaintext highlighter-rouge">Q</code>、替代式次數 <code class="language-plaintext highlighter-rouge">R</code>、群數 <code class="language-plaintext highlighter-rouge">r</code> 及摘要比例 <code class="language-plaintext highlighter-rouge">τ</code> 必須共同調整，才能讓總指數低於任何固定比例的 <code class="language-plaintext highlighter-rouge">n</code>。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=12">論文式 (2.10)–(2.11)</a>。</p>

<h2 id="從任意-k-cnf-走到稀疏多項式計數">從任意 k-CNF 走到稀疏多項式計數</h2>

<p>前面描述的直接分離方法，需要處理變數出現次數或子句密度。論文的完整路徑進一步使用<strong>稀疏化與分支</strong>，把一般 k-CNF 拆成可加總、彼此不重複的子問題，再把子句違反情形轉成有限域 <code class="language-plaintext highlighter-rouge">F₂</code> 上的稀疏多項式方程。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=19">論文 §2.8–2.9、§5–6</a>。</p>

<p>這一段很容易誤讀。把一個方程看成 <code class="language-plaintext highlighter-rouge">P_i(x)=0</code>，數學上是在計算所有方程的共同零點。論文 §6 並非把每個原始子句逐一轉成一條新方程，那樣方程總數仍可能過大；它透過短的 parity tests 與確定性選取，讓約 <code class="language-plaintext highlighter-rouge">O(n)</code> 條稀疏方程便能辨認滿足指派。其選取過程又會呼叫 §5 的精確計數器，逐步縮減仍誤通過的非滿足指派。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=40">論文 §6.1–6.3</a>。</p>

<p>這裡有兩個成本需要一起守住：一方面，方程要少且每條方程的 monomial 數量要小；另一方面，將方程轉為可計數的代數形式後，還要保有適當的總次數。若只追求方程數量減少，卻讓每條方程變成密集且極高次，仍然無法推出次指數演算法。</p>

<h2 id="appendix-d-利用張量收縮收緊時間界">Appendix D 利用張量收縮收緊時間界</h2>

<p>OpenAI 論文主文已給出次指數時間的構造，Appendix D 再改用 <strong>tensor network contraction（張量網路收縮）</strong> 來得到較強的時間界。它把布林計數表示為由局部張量組成的網路；整體收縮等價於把內部索引全部求和，因而得到總計數。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=54">論文 Appendix D</a>。</p>

<p>最小例子是矩陣乘法中的共享索引：<code class="language-plaintext highlighter-rouge">Σ_j A_{ij}B_{jk}</code>。直接計算每個完整索引組合會很昂貴，但若能選好中間結果的合併順序，重複的局部計算便能共用。張量網路把這個思想推廣到許多局部因子的乘積與總和；網路的結構、切割方式及中間張量大小控制成本。</p>

<p>論文利用特定張量網路構造與收縮方式，在稀疏子句情況達成 <code class="language-plaintext highlighter-rouge">2^{O(n/√log n)}</code> 量級，在一般固定 <code class="language-plaintext highlighter-rouge">k</code> 的情況達成 <code class="language-plaintext highlighter-rouge">2^{O(n log log n/√log n)}</code> 量級，並維持多項式空間。這些是<strong>論文宣稱的最壞情況漸近界</strong>，尚非執行 SAT benchmark 的成績。</p>

<h2 id="anthropic-的獨立結果與-lean-實際檢查的內容">Anthropic 的獨立結果與 Lean 實際檢查的內容</h2>

<p>Anthropic 公開的 <em>A 2^{o(n)} Time Algorithm for 3-SAT</em> 宣稱，以確定性演算法在 <code class="language-plaintext highlighter-rouge">2^{O(n log log n/√log n)}</code> 時間內完成 #3-SAT。其 <a href="https://github.com/anthropics/formal-math/blob/main/eth/README.md">README</a> 摘錄了一個張量網路的遞迴改善構想：把網路節點排列成格點，對跨線操作做代數分解，再選擇較便宜的收縮與重新分組方式，使收縮成本參數在放大問題規模時下降。兩家公司都說其模型在 10 月 16 日獨立取得結果。<a href="https://hexagonmath.org/2610.00577v1">Anthropic 原始論文</a>。</p>

<p>兩份研究在目標上接近，但閱讀時應把<strong>自然語言主文、Lean 定理陳述、Lean proof kernel 通過、外部研究者確認數學含義</strong>分成四層。OpenAI 的 <a href="https://github.com/openai/math/blob/main/lean/docs/378.md">Lean scope note 378</a> 明列：目前機器檢查的是固定 <code class="language-plaintext highlighter-rouge">k</code> 下 <code class="language-plaintext highlighter-rouge">poly(L)·2^{O_k(n(log log n)^2/√log n)}</code> 的計數界，<code class="language-plaintext highlighter-rouge">L</code> 是輸入編碼位元長度；論文較強的時間界尚需對照其額外推導。Anthropic 則表示 <code class="language-plaintext highlighter-rouge">MainResults.lean</code> 的形式化結果已由 Lean 4 檢查，並安排以獨立 kernel <code class="language-plaintext highlighter-rouge">nanoda</code> 再核對，但 repo 也提醒讀者：程式本身不會自動確認 Lean 的定理陳述與論文自然語言敘述相同。</p>

<table>
  <thead>
    <tr>
      <th>檢查層次</th>
      <th>能回答的問題</th>
      <th>仍需額外做的工作</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>公式與論文</td>
      <td>演算法、時間界、假設如何陳述</td>
      <td>逐項重建推導、核對模型</td>
    </tr>
    <tr>
      <td>Lean 定理</td>
      <td>在形式系統中究竟宣稱什麼</td>
      <td>對照自然語言問題定義</td>
    </tr>
    <tr>
      <td>Lean kernel</td>
      <td>證明項是否推出已陳述的定理</td>
      <td>確認形式化與原始主張相符</td>
    </tr>
    <tr>
      <td>獨立學術審查</td>
      <td>整體主張能否由外部社群重現與接受</td>
      <td>公開反例搜尋、簡化證明、交叉檢查</td>
    </tr>
  </tbody>
</table>

<p>OpenAI 邀請 ETH 原始提出者 Russell Impagliazzo、Ramamohan Paturi，與 MIT 的 Ryan Williams 組織社群檢視。三人於 10 月 26 日的公開聲明明確表示，參與檢視<strong>並不構成對結果的認證</strong>。截至 10 月 31 日，公開資料顯示已有簡化講義、形式化重建與小型範例測試，尚無三人審查團隊的最終結論。<a href="https://ethdiscussion.blog/category/uncategorized/">公開審查聲明</a>、<a href="https://papex.org/blog/eth-refutation-what-has-been-checked">審查進度整理</a>。</p>

<h2 id="推翻-eth-之後哪些結論會改變">推翻 ETH 之後哪些結論會改變</h2>

<p>假設 ETH 最終被確認為假，最直接的變化是演算法下界的解讀。凡是寫成「<strong>若 ETH 成立，則某問題在某個參數下需要指數時間</strong>」的定理，原本的條件式邏輯仍正確；但其前提失效，便不能再藉此斷言該問題具有相同的實際困難程度。某些歸約也可能反過來提供新的演算法：若能把問題轉成大小僅線性增加的 SAT instance，就有機會繼承次指數時間界。<a href="https://cseweb.ucsd.edu/~paturi/myPapers/pubs/ImpagliazzoPaturiZane_2001_jcss.pdf">原始稀疏化與歸約論文</a>。</p>

<p>這裡的規模保存十分重要。假設某問題的輸入規模是 <code class="language-plaintext highlighter-rouge">N</code>，歸約後 SAT 變數數量變成 <code class="language-plaintext highlighter-rouge">n=N²</code>，那麼 <code class="language-plaintext highlighter-rouge">2^{o(n)}</code> 只能推出 <code class="language-plaintext highlighter-rouge">2^{o(N²)}</code>，無法直接推出 <code class="language-plaintext highlighter-rouge">2^{o(N)}</code>。複雜度分類沿著歸約傳遞時，必須保留實際的參數膨脹。OpenAI 論文本身也特別提醒：一般多項式時間歸約不足以把所有 NP 問題都變成相同參數的次指數演算法。<a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf#page=3">論文 §1</a>。</p>

<p>更長遠的研究問題，是這種代數分離能力能否延伸至一般 circuit、非固定寬度約束、最佳化以及計數以外的結構。若只能在特殊的局部因子網路裡壓低收縮成本，其應用便會相對集中；若能形成一般性的結構參數與演算法工具，相關領域就可能出現新的速度上界。</p>

<h2 id="eda-工程會先受益於哪一類問題">EDA 工程會先受益於哪一類問題</h2>

<p>SAT 與 #SAT 在晶片設計相關工作中分別對應不同需求。等價檢查、bounded model checking、部分 ATPG 流程主要關心是否有反例；design-space analysis、模型計數與機率評估則可能需要知道有多少組配置滿足限制。它們的形式化模型、量詞、位元向量與電路展開規模各不相同，直接把 SAT 複雜度改良換算成工具加速倍率，會忽略工作負載結構。</p>

<p>可採取三種不同的工程方向：</p>

<table>
  <thead>
    <tr>
      <th>方向</th>
      <th>可能得到的收穫</th>
      <th>必須付出的成本</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>現有 CDCL／SMT／Formal solver</td>
      <td>延續成熟的學習、傳播、incremental solving 與產業工作負載最佳化</td>
      <td>最壞情況仍可能具有指數時間</td>
    </tr>
    <tr>
      <td>代數計數與張量方法</td>
      <td>探索可利用因子局部性、結構參數與共享中間結果的問題</td>
      <td>張量收縮順序、記憶體與巨大常數可能吃掉優勢</td>
    </tr>
    <tr>
      <td>混合式求解器</td>
      <td>用現有 solver 化簡，再在特定子問題使用精確計數或代數分解</td>
      <td>需要辨認何種 instance 值得切換與支付轉換成本</td>
    </tr>
  </tbody>
</table>

<p>可以把實驗問題設得很具體：從公開的小型 RTL／Formal benchmark 產生 CNF，固定 <code class="language-plaintext highlighter-rouge">n</code>、<code class="language-plaintext highlighter-rouge">m</code>、子句寬度、連結程度、可滿足比例與編碼方式，對照現有 SAT solver、#SAT counter 與研究原型的 runtime、記憶體峰值以及結果一致性。若演算法論證首先只在極大 <code class="language-plaintext highlighter-rouge">n</code> 才展現漸近優勢，工程上最值得抽取的反而可能是<strong>某種可移植的局部代數化簡策略</strong>，而非立刻替換主求解器。</p>

<p>本站先前的 <a href="/ai-frontier/2026/10/07/harness-engineering-coding-agents.html">Coding Agent 與 harness 機制研究</a> 討論模型輸出如何經過工具與外部結果檢查，才成為工程上可使用的工作成果。這次事件把相同問題推向數學研究：探索者可以是 AI，但可供後人使用的成果仍須有可重建的定義、演算法與正確性論證。</p>

<h2 id="接下來一年可驗證的研究走向">接下來一年可驗證的研究走向</h2>

<p>到 2027 年 10 月，可以沿三條公開紀錄辨認這次突破究竟改變了多少電腦科學。第一，獨立學者是否完成定理敘述、計算模型與複雜度上界的逐項對照，並產生較短、可重建的證明。第二，是否有人將構造轉成可執行 solver，在明確界定的問題族上超越既有方法。第三，是否出現利用此算法的新型歸約或計數上界，而且轉換後的參數仍保有次指數改善。</p>

<p>也存在另一種走向：即使 ETH 的數學反例成立，過大的常數與特殊的構造成本仍讓產業求解器繼續以 CDCL、局部搜尋和問題特定最佳化為主。這種結果會保留理論突破的價值，同時限制短期工程影響；若未來出現可在實際 SAT／EDA 測試上穩定獲益的實作，才需要調整這項判斷。</p>

<p>OpenAI 與 Anthropic 這次共同呈現了一個新的研究流程：模型生成候選定理與演算法，形式化系統檢查其數學敘述，再由研究社群把結果轉成可以理解、延伸和挑戰的知識。最有力量的後續成果，將是研究者能以更短的證明、更好的演算法，回答原始論文尚未解決的「為什麼可以這麼快」。</p>

<h2 id="證據範圍">證據範圍</h2>

<ul>
  <li>本文導讀以 OpenAI 2026 年 10 月 25 日修訂的 67 頁論文為主，並輔以 Anthropic 10 月 27 日論文與兩方公開的 Lean 說明。主文的較強時間界、形式化檢查範圍和社群審查狀態分別列出；目前沒有把廠商主張當作已由獨立審查確立的定理。</li>
  <li>分群枚舉與固定 <code class="language-plaintext highlighter-rouge">b</code> 的算例均屬教學用簡化模型，不是 OpenAI 正式的低次替代式、線性測量矩陣或完整張量收縮演算法；文章介紹的是核心機制與各章推導關係，並非對 67 頁全部引理的獨立數學驗算。</li>
  <li><code class="language-plaintext highlighter-rouge">2^{o(n)}</code> 仍可能遠慢於現有求解器，也不代表 P=NP、不直接危及依賴其他困難性假設的密碼系統，或讓一般 NP 問題透過任意多項式歸約得到 <code class="language-plaintext highlighter-rouge">2^{o(N)}</code> 時間。</li>
  <li>截至 2026 年 10 月 31 日，社群已有公開研討與部分重建工作，尚無三位審查召集人的最終正式認證；OpenAI 與 Anthropic 內部 AI 探索的具體實驗流程依各自披露描述。</li>
</ul>

<h2 id="參考資料">參考資料</h2>

<ol>
  <li>OpenAI, <a href="https://mathcommunity.github.io/oai-math-revised/papers/The-Exponential-Time-Hypothesis-is-False-October-25-2026/paper.pdf"><em>The Exponential Time Hypothesis is False</em></a>，2026 年 10 月 17 日初稿，10 月 25 日修訂，67 頁；主文 §2–6 與 Appendix D 為本文主要技術依據。</li>
  <li>OpenAI, <a href="https://openai.com/index/building-scientific-understanding-with-academic-communities/"><em>Working with academic communities to build scientific understanding</em></a>，2026 年 10 月 26 日；公開合作與發表時序。</li>
  <li>OpenAI, <a href="https://github.com/openai/math/blob/main/lean/docs/378.md">Lean Scope Note 378</a>，形式化涵蓋的定理與較弱的時間界。</li>
  <li>Anthropic, <a href="https://hexagonmath.org/2610.00577v1"><em>A 2^{o(n)} Time Algorithm for 3-SAT</em></a>，2026 年 10 月 27 日；<a href="https://github.com/anthropics/formal-math/blob/main/eth/README.md">論文與 Lean 說明</a>。</li>
  <li>Impagliazzo, Paturi, <a href="https://www.sciencedirect.com/science/article/pii/S0022000000917276"><em>On the Complexity of k-SAT</em></a>，JCSS，2001 年；ETH 的定義。</li>
  <li>Impagliazzo, Paturi, Zane, <a href="https://cseweb.ucsd.edu/~paturi/myPapers/pubs/ImpagliazzoPaturiZane_2001_jcss.pdf"><em>Which Problems Have Strongly Exponential Complexity?</em></a>，JCSS，2001 年；稀疏化與細粒度歸約。</li>
  <li>Schöning, <a href="https://ieeexplore.ieee.org/document/814612"><em>A Probabilistic Algorithm for k-SAT and Constraint Satisfaction Problems</em></a>，FOCS 1999；較早的指數時間改良演算法。</li>
  <li>Impagliazzo, Paturi, Williams, <a href="https://ethdiscussion.blog/category/uncategorized/"><em>ETH Refutation: Examination and Discussion</em></a>，2026 年 10 月 26 日；獨立公開檢視聲明。</li>
  <li>Papex, <a href="https://papex.org/blog/eth-refutation-what-has-been-checked"><em>Has the ETH refutation been verified?</em></a>，2026 年 10 月 31 日；社群檢視進度彙整。</li>
</ol>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="ai-frontier" /><summary type="html"><![CDATA[從可手算的 SAT 範例出發，拆解 OpenAI 以共享線性摘要、低次多項式插值和張量收縮取得次指數時間的主張，並比較 Anthropic 的形式化成果及其對演算法與 EDA 的意義。]]></summary></entry><entry><title type="html">Eunomia 讓 RDMA 用動態 bitmap 承受常態多路徑失序</title><link href="https://rightson.github.io/networking/2026/10/28/eunomia-dynamic-bitmap-rdma-reordering.html" rel="alternate" type="text/html" title="Eunomia 讓 RDMA 用動態 bitmap 承受常態多路徑失序" /><published>2026-10-28T19:08:18+08:00</published><updated>2026-10-28T19:08:18+08:00</updated><id>https://rightson.github.io/networking/2026/10/28/eunomia-dynamic-bitmap-rdma-reordering</id><content type="html" xml:base="https://rightson.github.io/networking/2026/10/28/eunomia-dynamic-bitmap-rdma-reordering.html"><![CDATA[<p>大型 RDMA fabric 一直有一個互相牽制的選擇。ECMP 把一條 flow 固定在一條路徑上，封包大致有序，RNIC 容易維持零複製與低延遲；但粗粒度雜湊遇到 elephant flow 或路徑不等長時，仍可能讓一條 uplink 壅塞、另一條閒置。Packet spraying 把每個封包分散到不同路徑，可以更快填平流量，代價是 receiver 看見的 packet sequence number（PSN）不再連續。</p>

<p>傳統 lossless RDMA 常把 PSN 缺口當成遺失。若 receiver 收到 8、10、11，卻還沒看到 9，它可能丟棄後續封包，sender 再以 go-back-N 從 9 開始重傳。這個機制面對偶發掉包尚可理解；當失序本身就是負載平衡的正常結果時，卻會把已經抵達的資料反覆丟棄，讓頻寬、尾延遲與 PFC 壓力一起惡化。</p>

<p><a href="https://arxiv.org/abs/2412.08540">Eunomia</a> 的提案不是消除失序，而是在 RNIC 收到資料、送進 host memory 前先記住哪些 PSN 已經到達。它的核心取捨很精確：不替每條 queue pair（QP）常駐配置足以覆蓋最壞失序範圍的 bitmap，只在真的發生失序時，向共享片上記憶體逐塊索取空間。這使 packet spraying、deflection routing 與不規則拓樸有機會成為日常工具，而不是只有應急時才敢啟用的功能。</p>

<p>2018 年的 <a href="https://www.usenix.org/conference/nsdi18/presentation/lu">MP-RDMA</a> 已經用端點 bitmap 與選擇性確認承受多路徑失序；2023 年的 <a href="https://conferences.sigcomm.org/sigcomm/2023/program.html">ConWeave</a> 則把 reorder queue 放到目的端 ToR。Eunomia 的新問題是：當資料中心有數十萬到百萬條 QP，而且每條連線的失序跨度差異很大，能否讓片上 SRAM 成本跟「當下真的失序」的連線數量與跨度一起伸縮？</p>

<p><img src="/images/networking/2026-10-28/eunomia-end-to-end-path.svg" alt="Eunomia 的端到端資料路徑" /></p>

<h2 id="多路徑把偶發失序改成持續工作負載">多路徑把偶發失序改成持續工作負載</h2>

<p>先區分三種看似相近、實際代價不同的情況。</p>

<p>第一種是封包遺失。PSN 9 沒有抵達，receiver 永遠看不到它，最後必須由 timeout、NACK 或 selective repeat 觸發重傳。第二種是短暫重排。PSN 10 先到，9 稍後抵達；receiver 只要暫時保留 10 的到達狀態，就能避免重傳。第三種是大範圍失序。Packet spraying 讓 20、33、17、41 交錯抵達，缺口不只一個，而且最大 PSN 與目前連續前綴之間可能持續擴張。</p>

<p>固定大小 bitmap 的索引很簡單：PSN 減去 Head，或直接做模數映射。困難是尺寸。若 bitmap 太小，跨越視窗的封包仍需丟棄；若為每條 QP 都按最壞情況配置，幾乎從不失序的連線也會吃掉 SRAM。以論文比較口徑，100 Gb/s、8 微秒 RTT、100 個封包的 bandwidth-delay product 下，IRN 每條連線需要 125 bytes bitmap 加約 20 bytes metadata。把 145 bytes 乘上一百萬條 QP，就是約 145 MB；這遠高於一般 RNIC 願意留給 reorder state 的片上容量。</p>

<p>Eunomia 把接收工作分成三層。Packet driver 先辨識 Head、Last 與 PSN；Hybrid Dynamic（HD）bitmap 記錄已到達的序號；memory controller 管理所有連線共用的 2-byte blocks、metadata 與空閒表。資料本體仍可依原有 DMA 路徑寫入 host memory，Eunomia 主要保存「到達與否」，不是複製整個 payload。</p>

<p>Sender 需為每個 message 增加 33 bits：32-bit Head 指出訊息的第一個 PSN，1-bit Last 標示最後一包。這個開銷不能只報一個百分比，因為它依 payload 大小而變。若 payload 為 256 bytes，33 bits 約占 1.61%；1 KiB 時約 0.40%；4 KiB 時約 0.10%。計算與假設已放在<a href="/scripts/experiments/eunomia_bitmap_budget.py">可重現腳本</a>與<a href="/scripts/experiments/eunomia_bitmap_budget.results.json">輸出結果</a>。</p>

<h2 id="circular-與-linear-區段讓-bitmap-擴張時免搬舊狀態">Circular 與 linear 區段讓 bitmap 擴張時免搬舊狀態</h2>

<p>純 circular bitmap 容易回收。假設視窗有 8 bits，Head 是 0，已收到 0、1、2、4、6；當 3 抵達後，連續前綴可以推進到 5，前四個位置就能循環使用。問題出在擴張：如果新封包 PSN 15 抵達，8-bit 視窗容納不了。直接把 circular bitmap 從 8 擴到 16 bits，既要配置新區域，也可能要搬移與重新映射原有 bits，資料路徑硬體會變複雜。</p>

<p>Eunomia 將 bitmap 分成 circular portion 與 linear portion。第一個區段維持既有索引與回收；失序跨度超過容量時，memory controller 在尾端配置一個 linear block，讓新 PSN 先落在不會改變舊映射的位置。後續若又超過，再繼續接 block。等 circular 區段的缺口補齊、Head 前進並釋放舊區段後，linear portion 才合併成新的 circular portion。</p>

<p><img src="/images/networking/2026-10-28/eunomia-hybrid-bitmap.svg" alt="Hybrid Dynamic bitmap 的擴張與合併" /></p>

<p>用一個完整例子看資料流。QP 收到 message 的 Head=100、Last=115。100 到達時仍是 in-order，不需配置 bitmap；101、102 依序抵達也一樣。接著 108 先到，receiver 發現 103–107 是缺口，才配置第一個 16-bit block與 metadata，將相對位置 8 標成 1。112 到達時仍在同一 block；若 120 屬於下一個 message，就由新的 Head 隔離，不得誤用前一個 message 的窗口。</p>

<p>現在 103、104、105 陸續抵達。Head 可以前進，但 106、107 還沒到，所以 108 之後的 bits 仍保留。若 115 到達並帶 Last=1，receiver 已知道 message 的上界，仍不能提前完成；要等 106、107、109–111、113、114 全部補齊，bitmap 顯示從 Head 到 Last 連續，才把 completion 交給應用程式。若缺口長時間不補，timeout 仍回到既有 go-back-N 或 selective repeat，而不是假裝所有缺口都是重排。</p>

<p>這個機制同時處理兩個尺度。快路徑只做 bit set、Head 推進與 ACK/SACK；慢一點的配置路徑才處理 block 尋找、metadata 更新、區段合併。論文原型的 master memory array 以 2-byte block 管理，共示範 1024 個 blocks；每條連線保留 4-byte HD bitmap address。當連線第一次失序，controller 尋找 24 個連續 blocks 建立 48-byte metadata。作者也明列限制：若找不到連續 metadata 空間，非連續 linked metadata 還是後續工作。</p>

<h2 id="記憶體節省來自只替失序連線付-metadata">記憶體節省來自只替失序連線付 metadata</h2>

<p>Eunomia 的節省不是「每條連線的 bitmap 永遠更小」，而是把常駐成本變成共享池。沒有失序的 QP 只保留 4-byte 位址；active QP 才付 48-byte metadata 與實際 bitmap blocks。論文表格報告 Eunomia 每連線約 4–82 bytes，範圍取決於是否 active 與 bitmap 擴張程度。</p>

<p>要判斷何時划算，可以先做一個清楚的假設模型。以下不是論文的硬體量測，而是以一百萬條 QP、固定方案每條 32-byte bitmap 加 9-byte metadata、Eunomia 每條 4-byte base state、active QP 另付 48-byte metadata，加上每 16 PSN 使用 2 bytes block，計算共享池需求。</p>

<p>當 active QP 平均需要 64 bits bitmap 時，固定方案為 41 MB。若 5% QP 失序，動態方案約 6.8 MB；20% 時 15.2 MB；60% 時 37.6 MB；100% 時反而升到 60 MB。兩者交會約在 active ratio 66.1%。平均跨度只有 16 bits 時，交會點約 74%；跨度 256 bits 時，交會點降到約 46.3%。</p>

<p><img src="/images/networking/2026-10-28/eunomia-memory-budget.svg" alt="一百萬條 QP 的記憶體預算假設" /></p>

<p>這個計算揭露三個部署問題。第一，active ratio 比峰值 reorder depth 更重要；少數很深的失序可能仍比多數輕微失序便宜。第二，metadata 是固定稅。bitmap 很小時，48-byte metadata 甚至比 bits 本身大。第三，共享池需要公平性。若少數長 flow 無上限擴張，它們會耗盡 blocks，使新失序連線拿不到狀態。Eunomia 因此允許設定每連線上限；達上限後的新封包必須被丟棄或交回原有 loss recovery。</p>

<p>論文也展示這個反轉：在 20 條連線的 microbenchmark 中，隨失序連線比例上升，動態配置一開始省記憶體；超過約六成後，metadata 與配置成本可能讓總量高於固定配置。這不是設計失敗，而是動態配置的適用邊界。部署前要量測的是「同時 active 的失序 QP 分布」，而不是只看平均 packet reordering rate。</p>

<h2 id="配置器必須在封包時間內回答三個問題">配置器必須在封包時間內回答三個問題</h2>

<p>共享狀態省下容量後，控制器必須回答三個原本不存在的問題：誰先取得 block、何時歸還、拿不到時怎麼退回。第一個問題是 admission。假設 100 Gb/s port 收到 1,500-byte packets，線速約每 120 奈秒出現一包；即使硬體平行處理，第一次 OOO 同時觸發 metadata 建立與 block 搜尋，也不能讓單一 allocator 鎖住所有 queue。實作上需要把 free-block bitmap 分 bank、把 QP hash 到不同 allocation queue，或為每個 ingress pipeline 預留小型 local cache。否則 Eunomia 雖減少 SRAM，卻可能把突發失序轉成 controller head-of-line blocking。</p>

<p>第二個問題是 reclamation。bitmap 的 bit 可以隨 Head 前進而清除，metadata 卻不能因暫時沒有缺口就立刻釋放。若釋放門檻太積極，同一條多路徑連線下一個 burst 又要重新配置，allocator traffic 會振盪；若保留太久，已回復有序的 QP 仍占著 48-byte metadata。可行策略是加 idle epoch：連續若干 RTT 沒有 OOO，才把 block 歸還共享池。以 8 微秒 RTT、保留 32 RTT 為例，狀態至少留 256 微秒，能吸收微突發，又不至於在流結束後停留數秒。這個數字應由 trace 中的 reorder burst gap 校準，不能只憑平均流長設定。</p>

<p>第三個問題是 exhaustion。當 free blocks 低於保留水位，控制器可依序採取四級動作：停止替既有 QP 擴張、拒絕新 metadata、對越界 PSN 回 NACK、最後退回既有 go-back-N。這條 failure path 必須明確，因為「失序支援暫時退化」比「部分 QP 永遠等不到 completion」更容易營運。遙測至少要提供 pool occupancy、allocation latency、allocation miss、每 QP cap hit、bitmap merge 次數與 fallback 次數；若只能看到整體 FCT，事故發生時無法分辨是 fabric 壅塞、真正掉包，還是 reorder state 被耗盡。</p>

<h3 id="一次-256-psn-失序如何消耗共享池">一次 256-PSN 失序如何消耗共享池</h3>

<p>沿用 16-bit、2-byte block。QP 首次看到超前封包時，配置 48-byte metadata 與一個 2-byte block；若最遠 PSN 距 Head 為 255，需要 16 個 blocks，也就是 32 bytes bitmap。加上 metadata，這條 active QP 使用 80 bytes，再加每 QP 原有的 4-byte address，共 84 bytes。這與論文表中的 4–82 bytes 只差口徑：表格把常駐 address 與 active 結構分開表達；本文預算圖則把兩者都算進全系統總量。</p>

<p>如果同一百萬 QP 中只有一萬條出現這種最深跨度，額外 active state 約 0.8 MB，加上所有 QP 的 4 MB base address，仍遠低於每條固定配置 41 bytes 的 41 MB。若六十萬條都達到 256-PSN 跨度，active state 就約 48 MB，再加 base 4 MB，已超過固定方案。這也說明 active ratio 與 span 必須聯合觀察：只報「最大失序 256 包」會高估容量，只報「平均失序連線 5%」又可能漏掉少數連線持續占滿 pool。</p>

<p>Block size 也不是越小越好。2-byte block 的內部浪費低，卻增加鏈接、allocation 與 merge 次數；64-byte block 更容易以 SRAM row 讀寫，但只有幾個 OOO packets 時會浪費大部分 bits。產品化時可採兩級 slab：常見小跨度先拿小 block，超過門檻後換成大 block；代價是 controller 還要處理兩種 free list 與遷移。Eunomia 論文選擇固定 2-byte block，先證明資料結構可擴張，沒有宣稱已找到所有 RNIC 的最佳粒度。</p>

<h3 id="連線與裝置故障不能留下幽靈狀態">連線與裝置故障不能留下幽靈狀態</h3>

<p>正常 close 時，QP context 可以帶著 bitmap 一起回收；異常情況更麻煩。若 receiver reset，sender 仍可能重送舊 PSN，新建立的 QP 必須用 generation 或 connection identity 隔離舊封包，否則過期封包可能把新 bitmap 的 bit 設成 1。若 memory controller 更新 metadata 到一半發生錯誤，Head、Tail 與 block owner 也要能以一致順序重建，不能讓同一 block 同時屬於兩條 QP。</p>

<p>一個保守的寫入次序是先標記 block owner，再更新相對地址，最後才公布新的 Tail；回收則先讓 QP 不再引用 block，再清 owner。任何中途失敗都偏向暫時洩漏容量，而不是錯把別人的到達狀態當成自己的資料。洩漏可由背景 scrubber 依 owner 與 QP generation 回收；跨連線錯配則可能直接破壞 RDMA 的資料正確性。這些 recovery 行為尚未在論文的單 FPGA packet driver 中完整驗證，卻是從研究原型走向 NIC firmware 時最先要補的項目。</p>

<p>實際驗收還應把這些計數器與 flow completion 串在一起。當 p99 上升時，若 allocation miss 先升、PFC pause 沒升，問題更可能在端點狀態；若 pause 與 queue depth 同時升，則應先處理 fabric hotspot。這種可觀測性可避免把所有尾延遲都歸咎於 packet spraying。</p>

<h2 id="sack-阻止正常重排觸發丟包修補">SACK 阻止正常重排觸發丟包修補</h2>

<p>只記 bitmap 還不夠，sender 必須知道缺口附近哪些封包已經到達。Eunomia 的 ordering feedback 與 congestion feedback 分開：ACK 表示新的連續前綴，SACK 表示超前抵達的 PSN，NACK 表示 receiver 無法處理或視窗越界。論文模擬中，ordering ACK 流量約帶來 5% 額外負載；壅塞控制仍由 DCQCN 等既有機制負責。</p>

<p>分離兩種回饋很重要。若把 SACK 視為壅塞訊號，packet spraying 造成的路徑延遲差會讓 sender 無謂降速；若把所有缺口都視為重排，真正遺失又會拖到 timeout。Eunomia 的判斷是先保留 OOO 到達狀態，讓短暫缺口有時間補齊；既有 timeout 與 recovery 邏輯仍負責證明「不是只晚到，而是需要重傳」。</p>

<p>這也解釋為什麼 Eunomia 與 <a href="/networking/2026/10/21/irn-selective-retransmission-rdma-completion.html">上一篇 IRN 深度文</a>互補。IRN 用 BDP 大小的固定 bitmap 與 selective retransmission，目標是讓有損網路不必依賴 PFC；Eunomia 把 bitmap 改成依失序需求擴張，目標是承受 packet spraying 的更大 reorder window。兩者都避免 go-back-N 浪費，但容量模型與首要故障不同。</p>

<p>在作者的 ns-3 設定中，網路是 8×8 Clos、128 hosts、100 Gb/s links、1 微秒 propagation delay、1:2 oversubscription、9 MB shared switch buffer，並開啟 PFC 與 DCQCN。以 AliStorage 工作負載比較時，細粒度負載平衡加 Eunomia 相對 ECMP 的平均 FCT 最多降低 85%、尾端最多 91%；相對 ConWeave 最高約降低 53% 與 55%。作者也報告 PFC pause 最多下降約 99%，原因是 packet spraying 先降低 hotspot，再由 endpoint 吸收重排。</p>

<p>這些數字證明的是「在該模擬環境裡，端點可承受失序後，細粒度負載平衡的上限很高」，不是所有 fabric 都會得到相同幅度。工作負載、oversubscription、buffer、ECMP entropy、路徑延遲差與 RNIC implementation 都會改變結果。更保守的驗證方式，是先重播自己的 flow size distribution 與 path delay trace，再比較 p50/p99 FCT、pause duration、SACK bandwidth、bitmap occupancy 與 block allocation failure。</p>

<h2 id="完成語意使-send-與-write-付出不同代價">完成語意使 SEND 與 WRITE 付出不同代價</h2>

<p>RDMA 的困難不只在封包是否到齊，也在何時可以對應用程式宣告完成。SEND/RECV 比較直觀：receiver 已知道 message boundary，可以讓 OOO data 寫入預定位置，但 completion queue entry 必須等 Head 到 Last 全部連續。Eunomia 的 Last bit 讓 RNIC 知道最後一個 PSN，不會因較後封包先到就過早完成。</p>

<p>RDMA WRITE 更敏感。遠端 CPU 通常不參與，而且應用程式可能把最後一筆 write 或 immediate data 當成「前面的內容都可讀」的信號。若末包先經較快路徑抵達，單靠 receiver bitmap 雖知道還有缺口，卻可能已把完成可見性暴露給軟體。</p>

<p>Eunomia 的主要方案在 sender 端延後末包：先送前面所有 packets，等到它們都被連續確認，再送 Last packet。這維持既有 receiver completion 語意，但為 WRITE 多付一個 RTT。若 RTT 為 8 微秒，短 message 的完成時間可能直接增加約 8 微秒；長 flow 已經跨越多個 RTT 時，相對比例較小。</p>

<p>替代方案是 receiver 暫存末包，直到 bitmap 連續後才 DMA。它省掉 sender 額外 RTT，卻要讓 RNIC 保存 payload 或額外做一次 PCIe 搬移，並處理暫存空間耗盡。這是典型的端到端取捨：等待放在 sender，成本是 latency；等待放在 receiver，成本是 buffer、PCIe traffic 與更複雜的完成閘門。</p>

<h2 id="三個方案把等待與狀態放在不同位置">三個方案把等待與狀態放在不同位置</h2>

<p><img src="/images/networking/2026-10-28/eunomia-design-tradeoffs.svg" alt="端點與交換器重排方案的取捨" /></p>

<p>第一個替代方案是 IRN 類固定 BDP bitmap。它的優點是索引、時序與容量上界清楚，且 selective retransmission 已直接對準 loss recovery。若 fabric 的最大 reorder depth 本來就小於 BDP，而且 QP 數量可控，固定配置可能比共享 allocator 更容易驗證。它的弱點是每條 QP 都付最壞狀態，在百萬 QP 或高度稀疏失序時浪費 SRAM。</p>

<p>第二個替代方案是 ConWeave 類 in-network reordering。目的端 ToR 能在封包進 RNIC 前恢復順序，因此 commodity RNIC 不需修改；代價是交換器要保存 flowlet／route state 與 reorder queue，且 failure、路由狀態回收與跨 ToR 部署成為新的控制面問題。論文的 failure simulation 甚至觀察到 ConWeave 在超過 2% link failure 後無 flow 完成，作者歸因於 route-state 問題；這是特定模擬結果，不宜外推成所有實作的定論。</p>

<p>第三個替代方案是限制 packet spraying，只在 elephant flows 或遙測顯示 hotspot 時啟用。這能把 reorder state 壓到小範圍，也降低 ACK 流量；但需要準確分類 flow、快速偵測 congestion，切換期間仍會遇到 reorder。對短流占比高、路徑相近的 fabric，這可能比全流量 spraying 更務實。</p>

<p>Eunomia 的 FPGA prototype 以 SystemVerilog 實作於 AMD Kintex UltraScale+ XCKU5P KCU116，使用 Vivado 2022.2。整體約 82,201 LUT、3,434 registers；memory controller 約 81,029 LUT，是主要成本，HD bitmap 模組約 2,180 LUT。這個原型證明資料結構能進硬體，但沒有等同商用 RNIC tape-out：LUT 與 ASIC SRAM/logic 面積不能直接換算，單 packet driver 也還未覆蓋多 port、完整 transport pipeline、PCIe contention 與 firmware recovery。</p>

<p>未來 12 個月若要把 Eunomia 方向帶進產品，最值得先做三件事。其一，從 production trace 建立每毫秒 active OOO QP、reorder span 與持續時間的聯合分布，據此決定 block size、metadata pool 與 per-QP cap。其二，把 allocation miss、SACK bandwidth 與 WRITE extra RTT 放進 SLO，而不只看平均 FCT。其三，做故障注入：link flap、route change、receiver restart、metadata corruption 與 block exhaustion 時，確保系統能退回既有 recovery，不會把缺口永久卡在完成閘門。</p>

<p>Eunomia 最有價值的地方不是宣稱 packet spraying 已經沒有代價，而是把代價從「所有 QP 都先付固定 bitmap」改成「真的失序時，按跨度租用共享狀態」。只要 active ratio、allocator 延遲與 completion 語意都被量測，這個設計能讓負載平衡從 flow-level hash 進一步走向 packet-level。反過來，若大多數 QP 長期失序、metadata 連續空間不足，或 WRITE 的額外 RTT 無法接受，固定端點狀態或目的端 ToR 重排仍可能是更穩健的選擇。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>本文的機制、資源數字與效能結果以 2024-12-11 發布的 <a href="https://arxiv.org/abs/2412.08540">Eunomia 論文</a>及 <a href="https://conferences.sigcomm.org/events/apnet2025/apnetprogram.php">APNet 2025 官方議程</a>為主。效能來自 ns-3 模擬，硬體成本來自單一 FPGA prototype，尚不是商用 RNIC 的實測結果。文中的一百萬 QP 記憶體圖是明示假設的重算，用來找動態與固定配置交會點，不是作者量測；完整數值可由附帶腳本重建。</p>

<h2 id="參考資料">參考資料</h2>

<ul>
  <li>Sana Mahmood、Jinqi Lu、Soudeh Ghorbani，〈<a href="https://arxiv.org/abs/2412.08540">Eunomia: Enabling General and Efficient Packet Reordering Support for RDMA</a>〉，2024-12-11。</li>
  <li>APNet 2025，〈<a href="https://conferences.sigcomm.org/events/apnet2025/apnetprogram.php">Reinventing RDMA session</a>〉，2025-08-07。</li>
  <li>Yiwen Lu 等，〈<a href="https://www.usenix.org/conference/nsdi18/presentation/lu">Multi-Path Transport for RDMA in Datacenters</a>〉，NSDI 2018。</li>
  <li>Jiaqi Gao 等，〈<a href="https://conferences.sigcomm.org/sigcomm/2023/program.html">ConWeave: Reimagining Congestion Control in Lossless Ethernet</a>〉，SIGCOMM 2023。</li>
  <li>Inho Cho 等，〈<a href="https://arxiv.org/abs/1806.08159">Breaking the Transience-Equilibrium Nexus: A New Approach to Datacenter Packet Transport</a>〉，IRN，2018。</li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="networking" /><summary type="html"><![CDATA[Eunomia 只在連線真的失序時配置可擴張 bitmap，讓 packet spraying 與不等長路徑不再反覆觸發 RDMA 丟包處理；片上記憶體、ACK 流量與 WRITE 完成延遲則成為新的成本。]]></summary></entry><entry><title type="html">Marvell 把 3DIC signoff 延伸到 die、封裝與完整堆疊</title><link href="https://rightson.github.io/ic-design-platform/2026/10/26/marvell-3dic-physical-signoff-handoff.html" rel="alternate" type="text/html" title="Marvell 把 3DIC signoff 延伸到 die、封裝與完整堆疊" /><published>2026-10-26T06:03:58+08:00</published><updated>2026-10-26T06:03:58+08:00</updated><id>https://rightson.github.io/ic-design-platform/2026/10/26/marvell-3dic-physical-signoff-handoff</id><content type="html" xml:base="https://rightson.github.io/ic-design-platform/2026/10/26/marvell-3dic-physical-signoff-handoff.html"><![CDATA[<p>一顆 3DIC 可以讓每個 die 各自通過 DRC、LVS 與 ESD 檢查，組裝後仍留下錯誤。原因很具體：兩顆 die 的 hybrid bond pads 可能沒有對齊，彼此對應的 net 名稱可能不一致，從 package BGA 經 TSV 到上層 power clamp 的電阻也可能超過規則。單顆 die 的綠燈只覆蓋局部設計，無法描述跨越封裝的完整導電路徑。</p>

<p>Marvell 在 2025 年 WISH 發表的<a href="https://designthesolution.org/wp-content/uploads/2025/09/navigating-the-challenges-of-physical-verification-in-3dics-from-2d-to-3d-solutions-qi-mohannad-jeanne-abhijat-mike.pdf">完整論文</a>，提供一個少見的具名公司案例：流程先完成各 die、interposer 與 substrate 的檢查，再組裝 3D layout 與系統 netlist，最後執行跨 die 連接、對位和六類 ESD 路徑檢查。公開簡報另列出工作時間、核心數、超過 24,000 條 die-to-die signal nets，以及 Tier1、Tier2 各九個 power domains，足以把方法轉成可計帳的平台交接。</p>

<figure>
<a href="/images/ic-design-platform/2026-10-26/marvell-3dic-signoff-flow.svg"><img src="/images/ic-design-platform/2026-10-26/marvell-3dic-signoff-flow.svg" alt="Marvell 3DIC 實體 signoff 先分別檢查 SoC、HBM、interposer 與 substrate，再以 3Dblox 和系統 netlist 組裝，最後執行幾何、連接與 ESD 跨層檢查。" width="640" height="900" /></a>
<figcaption>圖一：依據 Marvell <a href="https://www.gsaglobal.org/events/wp-content/uploads/sites/10/2024/12/process-3v2-qi-wang-wish25_navigating_challenges_pv_v3.pdf">WISH 2025 簡報</a>與<a href="https://designthesolution.org/wp-content/uploads/2025/09/navigating-the-challenges-of-physical-verification-in-3dics-from-2d-to-3d-solutions-qi-mohannad-jeanne-abhijat-mike.pdf">論文</a>重繪。流程方塊表示交付順序，沒有表示組織架構或 runtime 比例。</figcaption>
</figure>

<p>沿圖往下看，3DIC signoff 多出的工作並非把多份 DRC 報告放在一起。它需要一個系統層描述，把各自正確的 die、封裝連接與保護元件組成同一張可檢查的圖。</p>

<h2 id="三個局部結果要組成同一份系統狀態">三個局部結果要組成同一份系統狀態</h2>

<p>Marvell 方法的第一層仍是熟悉的單體流程。SoC chiplets、HBM 和 dummy dies 各自執行 multi-DRC、antenna、LVS 與 ESD；interposer 和 substrate 則檢查其 routing、bump 與封裝規則。這些結果讓各團隊能在自己的設計資料上收斂，也保留不同 node、foundry 與工具所需的規則 deck。</p>

<p>第二層才建立完整 stack。論文寫明，layout assembly 使用 3Dblox 表達 die、interposer 與 substrate 的位置和介面，logical inter-die connectivity 則轉成可供比較的系統 netlist。IEEE P3537 將 3Dblox 定義為描述 chiplets、interposers、substrates 及其 connectivity 的模組化階層語言；標準化的用途，是讓不同工具交換同一份高階組裝意圖。<a href="https://standards.ieee.org/ieee/3537/11871/">IEEE P3537 scope</a></p>

<p>這個交接需要同時固定幾何與邏輯。幾何資料回答 die 的尺寸、方向、厚度、介面區域和相對位置；邏輯資料回答每一個 hybrid bond、micro-bump、C4 與 BGA 最終接到哪一條 net。完整 layout 抽出的連接若與 top-level system netlist 不一致，3DSTACK 類工具便可找出 open、short、缺失 label 或錯位的 bump。<a href="https://www.siemens.com/en-us/products/ic/calibre-design/calibre-3d-ic/3dstack/">Siemens Calibre 3DStack</a></p>

<p>因此 artifact 的責任可以分成四份：</p>

<table>
  <thead>
    <tr>
      <th>交付層級</th>
      <th>主要輸入</th>
      <th>可變內容</th>
      <th>接收端需要的結果</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>單顆 die</td>
      <td>layout、netlist、製程 deck、bump 與 clamp 資料</td>
      <td>P&amp;R 幾何、局部 routing、保護元件</td>
      <td>DRC／LVS／antenna／die ESD 結果與版本</td>
    </tr>
    <tr>
      <td>Interposer／substrate</td>
      <td>package layout、RDL、C4、BGA、封裝規則</td>
      <td>封裝走線、escape、尺寸與材料堆疊</td>
      <td>interposer 和 substrate 的連接及規則結果</td>
    </tr>
    <tr>
      <td>Assembly</td>
      <td>3Dblox、die transforms、介面對應、system netlist</td>
      <td>die 放置、方向、連接映射</td>
      <td>可抽取的完整 3D layout 與跨 die netlist</td>
    </tr>
    <tr>
      <td>Stack signoff</td>
      <td>組裝 layout、系統 netlist、ESD 規則及各層結果</td>
      <td>waiver、規則設定、修正後的幾何與 routing</td>
      <td>alignment、stack LVS、TOPO、P2P、CD 報告</td>
    </tr>
  </tbody>
</table>

<p>版本關係是平台必須補上的部分。只用檔名連接這四層，會允許新 die layout 搭配舊 3Dblox，或讓 clamp library 更新後仍沿用舊 P2P 結果。參考設計可把每次 stack run 綁定 die layout digest、netlist digest、process deck revision、assembly description、tool build 和 waiver set；接收方看到 pass 時，也能知道它屬於哪一組實體輸入。</p>

<p><a href="/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff.html">前一篇 RapidWright 文章</a>保存局部 placed-and-routed module，讓全域整合者重用實體結果。Marvell 案例處理更晚的交接點：每個 die 已有自己的實體結果，平台還要證明完整封裝中的幾何、電氣連接與保護路徑一致。兩者共同之處是局部成功仍要經過系統層重新組合。</p>

<h2 id="seal-ring-進場後pr-看不到的幾何也要被檢查">Seal ring 進場後，P&amp;R 看不到的幾何也要被檢查</h2>

<p>第一個關鍵機制出現在 hybrid bonding 的 seal ring。Marvell 論文說明，seal ring 在 die assembly 之後依晶片尺寸加入，用來提供切割時的機械保護和環境隔離。它位於 P&amp;R 工具之外，原本的 P&amp;R 環境看不到新增區域，因此也無法替 seal ring 周邊安排 dummy hybrid bond pads。</p>

<p>Marvell 的做法是由插入流程自動產生符合 DRC 的 dummy HBPs，再把 Tier1 與 Tier2 的 projected pad locations 放入 floorplanning 對位檢查。這處理的是跨工具可見性：P&amp;R 完成時的合法 layout，在 assembly 階段加入 seal ring 後多了新幾何；若平台沒有把新增物件送回檢查路徑，局部完成狀態便無法直接沿用。</p>

<p>同一份論文把多種 die-level checks 合併成單一 runset，包含 logic、SoIC TSV、backside metal、hybrid bond 與 micro-bump，並提供可在 floorplan 階段開啟的規則模式。早期模式用來發現介面對位、尺寸與重疊問題，最終模式則使用完整資料執行 signoff。兩者共享規則來源時，工程師能在幾何仍容易移動的階段收到回饋。</p>

<p>早期檢查節省的是昂貴重跑之前的修改成本。若錯位要等到完整 stack LVS 才出現，修正會穿過 assembly、layout extraction、netlist comparison 與相關 signoff 工作；在 floorplan 時發現，改動通常仍侷限於 die transform、pad planning 或 interface region。公開資料沒有提供迭代次數下降的量化結果，因此效益應以專案內的「首次發現階段、修正影響檔案數、重跑 core-hours」來量。</p>

<p>這套方法也增加維護面。Foundry rule、seal ring generator、dummy HBP 規則與 3Dblox 介面描述要一起升版。若自動產生器和 signoff deck 對同一個 enclosure 使用不同 revision，早期通過的 geometry 仍可能在最後被拒絕。平台應讓規則 revision 成為 run identity 的一部分，而非只保存工具 command line。</p>

<h2 id="esd-要沿-bgatsv-與-hybrid-bond-走完整條路">ESD 要沿 BGA、TSV 與 hybrid bond 走完整條路</h2>

<p>第二個機制是把 ESD 檢查從單顆 die 擴展成整個導電網路。Marvell 公開案例包含 top die 與 bottom die，兩者可由不同 node 製造，透過 hybrid bond pads 通訊；外部 I/O 從 BGA、substrate、C4 或 micro-bump 進入，再經 bottom die 的 TSV 到達上層 GPIO ESD cell 或 power clamp。</p>

<p>論文列出六種路徑，涵蓋面對面的 hybrid bonds、die-to-die signal pads、直接進入 Tier2 GPIO 的訊號，以及 power／ground 分別連到 Tier1、Tier2 或兩層 clamps 的組合。工具工作再拆成三類：</p>

<ol>
  <li><strong>TOPO</strong> 找出保護元件與合法拓樸，回答每個入口是否有可達的 ESD 元件。</li>
  <li><strong>P2P</strong> 沿實際導體量測 BGA 或 bump 到 clamp 的點對點電阻。</li>
  <li><strong>CD</strong> 檢查金屬寬度和 current density，確認路徑可承受規則指定的電流。</li>
</ol>

<p>這三項不能用單一 connectivity pass 取代。Netlist 連得上，只表示存在路徑；路徑若太長、太窄或跨越錯誤 clamp，ESD 電流仍可能造成損壞。Marvell 例子將一條 resistance rule 設為低於 0.1 Ω，工具回報 pad 與 clamp 間的實測電阻，工程師再依違例位置修 routing。這個數值屬於該案例規則，不是所有 3DIC 的通用上限。</p>

<p>完整路徑還揭示不同團隊的相依。Die team 擁有 clamp cell、TSV 與內部 routing，package team 擁有 BGA、C4、interposer 和 substrate，system signoff team 才看得到兩者串起來的電阻及分流。任何一方只交付 pass／fail 摘要，都不足以重建跨層問題；接收端至少需要 pin mapping、保護元件類型、抽取 connectivity、規則值與可定位的 violation path。</p>

<p>Siemens 2026 年的產品說明也把這條資料鏈分成相似的工具責任：Innovator3D IC 準備組裝與 netlists，Calibre 3DStack 建立完整 multi-die connectivity，Calibre 3DPERC 再執行 ESD path、point-to-point resistance 與 current density checks。<a href="https://blogs.sw.siemens.com/calibre/2026/05/14/the-calibre-3d-ic-solution-mastering-the-complexities-of-advanced-3d-ic-chip-design/">Calibre 3D IC solution</a> 這能交叉確認機制方向，Marvell 的實際 runset 和內部自動化仍以其論文揭露為準。</p>

<h2 id="p2p-讓-signoff-預算集中在少數工作">P2P 讓 signoff 預算集中在少數工作</h2>

<p>Marvell 的公開 runtime 表讓資源安排可以量化。Tier2 top die 案例有九個 power domains、一個 ground 和超過 24,000 條 D2D signal nets；Tier1 bottom die 也有相同的 power-domain 數量與超過 24,000 條 D2D nets，另有超過 100 條 I/O signal nets。簡報列出的 job 時間與 cores 如表：</p>

<table>
  <thead>
    <tr>
      <th>公開工作</th>
      <th style="text-align: right">Tier2 runtime／cores</th>
      <th style="text-align: right">Tier1 KGS runtime／cores</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>TOPO</td>
      <td style="text-align: right">1.5 h／48</td>
      <td style="text-align: right">2.9 h／48</td>
    </tr>
    <tr>
      <td>LDL</td>
      <td style="text-align: right">1.6 h／48</td>
      <td style="text-align: right">2.5 h／48</td>
    </tr>
    <tr>
      <td>CD</td>
      <td style="text-align: right">1.8 h／48</td>
      <td style="text-align: right">6.2 h／16</td>
    </tr>
    <tr>
      <td>P2P</td>
      <td style="text-align: right">41 h／240</td>
      <td style="text-align: right">6.5 h／240</td>
    </tr>
  </tbody>
</table>

<p>將每項的 wall-clock hours 乘上 cores，可得到工作量近似值。Tier2 四項合計約 10,075.2 core-hours，其中 P2P 為 9,840 core-hours，占 97.7%；Tier1 KGS 合計約 1,918.4 core-hours，P2P 為 1,560 core-hours，占 81.3%。不同 tier 和模式的設計內容不相同，兩欄不適合被當成工具速度比較；它們共同指出 P2P 會支配計算預算。</p>

<figure>
<a href="/images/ic-design-platform/2026-10-26/marvell-3dic-resource-budget.svg"><img src="/images/ic-design-platform/2026-10-26/marvell-3dic-resource-budget.svg" alt="Marvell Tier1 KGS 公開工作中 P2P 為 1560 core-hours，佔總量 81.3%；五次迭代的假設中，每次完整執行為 9592 core-hours，四次只跑 TOPO 與 LDL 再做一次完整工作為 2955.2 core-hours。" width="640" height="900" loading="lazy" /></a>
<figcaption>圖二：上半部依據 Marvell WISH 2025 公開 runtime 與 cores 換算；下半部是五次迭代的假設算例。<a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/marvell_3dic_signoff_budget.py">計帳程式</a>與<a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/marvell_3dic_signoff_budget.results.json">結果檔</a>可重跑。</figcaption>
</figure>

<p>假設同一個 Tier1 KGS stack 連續整合五次，每次都執行 TOPO、LDL、CD 與 P2P，總量是 5 × 1,918.4 = 9,592 core-hours。若前四次只跑 TOPO 和 LDL，最後一次再執行完整工作，算例變成 4 × 259.2 + 1,918.4 = 2,955.2 core-hours，下降 69.2%。這是排程模型，沒有宣稱輕量工作可以取代 CD 與 P2P。</p>

<p>可借鏡的實驗應把同一批真實 design changes 分成兩組。A 組每次跑完整工作；B 組讓 floorplan 和初期 assembly 只跑 geometry、TOPO 與 LDL，在里程碑補齊 CD、P2P 和完整 stack LVS。兩組都保存首次發現的 violation、重跑次數、core-hours、license-hours、人工除錯時間，以及最終完整工作找到的新增問題。若 B 組延後發現的高嚴重度問題抵銷計算節省，頻率就要提高。</p>

<p>排程還要分開 core-hours 與日曆時間。兩百四十 cores 跑 6.5 小時是 1,560 core-hours；若共享叢集只能短暫提供八十 cores，工具擴展性與排隊時間都可能改變完成時點。公司需要量到自己的 license 限額、記憶體峰值、I/O 和 parallel efficiency，Marvell 表格只能提供量級和工作組成。</p>

<h2 id="三種流程處理不同的變動形狀">三種流程處理不同的變動形狀</h2>

<p>Marvell 方法適合 die、封裝和 stack 由不同資料與團隊維護的情境。標準化 assembly description 把跨層連接變成共同輸入，multi-level checks 則讓局部與系統結果有明確接續。它的代價是多一份必須同步的 system description、跨 foundry 規則整合，以及昂貴的 full-stack extraction 和 P2P。</p>

<p>另一條路是讓單一 EDA 平台保有組裝、物理實作與 signoff 的共同資料庫。這可以減少格式轉換及版本對接，工具供應商也能把 in-design checking 接到修正介面；團隊換來較深的產品依賴，既有腳本和不同供應商的 die data 仍要轉入共同模型。Synopsys 的 <a href="https://www.synopsys.com/solutions/multi-die-design.html">Multi-Die System</a>屬於這類整合路線的公開產品說明。</p>

<p>第三條路是只在最終階段做 assembly verification。它對變動少、介面成熟的專案維護成本最低，卻把錯位、名稱對接與跨層保護問題留到修改代價較高的階段。若專案只有兩顆高度固定的 die，完整 flow automation 的投入可能難以攤提；若 chiplets、foundries、package variants 與 derivative products 持續增加，共同描述和早期檢查的回收機會會上升。</p>

<p>TSMC 在 2023 年公布 <a href="https://pr.tsmc.com/english/news/3070">3Dblox 2.0</a>，把 early 3D IC design 和跨生態系工具交換列為重點；Marvell 2025 年案例新增的理解，是將 seal ring 後處理、dummy HBPs、multi-level DRC 和跨 package ESD 電阻放進同一條具名公司流程。方法演進的方向，從「能描述多顆 die」走向「每個新增物件都能回到系統連接與可靠度規則」。</p>

<p>未來六個月，最值得測的是同一份 assembly intent 能否驅動早期分析與 final signoff，且在 die revision、package variant 和 tool version 改變時保持一致。可觀察三個訊號：跨工具轉譯後的 net count 是否穩定、早期 run 找到的違例有多少會在完整工作重現、final P2P 新增問題的比例是否下降。若版本同步成本持續高於省下的重跑，人力和時程改善就不成立。</p>

<p>Marvell 的公開案例補齊了 R2G 後段一個常被省略的交接：GDS、netlist 與單顆 die 報告交出去後，chiplet 系統仍需要自己的 design intent、layout assembly、系統 connectivity 和 ESD path results。流程能改善時程與 tool-hours 的條件，是介面資料可重用、早期檢查能實際攔下後期問題，且高成本 P2P 工作按風險安排頻率；代價落在共同模型、規則 deck、版本治理與 full-stack 計算。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>本文主要依據 Marvell 於 WISH 2025 發表的八頁論文與二十頁簡報。論文支持 multi-level DRC、3Dblox assembly、LVS connectivity、六類 ESD 路徑及 0.1 Ω 案例規則；簡報支持公開 runtime、cores、power domains 與 signal-net 規模。資料沒有提供 tapeout 名稱、量產狀態、導入前後迭代數、缺陷逃逸率或人力節省。</p>

<p>2026 DAC 議程另列 Marvell 的 stacked 3D chiplet SIP flow 和 physical signoff 報告，但目前公開頁面多為摘要；本文沒有用摘要補造論文未揭露的內部介面。Marvell 論文提到 Siemens Calibre PERC 與 Synopsys IC Validator，沒有揭露每項工作使用的完整版本、runset 或分配比例。</p>

<p>Core-hour 數字由公開 wall-clock hours 乘 cores，適合比較該表內工作量級，不表示工具的 CPU 使用率、license 費用或叢集效率。五次迭代模型是明示假設，沒有執行 EDA 工具、3D extraction 或實際 layout；0.1 Ω 僅屬論文案例規則。</p>

<h2 id="參考資料">參考資料</h2>

<ul>
  <li>Qi Wang 等，Marvell，<a href="https://designthesolution.org/wp-content/uploads/2025/09/navigating-the-challenges-of-physical-verification-in-3dics-from-2d-to-3d-solutions-qi-mohannad-jeanne-abhijat-mike.pdf">Navigating the Challenges of Physical Verification in 3DICs</a>，WISH 2025，2025-09-05。</li>
  <li>Marvell，<a href="https://www.gsaglobal.org/events/wp-content/uploads/sites/10/2024/12/process-3v2-qi-wang-wish25_navigating_challenges_pv_v3.pdf">WISH 2025 presentation</a>，完整流程、runtime 與資源表。</li>
  <li>IEEE Standards Association，<a href="https://standards.ieee.org/ieee/3537/11871/">P3537 Draft Standard for 3Dblox</a>，3Dblox language scope。</li>
  <li>Siemens EDA，<a href="https://www.siemens.com/en-us/products/ic/calibre-design/calibre-3d-ic/3dstack/">Calibre 3DStack</a>及<a href="https://blogs.sw.siemens.com/calibre/2026/05/14/the-calibre-3d-ic-solution-mastering-the-complexities-of-advanced-3d-ic-chip-design/">Calibre 3D IC solution</a>，assembly connectivity 與 3DPERC 工作。</li>
  <li>Marvell，<a href="https://www.marvell.com/company/events/dac-2026.html">DAC 2026 presentations</a>，後續 SIP flow、physical signoff 和 3Dblox 議程。</li>
  <li>Synopsys，<a href="https://www.synopsys.com/solutions/multi-die-design.html">Multi-Die System</a>，整合式 exploration-to-signoff 替代方案。</li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="ic-design-platform" /><summary type="html"><![CDATA[Marvell 的公開 3DIC 方法先分別檢查 die、interposer 與 substrate，再以 3Dblox 和系統 netlist 組裝跨 die 連接與 ESD 路徑；它能提早暴露對位、連接及電阻問題，代價是新增一層系統描述、規則維護與高成本 P2P 工作。]]></summary></entry><entry><title type="html">IRN 讓失序封包先落地，補齊缺口後才宣告 RDMA 完成</title><link href="https://rightson.github.io/networking/2026/10/21/irn-selective-retransmission-rdma-completion.html" rel="alternate" type="text/html" title="IRN 讓失序封包先落地，補齊缺口後才宣告 RDMA 完成" /><published>2026-10-21T19:08:00+08:00</published><updated>2026-10-21T19:08:00+08:00</updated><id>https://rightson.github.io/networking/2026/10/21/irn-selective-retransmission-rdma-completion</id><content type="html" xml:base="https://rightson.github.io/networking/2026/10/21/irn-selective-retransmission-rdma-completion.html"><![CDATA[<p>RDMA 把資料搬移交給 RNIC，application 只要張貼 WQE，稍後從 completion queue 取得結果。這個介面看似以 operation 為單位，線上傳送卻由多個帶 packet sequence number（PSN）的封包完成。只要其中一包遺失，transport 就必須回答兩個問題：要重送多少資料，以及 application 何時能相信整個 operation 已經完成。</p>

<p>傳統 RoCE 的可靠連線遇到失序封包時會丟棄它，sender 收到 NACK 後從最後一個連續確認點重新傳送。這個 go-back-N 作法適合幾乎不丟包的 fabric；若交換器開始丟包，一個缺口會讓後面已經跨過網路的封包失去價值。2018 年 Radhika Mittal 等人提出 <a href="https://arxiv.org/abs/1806.08159">IRN</a>，把 selective retransmission 與 BDP-based flow control 加進 RoCE endpoint，讓 fabric 可以承受丟包而不必用 PFC 保證每一包都留下。</p>

<p>這篇接續 <a href="/networking/2026/10/14/roce-pfc-ecn-feedback-buffer-budget.html">RoCE 用 PFC 接住在途資料，用 ECN 降低持續進入的流量</a>。上一篇從 queue 與控制延遲解釋 PFC 為何會暫停其他 flow；這一篇沿著丟包後的 PSN、memory placement、WQE 與 CQE 前進，說清 RNIC 如何只補缺口，同時維持 operation completion。</p>

<p>先沿下圖的藍色路徑看一遍：requester 從 Request WQE 取得位址與長度，切成 PSN 連續的封包；fabric 可以丟失或重排；responder 把先到資料直接 DMA 到最終位址。橘色路徑負責補洞。arrival bitmap 已經看見尾包，也要等較早 PSN 補齊，才把 completion 交給 application。</p>

<p><img src="/images/networking/2026-10-21/irn-end-to-end-path.svg" alt="IRN requester 將 WQE 分段，封包經 lossy fabric 後由 responder 直接 DMA 並以 bitmap 等待缺口，連續前綴完整後交付 CQE" /></p>

<p>圖一：依據 <a href="https://arxiv.org/abs/1806.08159">IRN extended paper §3、§5</a> 整理。資料 placement 與 completion notification 是兩條相關但分開推進的狀態路徑。</p>

<h2 id="go-back-n-把一個缺口放大成整段重送">Go-back-N 把一個缺口放大成整段重送</h2>

<p>假設一個 QP 已送出 PSN 0–63，PSN 7 與 29 在 fabric 內暫時性遺失。傳統 receiver 收到 PSN 8 時，因為期待值仍是 7，便丟棄 8 以及後續失序封包並回 NACK。sender 從 PSN 7 起重送到 63，共 57 包；其中只有 7 與 29 原本缺失，另外 55 包曾經成功越過網路，卻因 receiver 沒有保留而再走一次。</p>

<p>IRN receiver 收到失序封包時不丟棄資料。NACK 同時帶回 cumulative ACK，也就是目前第一個缺口，以及觸發 NACK 的較高 PSN，形成簡化的 SACK。sender 以 bitmap 記錄哪些 PSN 已被累積或選擇性確認，進入 loss-recovery mode 後先補累積 ACK 指向的缺口；較高 PSN 已有選擇性確認時，bitmap 內的零才代表另一個需要重送的位置。<a href="https://arxiv.org/abs/1806.08159">IRN §3.1</a> 還用 recovery sequence 記住進入修補前最後一次正常送出的 PSN；累積 ACK 越過它之後，sender 才離開修補模式。</p>

<p><img src="/images/networking/2026-10-21/irn-retransmission-timeline.svg" alt="同一個64包視窗遺失PSN 7與29，go-back-N從7起重送57包，IRN只補2包" /></p>

<p>圖二：假設算例。丟包視為暫時事件，重送成功；總傳送量由 121 包降到 66 包。這是 packet accounting，沒有代入 queue、RTT、RTO 或 congestion control。</p>

<p>這個差異會在 congestion 時自我強化。go-back-N 增加的 55 包與新流量共用同一個瓶頸，延長 queue 並創造更多丟包機會。selective retransmission 只補兩個缺口，把重傳負擔限制在出錯 flow 與出錯 PSN。IRN 論文的 factor analysis 也測過「選擇性重傳但沒有 SACK」：遇到同一視窗內多個缺口時，需要用多個 RTT 逐次發現，與 SACK 版本相比，平均 flow completion time 在不同情境下惡化不到 1% 到 75%。同一分析把 SACK 換回 go-back-N，搭配 Timely 時平均 FCT 差距仍有 20%–50%。</p>

<p>SACK bitmap 不是讓 sender 立刻相信所有較高 PSN 永久安全。它是在一個受限制的在途範圍內記錄 receiver 已看到的 PSN，sender 仍保存可重傳資料；cumulative ACK 往前推，才代表連續區段完成。這個區分也解釋 IRN 為何要把 selective retransmission 與 BDP-FC 成對設計。</p>

<h2 id="bdp-fc-同時限制-queue-壓力與追蹤狀態">BDP-FC 同時限制 queue 壓力與追蹤狀態</h2>

<p>若 sender 可以無限增加在途封包，receiver 的失序集合也可能無限增長。IRN 以 bandwidth-delay product 設定靜態 packet cap：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BDP_bytes = link_rate_bytes_per_second × path_RTT_seconds
BDP_packets = ceil(BDP_bytes / MTU_bytes)
in_flight_packets &lt; BDP_packets
</code></pre></div></div>

<p>sender 只有在目前 PSN 與最後確認 PSN 的差小於 cap 時，才送新封包。<a href="https://arxiv.org/abs/1806.08159">IRN §3.2</a> 使用已知 datacenter topology 最長路徑的 BDP，並容許適度高估。cap 太小會讓長路徑鏈路等不到下一批資料；cap 太大仍能傳滿鏈路，卻增加 queue 與 bitmap 狀態。</p>

<p>論文的預設網路是 40 Gb/s、最長六 hop、每 hop 傳播延遲 2 μs，給出 120 kB BDP，約 110 個 1 kB MTU 封包。原文的 FPGA resource 試算將 bitmap 向上取成 128 bits。IRN 共使用五張 BDP-sized bitmap：responder 兩張追蹤到達與尾包事件，requester 一張追蹤 Read response，兩端各一張追蹤 selective ACK。原文在 128-bit 假設下得到每 QP 640 bits bitmap，另外增加 160 bits per-QP state 與每個 WQE 3 bytes context。</p>

<p>同一公式套到更高速鏈路，狀態量會跟著 BDP 增加。下面的試算固定 1 KiB MTU，採十進位 Gb/s 與 bytes；「每 QP bytes」只計五張 bitmap，未納入 alignment、cache、timer、WQE 及 allocator overhead。</p>

<table>
  <thead>
    <tr>
      <th>鏈路與 RTT</th>
      <th style="text-align: right">BDP</th>
      <th style="text-align: right">packet cap</th>
      <th style="text-align: right">五張 bitmap</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>40 Gb/s、24 μs</td>
      <td style="text-align: right">120,000 bytes</td>
      <td style="text-align: right">118 包</td>
      <td style="text-align: right">74 bytes/QP</td>
    </tr>
    <tr>
      <td>100 Gb/s、24 μs</td>
      <td style="text-align: right">300,000 bytes</td>
      <td style="text-align: right">293 包</td>
      <td style="text-align: right">184 bytes/QP</td>
    </tr>
    <tr>
      <td>200 Gb/s、12 μs</td>
      <td style="text-align: right">300,000 bytes</td>
      <td style="text-align: right">293 包</td>
      <td style="text-align: right">184 bytes/QP</td>
    </tr>
    <tr>
      <td>400 Gb/s、12 μs</td>
      <td style="text-align: right">600,000 bytes</td>
      <td style="text-align: right">586 包</td>
      <td style="text-align: right">367 bytes/QP</td>
    </tr>
    <tr>
      <td>800 Gb/s、12 μs</td>
      <td style="text-align: right">1,200,000 bytes</td>
      <td style="text-align: right">1,172 包</td>
      <td style="text-align: right">733 bytes/QP</td>
    </tr>
  </tbody>
</table>

<p><img src="/images/networking/2026-10-21/irn-bdp-bitmap-scaling.svg" alt="BDP packet cap與五張bitmap的每QP狀態隨鏈路速率增加" /></p>

<p>圖三：假設算例，以 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/irn_selective_retransmission.py">可重跑腳本</a> 產生；紫色 800 Gb/s bar 提醒高速下 RTT 仍主導狀態。數值不是現代 RNIC 的實測資源。</p>

<p>以 400 Gb/s、12 μs 為例，五張 bitmap 的純資料量是 367 bytes/QP。若設計目標是 100 萬個同時駐留的 QP，單純相乘約 367 MB；實作通常會把熱門 QP context 放片上 cache，冷 context 放較慢層級，packet-rate、cache miss 與 PCIe 往返因而成為另一組問題。縮短 RTT 可等比例縮小 cap；把 MTU 從 1 KiB 增加到 4 KiB 可把 bitmap 位元數約降為四分之一，但大封包在丟失時也多重送資料，並改變小訊息 latency 與 serialization。</p>

<p>另一個可行方向是 dynamic window，由 congestion control 依狀態縮放在途量。它能在低負載提高彈性，也把 transport state 與速率控制綁得更緊。IRN 刻意選擇固定 BDP cap，把「可安全追蹤多少封包」與「目前應該多快送」拆開：前者限制 state，後者仍可交給 DCQCN、Timely 或其他演算法。</p>

<h2 id="失序資料可以先寫入完成通知必須等待連續前綴">失序資料可以先寫入，完成通知必須等待連續前綴</h2>

<p>把 OOO 封包全放 RNIC SRAM 最直觀，也最昂貴。論文用 110 包/QP、1 kB/包估算，一千個 flow 就需要 110 MB packet buffer。IRN 的替代做法是把封包直接 DMA 到 application 指定的最終位址，只在 NIC 保留 bitmap。這個轉換將每個失序封包約 1 kB 的 packet storage，縮成一或數個追蹤 bit，但它也打破「最後一包到達等於整個 message 完成」的直覺。</p>

<p>考慮 12 包 RDMA operation。PSN 0、1、3…11 都已抵達，PSN 2 遺失。尾包 PSN 11 帶來 operation 的末端資訊，payload 也已放進 memory；連續前綴仍只有 0、1。若 RNIC 此時釋放 WQE 或產生可見 CQE，application 會讀到中間缺一段的 buffer。</p>

<p>IRN responder 使用兩類資訊把這兩件事拆開：arrival bitmap 表示各 PSN 是否到達，另一個 bit 標示哪些 PSN 是會觸發 MSN 更新、Receive WQE expiration 或 CQE 的最後一包。尾包先到時，RNIC 可以先建立 premature CQE 並把 metadata 放到 main memory；只有 bitmap 的連續前綴越過該尾包，才把 CQE 交給 application。<a href="https://arxiv.org/abs/1806.08159">IRN §5.3.3</a> 以這個順序維持 Write、Send 與 Write-with-Immediate 的完成語意。</p>

<p><img src="/images/networking/2026-10-21/irn-completion-gate.svg" alt="尾包PSN 11先到但PSN 2缺失，completion被保留；PSN 2補齊後才交付CQE" /></p>

<p>圖四：假設算例。綠格已 DMA，紅格是缺口，紫格為尾包；completion event 在第 12 次抵達，也就是 PSN 2 修補後才變成可見。</p>

<p>這裡的關鍵不在「資料能否先落地」，而在「哪一個事件授權 application 使用資料」。<a href="https://arxiv.org/abs/1806.08159">IRN Appendix B.1</a> 引用 InfiniBand Write completion 條件：Write-with-Immediate 的末包完成、後續 Send 完成，或後續 Atomic 更新，才能讓 responder application 依序使用先前 Write 的內容。IRN 讓這些後續事件都等到較早 PSN 連續完成，因此即使物理抵達順序改變，operation 可見順序仍維持。</p>

<h2 id="四種-rdma-operation-需要不同的失序補強">四種 RDMA operation 需要不同的失序補強</h2>

<p>Write 的第一包帶有 RETH，包含 remote address 與長度。後續封包若早到，只有 PSN 仍不足以算出 placement；IRN 因此要求每一包都攜帶 RETH。每包還要能推導相對 offset，responder 才能直接 DMA 到正確位置。這增加 header bytes，換來免存整包的 OOO placement。</p>

<p>Send 與 Write-with-Immediate 會消耗 responder 預先張貼的 Receive WQE，而且 WQE 必須依張貼順序配對。in-order transport 可以靠隱含游標前進；OOO transport 要在 Request WQE 與 Receive WQE 都維護 recv_WQE_SN，封包也攜帶這個編號。Send packet 還要帶相對 PSN offset，才能把資料寫進該 Receive WQE 指向的 buffer。</p>

<p>Read 的方向容易混淆。requester 發出 Read request，responder 反而成為資料來源；現有 RoCE requester 對 Read response 沒有逐包 ACK。IRN 為 Read response 新增 read (N)ACK opcode，requester 每收到一包 response 就回覆，responder 也要有 timeout。Read/Atomic request 本身若失序到達，必須在 responder 的 Read WQE buffer 等較早 request；read_WQE_SN 用來定位正確 slot。Atomic 是單包 operation，處理方式接近單包 Read。</p>

<p>這些補強可整理成一個順序：</p>

<ol>
  <li>packet arrival 先依 operation metadata 找到最終位址或 WQE slot；</li>
  <li>payload DMA 完成後設定 arrival bit；</li>
  <li>NACK/SACK 告訴 sender 哪些 PSN 已見、哪個連續缺口仍在；</li>
  <li>last-packet metadata 可以先保存；</li>
  <li>contiguous prefix 跨過 operation 尾端後，才更新 MSN、釋放 WQE 並提交 CQE。</li>
</ol>

<p>Shared Receive Queue 另有一個細節。receive WQE 由多個 QP 共用時，recv_WQE_SN 在 WQE 從 SRQ dequeue 時配置。若較高序號 Send 先到，RNIC 要依序 dequeue 足夠的 WQE，讓該封包配到對應 slot；如果 responder 沒有 credit，某些失序 probe 必須直接丟棄，等正常 loss recovery 重新送到。<a href="https://arxiv.org/abs/1806.08159">IRN Appendix B.2–B.4</a> 把 receiver-not-ready 等錯誤 NACK 與一般失序 NACK 分開，前者仍可能啟動 go-back-N 式處理。</p>

<h2 id="timeout-補上沒有較高-psn-可報告的丟包">Timeout 補上沒有較高 PSN 可報告的丟包</h2>

<p>SACK 需要較高 PSN 抵達，receiver 才能指出前面有洞。單包 RPC 整包遺失時，沒有後續封包觸發 NACK；message 尾端遺失也可能缺少足夠的新到達。sender 仍要靠 timeout。</p>

<p>IRN 使用兩個固定值。當在途封包數不超過 N 時，用較短的 <code class="language-plaintext highlighter-rouge">RTO_low</code>，降低單包訊息尾端等待；在途較多時改用 <code class="language-plaintext highlighter-rouge">RTO_high</code>，減少 queue variation 引起的 spurious retransmission。論文預設 N=3、<code class="language-plaintext highlighter-rouge">RTO_low</code>=100 μs、<code class="language-plaintext highlighter-rouge">RTO_high</code>=320 μs，並在模擬中把 <code class="language-plaintext highlighter-rouge">RTO_high</code> 放大至四倍、N 提高到 10 或 15，主要結果只有小幅差異。這些是 40 Gb/s 模擬參數，部署時要以實際 path RTT、queue delay 與 timer granularity重新選擇。</p>

<p>另一種方案是像 TCP 一樣動態估計 RTO。原文表示其實驗版本增加了複雜度，初始 timeout 的影響仍主導短訊息，因此沒有帶來改善。今天若 NIC 已有更細的 telemetry 與 timer wheel，dynamic RTO 可能重新變得有吸引力；代價是每 QP 估計狀態、更新頻率及 clock domain 會進入 packet-processing critical path。</p>

<h2 id="原始結果支持-endpoint-處理丟包部署條件已經改變">原始結果支持 endpoint 處理丟包，部署條件已經改變</h2>

<p>IRN 論文使用商用 NIC vendor 提供、擴充自 INET/OMNeT++ 的 RoCE simulator。預設是 54 台 server 的三層 fat-tree、40 Gb/s link、每 hop 2 μs propagation、70% network load；50% flow 是 32 bytes–1 kB 單包訊息，15% flow 為 200 kB–3 MB 大流量。論文報告 IRN 不開 PFC，相對 RoCE 加 PFC，在不同 topology、bandwidth、buffer、workload 與 congestion-control 情境改善 6%–83%。預設無 explicit congestion control 時，IRN 遭遇 8.5% packet drop，仍因 selective recovery 與無 pause spreading 得到較好的 network-wide 結果。</p>

<p>這組結果的意思是 endpoint loss recovery 足以改變 PFC 的必要性，並非「丟包越多越好」。論文同時顯示 BDP-FC 減少多餘 queue，SACK-based recovery 的影響又比 BDP-FC 更大；兩者一起才形成完整設計。搭配 Timely 或 DCQCN 後，IRN 開關 PFC 的差異縮小，因為 explicit congestion control 同時減少 drop 與 pause。</p>

<p>硬體部分以 Xilinx Kintex UltraScale KU060、Vivado HLS 2017.2 合成四個簡化模組。論文報告 receiveData、txFree、receiveAck 與 timeout 合計使用 1.35% FF、4.01% LUT，最慢模組 throughput 為 45.45 Mpps；bitmap 增大到支援 100 Gb/s 時，合計為 2.66% FF、9.5% LUT。這些模組接收已解析的 packet metadata 與 QP context，沒有包含完整 RNIC datapath。FPGA、HLS、40/100 Gb/s 與 2017 年工具結果只能說明增量邏輯可合成，不能直接當作現代 400/800 Gb/s ASIC 的面積與功耗。</p>

<p>相反方向的方案也合理。PFC 配合嚴格 traffic engineering，可以讓現有 go-back-N RNIC 在可控 fabric 內維持低 drop，且不改 endpoint packet format；代價是逐跳 buffer、priority mapping、watchdog 與 pause spreading 管理。iWARP 直接沿用 TCP reliability，能在一般 IP 網路上處理丟包；代價是 byte stream 與 RDMA segment 間的轉換，以及更完整的 transport state。IRN 選在兩者中間：保留 RDMA segment 與 operation 語意，只加入 packet-level SACK、有限在途與 OOO placement。</p>

<p>未來 24 個月內，若新一代 RNIC 或 scale-out transport 公開 per-packet SACK、OOO direct placement 與 completion gating 的資源數字，最值得比較的是 400/800 Gb/s 下每 QP bitmap cache miss、最大 resident QP 數及小訊息 loss tail。若業界仍普遍要求無丟包 fabric，而且 endpoint 沒有公開承擔這些狀態，IRN 的論點會繼續停留在架構參考；若 endpoint 能在不犧牲 message rate 的條件下吸收偶發 drop，PFC 的角色就可能縮到特定 traffic class 或最後一道保護。</p>

<h2 id="一個缺口牽動-packetmemory-與-application-三層狀態">一個缺口牽動 packet、memory 與 application 三層狀態</h2>

<p>IRN 的 selective retransmission 解決 bandwidth 浪費，BDP-FC 把失序集合限制在固定範圍，completion gating 則把「資料已落地」和「operation 可使用」重新接起來。少任何一層都會留下問題：只有 SACK 而沒有 cap，bitmap 可能隨在途量膨脹；只有 OOO DMA 而沒有 completion gate，application 會看見部分結果；只有 cap 而保留 go-back-N，丟包仍會重送整段資料。</p>

<p>64 包的假設案例把差距縮成可檢查的數字：兩個缺口時，go-back-N 送 121 包，selective retransmission 送 66 包。12 包 completion 案例也給出清楚條件：尾包已到仍停在連續前綴 2，補上 PSN 2 後才交付 CQE。這兩個結果由 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/irn_selective_retransmission.py">腳本</a> 與 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/irn_selective_retransmission.results.json">結果檔</a> 固定保存，方便改動 window、loss pattern、link rate、RTT 與 MTU 後重新核對。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>本文的 IRN transport、operation-specific header、bitmap、WQE/CQE ordering、模擬與 FPGA synthesis 數字，來自 2018 年 extended paper。假設算例只檢查 packet 數量、連續前綴與 BDP 公式，沒有重跑作者的 OMNeT++ simulator、FPGA RTL、商用 RNIC firmware 或實體 lossy fabric。</p>

<p>BDP 表採固定 RTT 與 MTU，沒有加入 protocol headers、ACK traffic、path asymmetry、timer wheel、context cache、alignment 及 memory hierarchy。每 QP 狀態相乘用來展示量級，不表示任何現有產品的實際容量。文章沒有宣稱 IRN 已成為 RoCE 標準，也沒有把論文的 40/100 Gb/s resource result 外推成 400/800 Gb/s ASIC 結果。</p>

<h2 id="references">References</h2>

<ul>
  <li>Radhika Mittal et al., <a href="https://arxiv.org/abs/1806.08159">Revisiting Network Support for RDMA</a>, extended version of ACM SIGCOMM 2018, 2018-06-21。</li>
  <li>Renato Recio et al., <a href="https://www.rfc-editor.org/rfc/rfc5040">A Remote Direct Memory Access Protocol Specification</a>, RFC 5040, 2007-10。</li>
  <li>Hemal Shah et al., <a href="https://www.rfc-editor.org/rfc/rfc5041">Direct Data Placement over Reliable Transports</a>, RFC 5041, 2007-10。</li>
  <li>Yibo Zhu et al., <a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf">Congestion Control for Large-Scale RDMA Deployments</a>, ACM SIGCOMM 2015。</li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="networking" /><summary type="html"><![CDATA[IRN 以選擇性重傳、BDP 在途上限與 completion gating，把丟包代價限制在缺失封包，同時維持 RDMA Write、Read、Send 與 Atomic 的完成順序。]]></summary></entry><entry><title type="html">EDA Agent 的評分要跟著同一份設計與執行結果走</title><link href="https://rightson.github.io/ic-design-platform/2026/10/20/eda-agent-artifact-grader.html" rel="alternate" type="text/html" title="EDA Agent 的評分要跟著同一份設計與執行結果走" /><published>2026-10-20T06:01:36+08:00</published><updated>2026-10-20T06:01:36+08:00</updated><id>https://rightson.github.io/ic-design-platform/2026/10/20/eda-agent-artifact-grader</id><content type="html" xml:base="https://rightson.github.io/ic-design-platform/2026/10/20/eda-agent-artifact-grader.html"><![CDATA[<p>驗證工程師收到一份新產生的 FIFO 測試：coverage 已到目標，另一份 scoreboard 報告也顯示零錯誤。接下來要交付的，卻是「這份測試在這版 RTL 上執行後，同時滿足目標覆蓋與資料正確性」。兩張漂亮報表與這個工程承諾之間，還隔著版本、stimulus 和執行身分的對應。</p>

<p>既有人工流程通常靠目錄命名、工程師記憶和固定 regression recipe 維持這種對應，腳本也能在輸入穩定時做得很好。Agent 加快了修改 test、RTL、SDC 與 Tcl 的頻率，還可能在一次對話內交替查看多次執行結果；原本由人腦補上的關係便需要明確保存。平台的下一步，是把可採計的產物集合固定下來，再比較哪種方法用較少工具與人工工作交付同樣品質。</p>

<p><a href="/ic-design-platform/2026/10/13/eda-diagnostic-skills-offline-replay.html">上篇診斷 skill 研究</a>評估的是下一步查核建議。本篇往下游走：Agent 提出了變更之後，如何建立一份可評分的交付，以及錯誤報告、過期結果和工具中斷如何影響分母。以下 runner、manifest 與測試都是參考設計，先用公開案例理解問題，再用可重跑的合成程式檢查必要條件。</p>

<figure>
<a href="/images/ic-design-platform/2026-10-20/artifact-grader-flow.svg"><img src="/images/ic-design-platform/2026-10-20/artifact-grader-flow.svg" alt="參考設計先固定 RTL、測試、seed 與工具版本，Agent 提出候選，runner 產生同一次執行的報告，獨立 grader 檢查後由工程師決定交付。" width="640" height="875" /></a>
<figcaption>圖一：產物評分流程的參考設計。最終產物檢查參考 <a href="https://developer.nvidia.com/blog/optimizing-agent-reliability-and-tool-calling-efficiency-for-chip-design-using-nvidia-nemo-gym/">Siemens／NVIDIA Liberty 案例</a>，評分工作區分離參考 <a href="https://chipagents.ai/research/build-a-chip-bench">Build-A-Chip-Bench</a>；具體 manifest、runner 與交付分工由本篇提出。</figcaption>
</figure>

<p>沿圖向下看，Agent 可以提出更多候選，正式比較卻只消費固定的提交。生成、執行、評分、工程接受各自有輸入和輸出，能讓同一套評量用於人工、腳本與不同模型。</p>

<h2 id="三個公開案例把評分推向不同交付物">三個公開案例把評分推向不同交付物</h2>

<p>2026 年 10 月 14 日，Siemens 與 NVIDIA 公開 Solido characterization 的開發案例：SPICE 輸入經設定、模擬與 Liberty 產生後，grader 檢查完整性、格式、相對 reference 的新增失敗、數值 tolerance 及結果是否完整生成。四個二元條件乘上 tolerance 內數值比例，任一必要條件失敗即為零。公開調校每輪只使用兩個 cells、36 個 PVT corners，約 25 個 rollouts；平均綜合分數約 55% 升至 95%，turns 155 降至 53，output tokens 約 81K 降至 29K，屬供應商自報的開發結果。<a href="https://developer.nvidia.com/blog/optimizing-agent-reliability-and-tool-calling-efficiency-for-chip-design-using-nvidia-nemo-gym/#reward-design-and-artifact-verification">原始方法與設定</a></p>

<p>同月的 Build-A-Chip-Bench 將目標擴到 RTL 與 GDS，Agent、可查詢的隱藏 VIP、獨立 grader 分置三個 container。每個 task 的功能通過、乾淨 GDS 條件與 PPA 分數相乘，再對全體 tasks 平均。公開最佳綜合分數 16.6% 是這套評法的自報結果；不同欄位有不同分母。<a href="https://chipagents.ai/research/build-a-chip-bench#results">方法、公式與結果</a></p>

<p>另一端是 <strong>Venkata Krishna Kumar Vedantam／Portland State University</strong> 於 2026 年 10 月 15 日發表的 AMBU-CovAgent v1。論文坦白指出，固定 stimulus 的 scoreboard 與生成測試分開執行，reactive monitor 尚未普遍接到每份生成測試；三個小設計的 coverage 提升因此留下同份 stimulus 的資料檢查缺口。<a href="https://arxiv.org/html/2610.21570v1#S2">論文方法與限制</a></p>

<p>三者提供互補的工程理解：Liberty 案例將錯誤回溯到設定與工具選擇；RTL-to-GDS 將跨階段品質放在共同 task 上；AMBU-CovAgent 則示範即使已有兩種檢查，對應關係仍可能斷開。共同的設計要求，是先定義每一個分數究竟屬於哪份輸出，再討論 Agent 的進步。</p>

<h2 id="報告要攜帶能重建工作的身分">報告要攜帶能重建工作的身分</h2>

<p>考慮一個公開式 FIFO 任務，要求在 reset 後保持資料順序，並補到 full、empty 與 reset interaction 的指定功能 bins。方法工程師先固定 RTL 與 coverage plan，既有 testbench 產生起始結果；Agent 只能在指定目錄寫新的 directed test。這時的提交單位可以是下列 manifest：</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">submission</span><span class="pi">:</span> <span class="s">fifo-candidate-17</span>
<span class="na">inputs</span><span class="pi">:</span>
  <span class="na">rtl_digest</span><span class="pi">:</span> <span class="s">...</span>
  <span class="na">test_digest</span><span class="pi">:</span> <span class="s">...</span>
  <span class="na">seed</span><span class="pi">:</span> <span class="m">11</span>
  <span class="na">simulator_build</span><span class="pi">:</span> <span class="s">...</span>
  <span class="na">checker_revision</span><span class="pi">:</span> <span class="s">fifo-monitor-v3</span>
  <span class="na">coverage_plan_digest</span><span class="pi">:</span> <span class="s">...</span>
<span class="na">execution</span><span class="pi">:</span>
  <span class="na">id</span><span class="pi">:</span> <span class="s">exec-104</span>
  <span class="na">state</span><span class="pi">:</span> <span class="s">completed</span>
<span class="na">outputs</span><span class="pi">:</span>
  <span class="na">trace_digest</span><span class="pi">:</span> <span class="s">...</span>
  <span class="na">coverage_report_digest</span><span class="pi">:</span> <span class="s">...</span>
  <span class="na">checker_report_digest</span><span class="pi">:</span> <span class="s">...</span>
</code></pre></div></div>

<p>Digest 是內容識別，execution id 則回答「哪次工作產生了這些內容」。同一份程式重跑兩次可能使用相同輸入，仍要分別記錄執行；相同的 pass 字樣更不足以識別資料。報告由 runner 收集、固定內容後交付 grader，Agent 可讀取診斷，評分所用副本保持唯讀。</p>

<p>輸入清單應按階段展開。生成測試以 RTL、stimulus、seed、simulator 與 checker 為主；綜合還要固定 Tcl、SDC、library view 和 elaboration 設定；APR 加入 netlist、floorplan、實體 library 與 recipe；post-route STA 再綁 SPEF 與 corner。直接把所有東西塞進一個「專案版本」會讓失效原因難以定位。分層列出相依，才能在只改 test 時保留其他可重用資料，改 RTL 時則明確重做相關功能與實體工作。</p>

<p>檔名也應和內容識別分開。工程師可以保留熟悉的 <code class="language-plaintext highlighter-rouge">reports/timing.rpt</code>，manifest 記錄它的來源及內容；grader 讀取固定提交中的檔案，避免 Agent 下一輪將相同路徑覆寫後改變評分。這讓不同工具的格式可以各自保留，只要 adapter 將共同欄位轉成可檢查資料即可。</p>

<p>可信任的產生者是另一項必要工作。若 Agent 同時能修改 checker、completion record 和 seal，所有欄位都匹配仍可能只是自製答案。實際平台應把 runner 的服務身分、可寫目錄及 grader 輸入控制分開；digest 只協助發現內容改動。權限系統負責誰能產生正式紀錄，領域 checker 負責輸出符合哪些工程條件，兩者需要分別測試。</p>

<h2 id="coverage-累積前先完成同一條軌跡的資料檢查">Coverage 累積前，先完成同一條軌跡的資料檢查</h2>

<p>一次測試可能寫入 7、讀出 8，卻成功碰到 empty-to-nonempty 狀態。Coverage 計數可以完全正確，資料順序卻已經出錯。參考設計讓 monitor 和 coverage instrumentation 共同消費同一次 DUT execution：write handshake 將資料加入期望佇列，read handshake 將實際輸出與佇首比較，reset 依規格清空狀態。</p>

<p>這裡至少有兩個不同定義要固定。第一是什麼時候算一次有效 transfer，例如 valid 與 ready 同時成立；第二是 reset 前後的資料如何處理。若 monitor 把尚未接受的 write 也放進佇列，就會對正確 RTL 產生誤報。Checker 的獨立性需要獨立的規格推導和測試，單純改成另一個 Python 檔案仍留下共用錯誤的可能。</p>

<p>有效 coverage 集合可以寫成：</p>

<p><code class="language-plaintext highlighter-rouge">有效 bins = union(通過同軌跡檢查之 executions 的 bins)</code></p>

<p>這會使錯誤測試的命中暫時退出累積集合，讓下一輪仍看到待補目標。若修改 RTL，集合要改用新 revision，或由明確的相容規則重新建立；沿用舊版的滿分容易掩蓋新缺陷。Agent 可以接收「哪個 bin 尚缺」與拒絕原因，隱藏 expected values 則保留給獨立評量，以減少反覆查詢對最後測試的污染。</p>

<p>2012 年 6 月 4 日，Accellera 公布 <a href="https://accellera.com/news/press-releases/90-accellera-systems-initiative-rolls-out-the-unified-coverage-interoperability-standard-ucis">UCIS 1.0</a>，推進跨工具 coverage 資料的共同存取與交換。這個前例解決資料互通的方向，Agent 流程新增的是高頻變更下的執行對應與生成測試品質。既有 coverage 基礎設施可以沿用，前提是保留能追到原始工作與檢查結果的 metadata。</p>

<p>AMBU-CovAgent 固定程式的 <code class="language-plaintext highlighter-rouge">compute_comparison</code> 分列 hit-only 和 verified，<code class="language-plaintext highlighter-rouge">should_stop</code> 則讀 raw coverage 與 data_fail；這兩組欄位的差別，正好顯示「有命中」與「該命中有資料檢查」需要明確區分。<a href="https://github.com/KrishnaKumarVedantam/AMBU-CovAgent/blob/2a9041dd488e1890daa072cae1577c6e8f9a5892/agent/agent.py">固定版本程式</a>可作靜態對照。本篇的修正方向是先接線、再計分，沒有修改該專案或重現其模型實驗。</p>

<figure>
<a href="/images/ic-design-platform/2026-10-20/artifact-grader-rejection.svg"><img src="/images/ic-design-platform/2026-10-20/artifact-grader-rejection.svg" alt="報告先核對完成狀態，再比對 RTL、測試和執行身分，接著檢查封存內容與同軌跡 checker，只有有效紀錄加入 coverage 集合。" width="640" height="739" loading="lazy" /></a>
<figcaption>圖二：報告採計的參考設計。不同 stimulus 的問題參考 <a href="https://arxiv.org/html/2610.21570v1#S4">AMBU-CovAgent 的限制</a>；版本、completion 與內容比對是本篇合成實驗測試的機制。</figcaption>
</figure>

<h2 id="十個手工案例檢查誤收從哪裡進來">十個手工案例檢查誤收從哪裡進來</h2>

<p>本篇的 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/agentic_artifact_grader.py">Python 協定測試</a>已實際執行，固定十個手工案例。程式用 deque 對照 write/read 資料，沒有執行 RTL simulation；coverage 值是手工 fixture。它的用途是檢查資料對應、拒絕原因與評分計帳，對照方法刻意保留常見的弱實作：只要 coverage 達 98%，另一份 scoreboard 零錯誤就接受，缺值還預設為零。</p>

<p>較嚴格的 grader 逐項比對輸入與 execution、completion、封存 digest、checker 是否存在及同一 trace 的資料結果，再看 coverage。兩個正常案例分別寫入並讀出 7 與 9，其餘案例注入資料錯誤、過期 RTL、不同 stimulus、缺 checker、封存後變更、超時半成品、coverage 不足與已回報錯誤。</p>

<table>
  <thead>
    <tr>
      <th>合成情境</th>
      <th>弱基準</th>
      <th>版本綁定及同軌跡檢查</th>
      <th>拒絕原因</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>兩個正常資料案例</td>
      <td>2 個接受</td>
      <td>2 個接受</td>
      <td>—</td>
    </tr>
    <tr>
      <td>生成 trace 讀出錯值</td>
      <td>接受</td>
      <td>拒絕</td>
      <td>同軌跡資料比對失敗</td>
    </tr>
    <tr>
      <td>舊 RTL／不同測試</td>
      <td>2 個接受</td>
      <td>2 個拒絕</td>
      <td>輸入或 execution 身分不同</td>
    </tr>
    <tr>
      <td>缺 checker</td>
      <td>接受</td>
      <td>拒絕</td>
      <td>檢查結果缺漏</td>
    </tr>
    <tr>
      <td>封存後內容改動</td>
      <td>接受</td>
      <td>拒絕</td>
      <td>digest 及資料檢查失敗</td>
    </tr>
    <tr>
      <td>超時但留下 coverage</td>
      <td>接受</td>
      <td>拒絕</td>
      <td>工作未完成</td>
    </tr>
    <tr>
      <td>coverage 不足／已回報錯誤</td>
      <td>2 個拒絕</td>
      <td>2 個拒絕</td>
      <td>原有條件已能識別</td>
    </tr>
  </tbody>
</table>

<p>弱基準接受八個，其中六個屬於預定義的無效案例；新 grader 接受兩個、誤收零個。兩者對相同十個 fixture 執行，結果與每筆拒絕原因保存在 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/agentic_artifact_grader.results.json">原始輸出</a>。這些案例依同一份設計規格編寫，結果證明程式按規則運作，統計泛化和真實團隊效益另需資料。</p>

<p>這個實驗也揭露最小模型省略的工作。它假設報告由可信任 producer 提供，seal 和 LOCK 都在同一程序中，沒有隔離 Agent 寫入能力；它沒有模擬 async FIFO 的時脈、backpressure 或 reset race。真正接到 cocotb／simulator 時，應先測 monitor 的 reset-heavy 行為、零比較次數、模擬 fatal、舊報告殘留，以及 replay 是否保留原始 trace。把這些列成下一步測試，比宣稱十例通過就能正式採用更有用。</p>

<h2 id="合格率與-ppa-必須保留交集分母">合格率與 PPA 必須保留交集分母</h2>

<p>跨 RTL 與實體流程的評量，還有另一種常見誤算。假設六個 tasks 中功能通過四個、物理條件通過四個，只有兩個同時通過；這兩個的 PPA 分數都是 80%。全體平均應是 <code class="language-plaintext highlighter-rouge">2 / 6 × 0.8 = 26.67%</code>。若把兩個邊際比例相乘，會得到 <code class="language-plaintext highlighter-rouge">4 / 6 × 4 / 6 × 0.8 = 35.56%</code>，多出 8.89 個百分點。</p>

<p>相乘邊際比例暗中加入兩項條件獨立的假設。設計工作通常有強烈關聯：為了時序加 pipeline 可能改變功能 latency，為了減面積共用運算單元可能降低吞吐；同一個架構決定會同時影響多項結果。最簡單的處理是保存逐 task 的功能、實體與 PPA，最後依同一列相乘再平均。上述六例也包含在實跑程式中。</p>

<p>將這個想法套回工具資料，功能報告的 RTL、equivalence 使用的 netlist、STA 的 SDC／SPEF，以及 GDS 的來源都要可對應。若 Agent 在功能測試後修改 pipeline，原先功能 pass 留在歷史，但新的提交需要自己的檢查。保留較佳舊提交則能讓探索失敗有退路，避免最後一輪變更把原本可交付的版本覆蓋。</p>

<p>總分仍要搭配失敗分類。語法錯誤、工具環境失敗、功能錯誤、物理失敗與預算耗盡，分別引導不同的改善工作。把它們全部壓成一個零分適合排名，診斷頁則要保留原因；否則平台團隊可能花時間修改模型描述，實際瓶頸卻是 license 排隊或 parser 拒收新版報告。</p>

<h2 id="失敗的工具工作也要分攤到合格交付">失敗的工具工作也要分攤到合格交付</h2>

<p>假設十次嘗試共消耗 160 core-hours，最後兩次交付合格，平均成本是每份合格成果 80 core-hours。這與只看成功兩次各用 16 core-hours 相差五倍。失敗嘗試有研究價值，也確實使用資源，因此導入評估需保留兩種帳：整個探索活動總成本，以及最後接受的成果數。</p>

<p>CPU、license、token、人工與日曆時間要分欄。16 核心跑一小時是 16 core-hours，單一授權占用一小時是一個 license-hour；二者價格與可取得性各異。等待 license 的兩小時可能幾乎沒有 CPU 消耗，卻延後設計交付。工程師修正 checker、改寫工具描述及判讀誤報的時間，則落在人力帳上。</p>

<p>一個可比較的試驗可先固定二十個任務、每個相同的總工具預算，三條路線分別為人工配既有腳本、固定 recipe 的自動執行，以及可以提出 bounded 變更的 Agent。三條路線共用相同需求、checker 與最後評分資料；資深工程師原本能使用的腳本保留，避免刻意弱化現行流程。任務按設計家族與工具版本分組，將調校使用的集合與最後測試隔開。</p>

<p>模型回合或 token 下降時，先觀察合格交付數與總工具工作是否也改善。若 Agent 更快提出錯誤配置，simulation 反而可能增加；若它精準指出一次 constraint 問題，少量模型成本就可能省掉一整輪 APR。這兩種情況用同一個成功分母才能比較。</p>

<h2 id="固定腳本與隔離重跑各有適用範圍">固定腳本與隔離重跑各有適用範圍</h2>

<p>最便宜的起點通常是保留既有 runner，只把 report、版本和完成狀態補齊。這種 adapter 路線改動小、容易沿用成熟 regression，但 runner 的共用工作目錄與工具狀態仍要仔細處理。另一條路線是每次在隔離環境重跑提交，以獨立 checker 產生最後結果；隔離更清楚，資料搬移、工具啟動與授權整合也更昂貴。</p>

<table>
  <thead>
    <tr>
      <th>路線</th>
      <th>較適合的條件</th>
      <th>主要成本與不足</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>人工＋固定腳本</td>
      <td>需求穩定、失敗類型少、工具流程成熟</td>
      <td>人工處理新問題，變更彈性較低</td>
    </tr>
    <tr>
      <td>原 runner 加版本化 grader</td>
      <td>已有可靠執行服務，需要先減少報告誤配</td>
      <td>逐工具 adapter、共享狀態調查與維護</td>
    </tr>
    <tr>
      <td>隔離提交＋獨立重跑</td>
      <td>Agent 可改動範圍大、需跨模型公平比較</td>
      <td>重跑、資料搬移、license 與環境複製</td>
    </tr>
    <tr>
      <td>自適應 Agent＋相同 grader</td>
      <td>已有固定任務與可信 checker，探索成本可控</td>
      <td>額外模型、評估調校與人工診斷工作</td>
    </tr>
  </tbody>
</table>

<p>這些是合理方案比較，尚無四條路線的實測排名。若既有腳本幾乎全數通過，且工程師介入很少，Agent 的額外組件可能只增加維護；平台應允許保留簡單流程。若任務變體多、工具等待昂貴、人工反覆閱讀 report，模型才較可能透過選擇下一步與修改候選產生淨收益。</p>

<p>長期來看，方法團隊會掌握 task、checker、版本關係與成本資料，供應商提供模型及工具能力。控制點由單次漂亮示範轉向可持續比較的工程規格；模型替換容易一些，checker 與 adapter 的維護責任則更集中。日常抄寫報告的工作可能減少，獨立規格、測試品質及失敗分析的工作會增加。</p>

<p><a href="/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff.html">近期 RapidWright 研究</a>說明已完成局部實作可以用模組庫保存並重用；本篇補上另一面：重用任何 DCP、測試或報告，都需要知道它在哪些條件下仍有效。交付物與評分一起保存，能讓省下的重跑有可核對的品質前提。</p>

<p>未來三個月，較有機會先改善的是既有 flow 上的 report 對應與有限操作評量，而非直接放大自主探索。可先在二十個公開小任務上比較相同品質下的總 tool-hours、人工介入與超時比例；若版本綁定持續攔到誤配，且維護時間低於省下的調查，就擴大到跨工具交接。若獨立重跑經常翻轉原結果，或 checker 誤報占用更多工程時間，應先修正量測流程，再增加 Agent 權限。</p>

<h2 id="工具中斷後半成品應留作診斷資料">工具中斷後，半成品應留作診斷資料</h2>

<p>一個具體失效情境是 simulator 已輸出 coverage，runner 在寫 scoreboard 前失去連線。殘留目錄可能同時存在本輪 coverage、上輪 scoreboard 與未更新的狀態檔。若合併程式僅看檔案存在，就會接受一份從未完整跑完的組合。</p>

<p>參考設計先將每次 execution 寫入獨立 staging 目錄。所有必要報告完成後，由 runner 記錄輸入與輸出 digest，再將完成提交提供給 grader。中斷的目錄保留失敗狀態與診斷資訊；新的嘗試使用新 execution id，避免沿用同一路徑把舊結果變成新結果。已完成的舊提交仍可供工程師選擇，探索的半成品則單獨保留。</p>

<p>偵測方式是檢查執行服務的最終狀態、必要報告集合與身分對應。對於遠端失聯，先確認工作是否仍在跑，再決定續接或取消；重新送出前要處理重複工作與授權占用。本文程式只測「未完成時拒絕採計」，正式的持久化、取消確認與 crash recovery 是後續執行服務工作。</p>

<p>這種安排改善的是報告品質和昂貴重跑的可見性。最終是否值得採用，仍回到同樣設計需求下，每份合格成果使用多少工具、多少人工以及多久日曆時間。Agent 生成更多內容之後，平台要讓團隊清楚知道哪些內容可以繼續使用、哪些需要重新檢查。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>Siemens／NVIDIA 的數字是受控開發子集的供應商自報結果，95% 不是完整 229-cell library 的通過率，也不是量產 signoff 機率。公開材料未提供足以重現的完整 rollout、tolerance、held-out 切分與全成本。本篇沒有執行 Solido、SPICE 或其 NeMo Gym environment，也未觀看並驗證 demo 影片。</p>

<p>Build-A-Chip-Bench 是公開方法與初步自報評量，頁面仍有 coming-soon 項目；本文沒有重跑 task pack、獨立驗證模型排名或把開源工具／PDK 結果外推先進製程。AMBU-CovAgent 的限制依 v1 與固定程式檢視，沒有量測生成 stimulus 的實際無效比例。不同案例的分數不互相比大小。</p>

<p>合成測試只實跑單程序的報告對應、deque 資料檢查、拒絕條件與算式；coverage、身分與成本全為手工資料。沒有 RTL／LLM／EDA、sandbox 隔離、真實 producer authentication、資料庫交易、競態、持久化或多機 crash 測試。十個案例零誤收不構成一般錯誤率或安全保證；98% 是測試設定，並非建議所有設計採用的門檻。全文參考設計不宣稱任何公司的內部部署，不包含內部程式、PDK 或客戶資料。</p>

<h2 id="參考資料">參考資料</h2>

<ul>
  <li>Joshua Mabry／NVIDIA 等，<a href="https://developer.nvidia.com/blog/optimizing-agent-reliability-and-tool-calling-efficiency-for-chip-design-using-nvidia-nemo-gym/">Optimizing Agent Reliability and Tool Calling Efficiency for Chip Design Using NVIDIA NeMo Gym</a>，2026-10-14。</li>
  <li>Surya Gunukula／ChipAgents 等，<a href="https://chipagents.ai/research/build-a-chip-bench">Build-A-Chip-Bench</a>，2026 年 10 月，Task shape 與 Results。</li>
  <li>Venkata Krishna Kumar Vedantam／Portland State University，<a href="https://arxiv.org/html/2610.21570v1">Independent Data-Integrity Verification for LLM-Driven Functional Coverage Closure in Hardware Design v1</a>，2026-10-15；<a href="https://github.com/KrishnaKumarVedantam/AMBU-CovAgent/blob/2a9041dd488e1890daa072cae1577c6e8f9a5892/agent/agent.py">固定 agent.py</a>。</li>
  <li>Accellera，<a href="https://accellera.com/news/press-releases/90-accellera-systems-initiative-rolls-out-the-unified-coverage-interoperability-standard-ucis">UCIS 1.0 公布</a>，2012-06-04。</li>
  <li><a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/agentic_artifact_grader.py">合成協定測試</a>與<a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/agentic_artifact_grader.results.json">實跑輸出</a>。</li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="ic-design-platform" /><summary type="html"><![CDATA[從 Liberty grader、RTL-to-GDS 評量與生成測試的檢查缺口，推導同一次執行的版本綁定、獨立檢查及失敗計帳。實跑合成協定測試，說明如何攔下跨版本報告與缺漏結果，並公平比較人工、腳本和 Agent。]]></summary></entry><entry><title type="html">RapidWright 讓 FPGA 實體模組成為可重用的交付物</title><link href="https://rightson.github.io/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff.html" rel="alternate" type="text/html" title="RapidWright 讓 FPGA 實體模組成為可重用的交付物" /><published>2026-10-19T06:04:03+08:00</published><updated>2026-10-19T06:04:03+08:00</updated><id>https://rightson.github.io/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff</id><content type="html" xml:base="https://rightson.github.io/ic-design-platform/2026/10/19/rapidwright-preimplemented-module-handoff.html"><![CDATA[<p>一個 FPGA 系統若含有數百個相似運算單元，每次修改頂層連線都重新解整顆設計，會重複支付大量局部實作成本。完整重跑仍有合理性：工具能一起調整邏輯、位置與線路，跨模組路徑也能獲得較多最佳化自由。但當功能單元已經穩定、變動主要出現在組合方式，保存局部實體結果就形成另一條工程路線。</p>

<p>AMD Research 的 <a href="https://www.rapidwright.io/docs/Introduction.html">RapidWright</a> 提供可讀寫 Vivado design checkpoint 的 Java 設計介面，讓工程師操作邏輯及實體 netlist。這篇聚焦它公開的預先實作模組方法：先付費找到可重用的局部解，再把整合工作縮小到選擇模組版本、安排位置和連接模組。研究主體是公司研究團隊公開的 CAD 方法與 Vivado 交接，官方程式碼則讓這條方法可以逐步檢查。</p>

<figure>
<a href="/images/ic-design-platform/2026-10-19/rapidwright-module-handoff.svg"><img src="/images/ic-design-platform/2026-10-19/rapidwright-module-handoff.svg" alt="設計團隊固定 RTL、裝置與時脈條件，Vivado 先建立局部實作，RapidWright 重用並拼接模組，再交回 Vivado 完成全域路由與整合檢查。" width="640" height="910" /></a>
<figcaption>圖一：依據 <a href="https://www.rapidwright.io/docs/PreImplemented_Module_Flow.html#high-performance-flow">RapidWright 預先實作流程</a>整理。圖中的功能需求與系統行為檢查是整合責任；箭頭表示交付順序，沒有表示速度比例。</figcaption>
</figure>

<p>沿圖往下看，兩次 Vivado 工作處理不同規模的問題。第一次針對模組建立實體版本，第二次解決組合後才存在的全域路徑。減少重做的工程，來自這個分工。</p>

<h2 id="一份-dcp-同時帶著邏輯與實體狀態">一份 DCP 同時帶著邏輯與實體狀態</h2>

<p>RTL 描述電路行為，綜合後的 netlist 描述元件及連接；完成實作後，還多出元件放在哪個位置、net 使用哪些路由資源。RapidWright 操作的 DCP 是設計快照，依產生階段可包含 netlist、constraints、placement 與 routing。模組交出去的材料因此超過一份可重新綜合的 RTL。<a href="https://www.rapidwright.io/docs/Design_Checkpoints.html">Design Checkpoints 文件</a></p>

<p>這會改變 IP 團隊和整合團隊的工作分配。IP 團隊除了提供接埠及功能，還要選出足以重用的實體配置；整合團隊則拿這些配置安排整個系統。一次已投入的實體最佳化可以跨多個實例及版本攤提，代價是部分局部決策提前固定。</p>

<p>完整路徑可以具體列成下表。前兩列是設計團隊在採用此方法前仍需完成的工程責任，後面才進入公開示範的實體組合流程。</p>

<table>
  <thead>
    <tr>
      <th>階段</th>
      <th>輸入與可改變內容</th>
      <th>交付物與接收工作</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>設計需求與 IP 整合</td>
      <td>功能、吞吐量、latency、時脈、裝置及板級 I/O</td>
      <td>固定 RTL、XDC 和介面規格；接收方確認 pipeline 與 reset 語意</td>
    </tr>
    <tr>
      <td>功能驗證與必要形式檢查</td>
      <td>RTL、測試、協定及跨時脈假設</td>
      <td>功能結果與版本；模組新增一拍須同步修改系統預期</td>
    </tr>
    <tr>
      <td>模組 OOC 實作</td>
      <td>綜合 netlist、pblock、時脈目標與工具選項</td>
      <td>局部 placed-and-routed DCP、接埠資料及報告</td>
    </tr>
    <tr>
      <td>模組庫與系統組合</td>
      <td>模組實體版本、合法位置、頂層連接</td>
      <td>RapidWright 輸出的組合 DCP；保留局部實體結果</td>
    </tr>
    <tr>
      <td>全域完成與板級交付</td>
      <td>系統 DCP、全域 clocks、跨模組 net、I/O 條件</td>
      <td>完整 routing、timing、DRC，再依專案要求產生 bitstream 與做板測</td>
    </tr>
  </tbody>
</table>

<p>FPGA 應用在此交付的是已製造晶片的配置。ASIC R2G 的 standard-cell library、製程 SDC、DFT 插入、APR、GDS signoff 和封裝設計，屬於另一條矽晶片製造交付鏈；兩者可比較交接方式，輸出形式及責任仍各自成立。若用 FPGA 驗證 SoC，DFT 及封裝需求要留在 ASIC 計畫中，板級原型只覆蓋選定的功能與系統情境。</p>

<h2 id="同一份電路要有不同的實體版本">同一份電路要有不同的實體版本</h2>

<p>可重用的實體模組需要符合目標 FPGA 的資源排列。FPGA 內部的邏輯、BRAM、DSP 與特殊區域有固定位置，矩形尺寸相同只解決幾何外形；移動模組還要找到能容納其元件與路由的相容位置。</p>

<p><a href="https://www.rapidwright.io/docs/PreImplemented_Modules_Part_I.html">官方 PicoBlaze 教學第一部分</a>提供一個直覺例子：目標是 VU3P 裝置上的小型微控制器，理論資源下限可估出十五個 slice，但三欄乘五列的緊密配置失敗，四欄乘五列才取得可用結果；流程另用 <code class="language-plaintext highlighter-rouge">CONTAIN_ROUTING</code> 約束局部路由。局部面積壓得越緊，搜尋與佈線越容易受限制，最小資源數因此只是起點。</p>

<p>由此可推得一項平台設計原則：模組庫應保存同一電路的幾種可用實體形狀，讓整合工程師依位置選擇。省去整顆設計的重跑後，工程努力會轉向「哪些形狀能反覆使用」。如果每次都為新的位置製作唯一形狀，資料庫雖持續膨脹，實際攤提次數卻很低。</p>

<p>目前 <a href="https://github.com/Xilinx/RapidWright/blob/adcd4c7cdfc9aeec3ce4e0025e0a35f15af0fa6a/src/com/xilinx/rapidwright/examples/PicoBlazeArray.java">PicoBlazeArray.java</a> 把這個交接寫得很具體。程式讀取多份 <code class="language-plaintext highlighter-rouge">pblock*.dcp</code> 及 metadata，把 BRAM 當模組 anchor，逐一檢查候選位置，選擇可用實作，再建立實例及其接埠連接；它也略過上下方 clock-region 區域以避開特殊資源情境。範例含一般 module 與多實作版本兩條程式路徑。</p>

<p>程式中的「同一種電路、多個實體版本」可以避免為每個實例各做一次搜尋，卻增加版本配對工作。參考設計可以把一個模組項目索引到 RTL／netlist digest、part 與 speed grade、工具 build、XDC、接埠及各實作的 pblock；系統組合另記錄每個 instance 選了哪個版本、放在哪裡。這是團隊可加上的資料設計，官方 metadata 格式與這份索引分開維護。</p>

<p>以模組名稱作唯一索引會留下風險。工程師即使保留相同 module name，也可能更換 BRAM 模式或 reset 行為；若仍取回舊 DCP，最後產物就含有舊功能。索引內容應先決定可重用範圍，檔名只提供查找入口。相反地，僅更改 instance 名稱時，局部電路和實體條件可能完全相同，過度保守的重建又會吃掉收益。</p>

<p>推論到資源安排，緊密包裝和容易搬移還會產生競爭。多留一圈路由空間，可能讓單一模組比較容易閉合，卻降低整顆裝置可容納的實例數；為每個位置增加一種版本，又會拉高探索與維護成本。實體設計團隊應同時記錄每種形狀的資源占用、合法位置數及實際使用次數，讓庫的成長跟隨已發生的需求。</p>

<p>這也影響工作優先順序。一個只使用一次的特殊模組，即使局部搜尋很成功，也可能排在可服務數十個實例的共用模組之後。整合計畫先固定常用介面，實體團隊才容易集中改善少數高重用版本；若前端持續改規格，後端建庫會變成追趕需求的額外工序。</p>

<h2 id="把搜尋成本移到可重複使用的階段">把搜尋成本移到可重複使用的階段</h2>

<p>第二個機制是改變計算工作的時點。單次專案可以承受一次完整探索，多次迭代則有機會共用探索結果。<a href="https://www.rapidwright.io/docs/PreImplemented_Module_Flow.html#module-cache">預先實作流程文件</a>描述，Vivado 先對每種 IP 做 OOC 綜合與實作；RapidWright 的模組資料包含實體資料、共用的壓縮 EDIF 與介面 metadata。BlockStitcher 依頂層連接組合模組，最後由 Vivado 完成全域路由。</p>

<p>這項分工帶來兩種時間。建庫的冷啟動可能很慢，已有合用模組時的暖啟動才會快。對每天只有一個新電路、很少重用的團隊，冷啟動接近常態；對同一組功能單元反覆改系統組合的團隊，暖啟動占比才有機會提高。導入決策因此應按實際版本序列計帳，包含失敗搜尋與被淘汰的模組。</p>

<p>時脈也是建庫與整合間的重要相依。局部路徑表現很好，跨模組長線仍可能成為 critical path。設計若允許額外 latency，可以在模組間增加 pipeline，換取較短的組合路徑；但資料、valid、ready、reset 和控制資訊都要保持對齊。只替資料加暫存器而沿用原控制協定，可能讓頻率改善伴隨功能錯誤。</p>

<p>同樣地，高複製次數通常有利於攤提，但高度密集的全對全通訊會把成本推回頂層路由。整合者應分開觀察「模組內部路徑」與「跨模組路徑」的惡化程度。若後者已支配設計，繼續提高模組庫的局部品質，改善空間就會縮小；需要回到連線拓樸、位置安排或系統 pipeline。</p>

<h2 id="從三種-picoblaze-實作走到整個陣列">從三種 PicoBlaze 實作走到整個陣列</h2>

<p><a href="https://www.rapidwright.io/docs/PreImplemented_Modules_Part_II.html">官方教學第二部分</a>在三個 pblock 上組合兩種 placer directive、兩種 router directive 和十五個 clock-uncertainty 設定，共一百八十次候選實作；再把選出的局部實作組成三百九十六個 PicoBlaze。這是指定 VU3P 教學的流程與規模，讀者可以順著參數和產物重建操作。</p>

<p>完整案例的輸入包括微控制器 netlist、三種區域配置、時脈目標與候選工具設定。探索階段先比較每種區域可取得的局部解；陣列建立階段則安排 instance，把相鄰單元的八位元接埠連起來，補上系統 clock、reset 及頂層 I/O，再輸出 DCP。接收工程師得到的是一份含既有局部路由的系統設計，仍要處理新增的全域關係。<a href="https://github.com/Xilinx/RapidWright/blob/adcd4c7cdfc9aeec3ce4e0025e0a35f15af0fa6a/src/com/xilinx/rapidwright/examples/PicoBlazeArray.java">範例連接程式</a></p>

<p>教學接著明列 <code class="language-plaintext highlighter-rouge">update_clock_routing</code>、<code class="language-plaintext highlighter-rouge">route_design</code> 和 <code class="language-plaintext highlighter-rouge">report_timing_summary</code>；其範例報告給出約 365 MHz 的時脈能力。這個結果伴隨模組建庫、裝置和連線條件，適合用來理解完整交接，不能拆成「拼接後自然保有原頻率」的保證。<a href="https://www.rapidwright.io/docs/PreImplemented_Modules_Part_II.html">陣列全域完成步驟</a></p>

<p>若重跑此案例，建議固定一組 Vivado 與 RapidWright 版本，保留每個候選的實際輸入及 timing report，再記錄陣列建立前後的 clock 與 constraint。檢查至少應覆蓋 setup、hold、未受約束的路徑、route status 及 DRC；最後再以功能測試核對系統連接。零退出碼只描述程序結束，工程師仍需閱讀哪些路徑被計入分析。</p>

<p>這條流程最有意思的分工，是 IP 團隊可以提供「已找到的一小組好解」，整合者再決定哪些解值得組合。若局部選擇導致全域失敗，應保留那份組合 DCP 和報告，換一種模組配置或安排後再完成全域實作；若發現模組本身功能變動，則回到建庫階段。兩種失敗的重跑範圍不同。</p>

<h2 id="十二次迭代才回收的假設成本">十二次迭代才回收的假設成本</h2>

<p>把官方的一百八十次搜尋作為工作數量，另假設每次花十五分鐘，建庫就需要 <code class="language-plaintext highlighter-rouge">180 × 0.25 = 45</code> 工作小時。再假設完整重跑每版六小時，已有模組庫後，拼接、全域路由與共同檢查合計每版兩小時。這些時間全部是明示假設，以下程式實跑的是成本模型。</p>

<p>設版本數為 N，完整重跑成本是 <code class="language-plaintext highlighter-rouge">6N</code>，重用成本是 <code class="language-plaintext highlighter-rouge">45 + 2N</code>，單位皆為 implementation-job hours，也就是各工具工作時數加總。故 <code class="language-plaintext highlighter-rouge">45 + 2N &lt; 6N</code> 要求 <code class="language-plaintext highlighter-rouge">N &gt; 11.25</code>，第十二版才開始節省。兩條路線應包含相同必要檢查，避免讓完整重跑負擔較嚴格的流程。</p>

<table>
  <thead>
    <tr>
      <th>版本數</th>
      <th>完整重跑</th>
      <th>建庫加重用</th>
      <th>重用節省</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>6 h</td>
      <td>47 h</td>
      <td>−41 h</td>
    </tr>
    <tr>
      <td>5</td>
      <td>30 h</td>
      <td>55 h</td>
      <td>−25 h</td>
    </tr>
    <tr>
      <td>12</td>
      <td>72 h</td>
      <td>69 h</td>
      <td>3 h</td>
    </tr>
    <tr>
      <td>20</td>
      <td>120 h</td>
      <td>85 h</td>
      <td>35 h</td>
    </tr>
  </tbody>
</table>

<figure>
<a href="/images/ic-design-platform/2026-10-19/rapidwright-reuse-amortization.svg"><img src="/images/ic-design-platform/2026-10-19/rapidwright-reuse-amortization.svg" alt="假設建庫需要四十五工作小時，每版由六小時降到兩小時，到第十二版才回本；二十版可省三十五小時，但每十版重建一次會反而多花十小時。" width="640" height="880" loading="lazy" /></a>
<figcaption>圖二：假設算例，數值由<a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/rapidwright_reuse_cost.py">成本模型程式</a>產生；不是 Vivado 或 RapidWright 的效能量測。</figcaption>
</figure>

<p>若每十版就因介面或實體條件變更而完整重建，二十版要支付兩次建庫，成本變成 <code class="language-plaintext highlighter-rouge">2 × 45 + 20 × 2 = 130 h</code>，比完整重跑的一百二十小時多十小時。同一套暖啟動數字，足以支持相反的導入結果；造成差異的是模組庫可用多久。</p>

<p><a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/rapidwright_reuse_cost.results.json">實跑結果檔</a>保存四組穩定重用情境、十版重建情境及假設。程式可用 <code class="language-plaintext highlighter-rouge">python3 scripts/experiments/rapidwright_reuse_cost.py</code> 重跑，另以逐版累加核對重建發生在第一版與第十一版。這個測試檢查計帳及臨界值，FPGA placement、routing 和 PPA 均未執行。</p>

<p>工作時數和日曆時間還要分開。如果有十二個可同時工作的槽位，四十五工作小時的理想計算下限是 3.75 小時，另加啟動、等待與最慢候選的影響；共享資源緊張時，建庫可能跨越更久。若不同階段使用不同核心數或授權 token，還應分別換算 CPU-hours 與 license-hours。CAD 團隊維護模組庫、除錯及審查的人工成本，也應列在同一份導入評估。</p>

<h2 id="完整重跑與固定-shell-都是合理選擇">完整重跑與固定 shell 都是合理選擇</h2>

<p>完整實作保有最多全域最佳化自由，也省下自訂模組庫的維護。當模組變動頻繁、設計較小或跨模組路徑主導時，它是有力的比較基準。選用 RapidWright 之前，應先確認現有工具流程已正常設定，避免把錯誤 baseline 的耗時算成重用收益。</p>

<p>另一條路是固定系統 shell，只替換少量變動邏輯。<a href="https://www.rapidwright.io/docs/ReusingTimingClosedLogicAsAShell.html">RapidWright 的 timing-closed shell 教學</a>從完整實作移除動態模組，保留靜態邏輯，再把新內容放回原介面；它使用保留介面與鎖定實體路由的步驟。這種重用固定平台的位置，與搬動數百個模組的工作形狀不同。</p>

<table>
  <thead>
    <tr>
      <th>路線</th>
      <th>適合的變動形狀</th>
      <th>主要代價</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>完整 Vivado 實作</td>
      <td>大量 RTL 或全域架構一起改動</td>
      <td>每版支付較多實作時間，保留較大最佳化自由</td>
    </tr>
    <tr>
      <td>RapidWright 預先實作模組</td>
      <td>穩定單元大量複製，組合經常調整</td>
      <td>建庫與合法位置管理，局部固定後犧牲部分全域自由</td>
    </tr>
    <tr>
      <td>固定 timing-closed shell</td>
      <td>靜態平台穩定，只有局部內容更換</td>
      <td>介面與周邊資源限制，新增內容仍須完成整合實作</td>
    </tr>
  </tbody>
</table>

<p>shell 做法也會反過來影響功能分工。保留的介面越穩定，平台重用越容易；若應用需要新增 clock、增加外部頻寬或大改 reset，既有 shell 的維護範圍就會擴大。模組重定位、固定 shell 以及裝置執行時的動態部分重配置，各自處理不同階段的問題，團隊應先明確選定要縮短哪一段迭代。</p>

<h2 id="三家公司把重用放在不同交接點">三家公司把重用放在不同交接點</h2>

<p>跨公司比較應看實際交付物。<a href="https://nvdla.org/hw/v2/integration_guide.html#synthesis">NVIDIA NVDLA 整合手冊</a>提供配置後 RTL、製程相關 cell 替換及綜合輸入輸出的接點；<a href="https://www.arm.com/products/cloud-datacenter/neoverse-compute-subsystems">Arm Neoverse CSS</a>則以已驗證、針對目標製程最佳化的運算子系統，替合作夥伴承擔部分非差異化整合工作。這兩者分別反映公開參考 IP 流程及商用子系統交付。</p>

<p>RapidWright 的公開方法再把重用推到 FPGA 的局部 placed-and-routed 狀態。三者都能減少下一個團隊需要重做的工作，限制則隨交付深度增加：RTL 接收者有較多重新實作自由，實體模組接收者要遵守更具體的裝置與位置條件。這是依交付物作出的工程比較，沒有對三家公司做速度排名。</p>

<p><a href="https://www.rapidwright.io/docs/_downloads/ba6c3a2f111b835c0e91e90884c0d55e/FCCM18-RapidWright.pdf">Xilinx Research Labs 的 Chris Lavin 在 2018 年 FCCM 的原始論文</a>已把局部實作重用與模組複製列為設計策略，並區分單純 RTL 重整與預先實作的結果。這個有日期的前例提醒我們，效益可能同時來自架構重整和實體重用；比較時應保留「原始設計、重整後完整實作、重整後模組重用」三組結果，才看得出哪一筆投入產生改善。</p>

<p>從團隊分工推論，長期資產會由單一專案的 Tcl recipe，延伸到有明確適用條件的實體模組庫。工具工作可能減少，IP 團隊的維護及整合溝通卻會增加；依賴也持續集中在裝置資料、DCP 相容性與 Vivado 完成流程。若 library owner 沒有資源維護版本，整合工程師就得自行承擔相容性調查，節省的運算成本可能換成更多人力。</p>

<p>未來三個月，團隊可選一個具有重複單元的公開設計，固定工具與裝置，對十次真實的設計變更同時跑完整實作、模組重用與固定 shell。逐版保存冷暖成本、人工介入時間、跨模組關鍵路徑和最終 timing；若只有暖啟動變快、累積成本及品質反而惡化，導入範圍就應縮小。若跨多次變更仍能維持相同功能及時脈要求，再增加模組庫覆蓋。</p>

<p><a href="/eda/2026/09/30/nvidia-nvdla-config-to-synthesis-handoff.html">前一篇 NVDLA 文章</a>停在生成 RTL、製程相關 views 與綜合資料的交接；RapidWright 補上保存局部實體結果再整合的一段。穩定介面、大量重複且全域連線可控制的設計，最有機會用前期建庫換取較短迭代；下一個實驗應直接量出模組庫在需求變動下的有效壽命。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>RapidWright 文件此次頁首為 2026.1.1-beta，PicoBlaze 教學未提供可據以推定所有範例數字更新日期的版本記錄；因此本文把數字標成官方教學結果，不稱為 2026 年重新量測。原始論文是 2018 年 Xilinx Research Labs 研究，現行文件將 RapidWright 列為 AMD Research 提供的框架；這些資料不足以證明 AMD 內部 ASIC 量產平台採用同一流程。</p>

<p>本文讀取官方程式碼 commit <code class="language-plaintext highlighter-rouge">adcd4c7cdfc9aeec3ce4e0025e0a35f15af0fa6a</code> 作為介面對照，沒有執行 Vivado、RapidWright 或 FPGA 板測。約 365 MHz 僅是官方指定陣列案例數字；一百八十次搜尋沒有搭配可直接引用到本文成本模型的實測工時。程式輸出全部是合成成本試算，沒有量測 PPA、功耗、license 消耗或真實開發時程。</p>

<p>DCP 文件明示加密設計與跨工具版本相容性的限制；checkpoint reader/writer 的 API library 另有修改版 Xilinx 授權條款。公開預先實作流程也註明其 RapidWright router 當前停用，本文因此把最終全域路由交回 Vivado。公司比較只涵蓋各自已公開的交付位置，不推定完整內部 CAD 架構，也不外推到商用先進製程 signoff。</p>

<h2 id="參考資料">參考資料</h2>

<ul>
  <li><a href="https://www.rapidwright.io/docs/Introduction.html">RapidWright Introduction</a>及<a href="https://www.rapidwright.io/docs/Design_Checkpoints.html">Design Checkpoints</a>，AMD Research 公開文件，頁首版本 2026.1.1-beta。</li>
  <li><a href="https://www.rapidwright.io/docs/PreImplemented_Module_Flow.html">A Pre-implemented Module Flow</a>，模組庫、BlockStitcher、Vivado 交接及流程限制。</li>
  <li><a href="https://www.rapidwright.io/docs/PreImplemented_Modules_Part_I.html">Pre-implemented Modules Part I</a>與<a href="https://www.rapidwright.io/docs/PreImplemented_Modules_Part_II.html">Part II</a>，VU3P PicoBlaze 教學。</li>
  <li><a href="https://www.rapidwright.io/docs/ReusingTimingClosedLogicAsAShell.html">Reusing Timing-closed Logic as a Shell</a>，固定實體平台的互補方法。</li>
  <li>Chris Lavin／Xilinx Research Labs，<a href="https://www.rapidwright.io/docs/_downloads/ba6c3a2f111b835c0e91e90884c0d55e/FCCM18-RapidWright.pdf">RapidWright: Enabling Custom Crafted Implementations for FPGAs</a>，FCCM 2018。</li>
  <li><a href="https://github.com/Xilinx/RapidWright/blob/adcd4c7cdfc9aeec3ce4e0025e0a35f15af0fa6a/src/com/xilinx/rapidwright/examples/PicoBlazeArray.java">PicoBlazeArray.java 固定版本</a>，模組載入、位置判定、接埠連接與 DCP 輸出。</li>
  <li><a href="https://nvdla.org/hw/v2/integration_guide.html">NVDLA Integrator’s Manual</a>及<a href="https://www.arm.com/products/cloud-datacenter/neoverse-compute-subsystems">Arm Neoverse CSS</a>，用於交付物比較。</li>
</ul>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="ic-design-platform" /><summary type="html"><![CDATA[AMD Research 的 RapidWright 以 checkpoint 重用局部佈局與佈線，把建庫和系統整合分開；模組重複、介面穩定時能攤提實作成本，頻繁改動或全域連線主導時則可能失去優勢。]]></summary></entry><entry><title type="html">商品目錄快取擴容，要一起搬動版本與回源預算</title><link href="https://rightson.github.io/distributed-systems/2026/10/16/distributed-cache-versioned-refill-resharding.html" rel="alternate" type="text/html" title="商品目錄快取擴容，要一起搬動版本與回源預算" /><published>2026-10-16T19:08:11+08:00</published><updated>2026-10-16T19:08:11+08:00</updated><id>https://rightson.github.io/distributed-systems/2026/10/16/distributed-cache-versioned-refill-resharding</id><content type="html" xml:base="https://rightson.github.io/distributed-systems/2026/10/16/distributed-cache-versioned-refill-resharding.html"><![CDATA[<p>一家提供多租戶商店的電商平台，讓商家修改商品名稱、圖片與展示文案，消費者則在活動期間大量開啟商品頁。商品資料原本由目錄 API 直接查資料庫，平常運作正常；活動連結被分享後，重複讀取開始拖慢商家的更新與管理頁。</p>

<p>消費者希望快速看到商品，商家則希望更新能在合理時間內出現。平台還會增加 API 與快取節點：若每次擴容都讓大量讀取重新打進資料庫，增加容量反而會造成停頓。接下來要設計的快取服務，必須同時回答資料能落後多久、誰有權回填，以及資料搬家時來源能承受多少工作。</p>

<p>先看原有路徑：大量訪客與少量商家操作共用目錄來源。圖中保留這個最小系統，先把新鮮度與來源負載要求說清楚，再加入快取與分區。這是一個公開技術機制支持的參考設計，所有業務流量均為假設。</p>

<figure>
  <img src="/images/distributed-systems/2026-10-16/catalog-cache-service-context.svg" alt="訪客讀取與商家更新共用商品目錄來源，訪客尖峰每秒三十萬次，來源安全讀取預算每秒兩萬次" style="max-width:100%;height:auto;" />
  <figcaption>圖 1｜參考設計的起始情境。讀取尖峰超出來源預算，而商家更新仍要可靠保存。容量相依的問題參考 <a href="https://aws.amazon.com/builders-library/caching-challenges-and-strategies/">AWS Caching challenges and strategies</a>；圖中數值與服務需求為假設。</figcaption>
</figure>

<h2 id="展示內容可以落後三十秒成交與授權另走權威路徑">展示內容可以落後三十秒，成交與授權另走權威路徑</h2>

<p>功能先限於按商品 ID 讀取名稱、圖片、展示文案，以及商家更新這些欄位。搜尋、推薦、精確點擊計數不在本次範圍；庫存預留、結帳價格與存取權判定也不交給這份展示快取。商品頁上的展示資料可能短暫落後，提交訂單時則重新確認成交資訊。</p>

<p>本案例採單區域，假設讀取尖峰 300,000 次／秒、更新尖峰 2,000 次／秒，熱工作集 2,000 萬筆。目錄讀取入口至送出回應的 P99 目標為 50 ms、有效請求成功率 99.99%；合法但不存在的商品回 404 算正常結果，來源過載回 503 算服務失敗。更新成功的資料必須在約定的單節點故障接手後保留，快取全失則允許暫時降低讀取可用性。</p>

<p>展示資料的硬限制是：在 API 做出回應判定時，採用的來源觀測距今最多三十秒。每次來源讀取必須是能看到當時已提交資料的短查詢，避開落後副本與長時間舊 snapshot。管理者更新後取得版本，例如 42；管理頁可帶 <code class="language-plaintext highlighter-rouge">min_version=42</code> 要求讀到至少該版本，必要時直接回源。一般訪客讀取接受三十秒內的舊版本，兩條路徑分別計量。</p>

<p>需要維持的規則很具體：租戶 A 的資料永遠不會因 key 相同而回給 B；同一 owner 已知的商品版本下限不因延遲回填倒退；搬到另一個節點或 L1 時保留原截止時間；來源查詢與背景預熱共用有上限的總預算。快取寫入成功只表示一份可丟棄副本已安裝，商家更新成功則表示權威交易已持久化，兩者分開回應。</p>

<p>若產品要求更新成功後所有訪客立刻看到新版，後面的有界陳舊方案就要改選。三十秒是明示的產品取捨；立即可見則需要把協調放進更新確認或讀取路徑。</p>

<h2 id="先用一份資料庫完成讀取與更新">先用一份資料庫完成讀取與更新</h2>

<p>最小版本是一組無狀態目錄 API，加上一個具交易與故障接手保證的資料庫。公開讀取使用 <code class="language-plaintext highlighter-rouge">GET /v1/catalog/items/{id}</code>，租戶由已驗證的站台或服務身分解析，回應包含 <code class="language-plaintext highlighter-rouge">item_id、version、display</code>；管理更新使用 <code class="language-plaintext highlighter-rouge">PATCH</code>，帶 <code class="language-plaintext highlighter-rouge">expected_version</code> 與請求識別。版本不符就回衝突，同一請求識別重試則找回原結果。</p>

<p>資料表以 <code class="language-plaintext highlighter-rouge">(tenant_id, item_id)</code> 為主鍵，保存 <code class="language-plaintext highlighter-rouge">version、display_payload、state、updated_at</code>；管理列表另設 <code class="language-plaintext highlighter-rouge">(tenant_id, updated_at, item_id)</code> 索引。更新交易原子檢查 expected_version、增加版本、改 payload，並保存請求結果。商品 ID 不重用；刪除保留遞增版本的終態記錄，避免「刪除後重建」讓版本重新從一開始。交易與請求識別的處理可接續<a href="/networking/2026/09/24/short-url-uniqueness-idempotency-cache-hotspots.html">短網址服務</a>，這裡不重新設計 ID 分配器。</p>

<p>一次正常更新是驗證商家身分 → 鎖定自己的商品列 → 檢查版本 → 提交新版與請求結果 → 回傳版本 42。讀取則以同一主鍵查短查詢，確認商品屬於該租戶與可展示狀態，再組回應。這個版本沒有跨節點快取一致性問題，先量來源的讀寫混合負載與延遲，就能知道是否需要下一步。</p>

<p>假設容量測試已替此案例設定來源讀取安全預算 20,000 次／秒，並已替更新保留資源。相較讀尖峰，至少需要擋下 <code class="language-plaintext highlighter-rouge">1−20,000/300,000 ≈ 93.3%</code> 的來源查詢，才能僅從平均請求數維持預算；實際還要替故障、偏斜與管理強讀留餘裕。因此先加入共用記憶體快取，目標穩態命中率 99%，讓一般回源約為每秒 3,000 次。這是容量目標，尚待壓測證明。</p>

<h2 id="每個-key-除了值還要帶著來源時間">每個 key 除了值，還要帶著來源時間</h2>

<p>快取先用 cache-aside：API 先查快取，miss 才查來源並回填。key 是包含 schema 版本的 <code class="language-plaintext highlighter-rouge">catalog:v1:&lt;tenant&gt;:&lt;item&gt;</code>，value 保存 payload、來源版本、來源讀取起點、soft deadline 與 hard deadline。各層傳遞截止時間，避免以接收時間重設三十秒。</p>

<p>例如來源查詢在 12:00:00 開始，結果因排隊到 12:00:02 才回到快取，硬期限仍從 12:00:00 算。這裡假設所有參與節點的時鐘相對 UTC 誤差各不超過 100 ms，名義 hard lifetime 使用 29.8 秒，為兩端最壞 200 ms 差額留餘裕；時鐘失控的節點停用快取回應。L1、備份快取及搬移複本都保存同一 absolute deadline，API 在送出前再檢查一次。</p>

<p>這個設計借用 HTTP cache 對傳輸延遲與 resident time 都要計入 age 的原則，應用層版本與期限欄位依本案例定義。<a href="https://www.rfc-editor.org/rfc/rfc9111.html#section-4.2.3">RFC 9111 §4.2.3</a>明確把 request／response 延遲與本地停留時間納入 age 計算。</p>

<p>soft deadline 可以在來源讀取後三至五秒隨機分散。soft 到期而 hard 尚未到期時，仍可回現有展示資料，同時讓一個請求負責更新；hard 到期就停止使用，來源不可用時回 503。這樣的 stale serving 消耗既有期限，沒有新增延長。AWS 的<a href="https://aws.amazon.com/builders-library/caching-challenges-and-strategies/">雙 TTL 做法</a>提供相同的基本取捨：較早嘗試更新，依賴失效時用到硬期限為止。</p>

<p>真正不存在的主鍵可以短暫 negative cache，例如兩秒，但來源逾時或容量拒絕保留為 UNAVAILABLE，避免把故障寫成 NOT_FOUND。新增商品會產生新版本通知，管理頁又可要求至少建立版本，因此兩秒負快取只影響接受一般展示一致性的訪客。</p>

<h2 id="失效先到回填後到單純刪-key-會留下裂縫">失效先到、回填後到，單純刪 key 會留下裂縫</h2>

<p>現在追蹤一次實際會影響新鮮度的交錯。讀者 R 遇到 miss，去來源取得 v41；商家隨後提交 v42，API 刪除快取；R 最後才把 v41 寫回。刪除命令全部成功，舊內容仍重新出現。加入 version 欄位也還少一個條件：空 key 已沒有可以比較的新版值。</p>

<p>2013 年 Facebook 的 Rajesh Nishtala 等人在《Scaling Memcache at Facebook》中，以 key 綁定的回填 lease 處理 stale set，並限制同 key 回源競爭。<a href="https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf#page=4">原論文 §3.2.1</a> 這提供機制起點，下面再補上本服務需要的重啟與搬移狀態。</p>

<p>快取節點為每個 key 原子管理 <code class="language-plaintext highlighter-rouge">generation、min_source_version、active_token</code>。miss 時只有一個呼叫者拿到 token，其餘得到 WAIT 或仍在期限內的 stale 值。token 綁定路由 epoch、owner incarnation、key、generation、單次序號與一秒期限；同一 owner 的發放序號不重用，每次重啟換 incarnation。外部 caller 無權自製 token 或任意 PUT。</p>

<p><code class="language-plaintext highlighter-rouge">Fill(token, source_version, payload, hard_deadline)</code> 必須在 owner 同一原子操作中核對：token 仍是 active、未過期、屬於目前 incarnation 與路由 epoch，來源版本至少等於 min_source_version，且 hard deadline 尚未到。安裝成功即消耗 token。等待者再次 Lookup 就讀到同一結果；填入成功而回應遺失，重試舊 token 不會再次修改狀態，caller 重新 Lookup 即可。</p>

<p>商家更新交易同時保存版本化失效事件，傳送者依 <code class="language-plaintext highlighter-rouge">(tenant,item,version)</code> 可重送。owner 收到較新的 v42 時把最低版本推到 42，推進 generation 並撤銷 active token，標記較舊 payload 待更新；重複或較舊事件保持現狀，成功回填也提高已知版本下限。DB 與快取之間沒有共同交易，所以事件傳遞是常態加速路徑，三十秒硬限制仍由來源時間保住。</p>

<p>若交易提交後傳送程序立刻崩潰，來源仍留著 v42 與待送事件，快取可能保留 v41。程序接手後由持久化進度繼續掃描並重送，監看最舊待送事件的年齡；通知中斷期間，一般展示最多用到原 hard deadline，管理者的 min_version 讀取則跳過 v41。已知舊值即使暫時供展示，也保持 stale 標記，收到通知的時間不會成為新的來源觀測時間。</p>

<figure>
  <img src="/images/distributed-systems/2026-10-16/cache-refill-version-race.svg" alt="讀者以舊 generation 取得 v41，商家提交 v42 後失效使 generation 前進，晚到的舊 token 回填被拒絕" style="max-width:100%;height:auto;" />
  <figcaption>圖 2｜參考設計的失效與回填競態。lease 的基本機制依據 <a href="https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf#page=4">Scaling Memcache at Facebook §3.2.1</a> 整理；epoch、incarnation 及來源版本檢查為本案例補充。</figcaption>
</figure>

<p>這裡第一個完整故障是 R 讀到 v41 後暫停，v42 事件已處理，R 才醒來。殘留狀態包括 R 的舊 token／payload，以及 owner 的新 generation 與最低版本。R 回填得到拒絕，使用者可改走一次 Lookup 或在原 deadline 內重讀來源；新回填須取得新 token。偵測看版本拒絕計數與失效傳遞 lag，處理時丟棄舊結果，避免無條件 SET 作為補救。</p>

<p>若 owner 在期間重啟，舊 token 也會因 incarnation 不同失效。若只是 value 被 eviction，仍須作廢相關 token；新建 metadata 使用新的發放序號，避免舊 token 因 generation 歸零而復活。版本下限可保留到所有在途來源查詢期限結束，之後才清理；來源讀取超過一秒就放棄，不能無限期帶著舊 snapshot 回填。</p>

<p>Memcached 現行 <a href="https://docs.memcached.org/protocols/meta/#serve-stale">Meta Text Protocol</a>提供 CAS、更新權與 stale 標記，可作為部分實作材料；完整 token 格式與跨路由語意仍需自行實作並測試，普通 GET／SET／DEL 並未包含上述全部保證。</p>

<h2 id="記憶體放不下後再決定-key-搬到哪一台">記憶體放不下後，再決定 key 搬到哪一台</h2>

<p>若每筆熱資料連同 key 與基本欄位平均 1,536 bytes，2,000 萬筆需要 <code class="language-plaintext highlighter-rouge">20,000,000×1,536=30.72 GB</code>。假設為可用性保存兩份快取資料，原始資料為 61.44 GB，再用 1.5 倍計入 allocator、索引與 metadata，約 92.16 GB。若正常只使用配置記憶體的 60%，需配置約 153.6 GB。這些 GB 均採十進位，程序 RSS 另以實測校準。</p>

<p>這個量級支持把共用快取分到多台，並保留每台的配置餘裕。以十六台均衡放置估算，每台約需 9.6 GB 配置容量；CPU、NIC 與大物件分布還要另測。尖峰只算 payload 回傳就有 <code class="language-plaintext highlighter-rouge">300,000×1,536≈460.8 MB/s</code>，約 3.69 Gbit/s，尚未計協定、第二份資料的更新與預熱。容量規劃因此同時看記憶體與每節點服務成本。</p>

<p>TTL 與 eviction 也各自處理不同問題：TTL 限制資料可供應的時間，eviction 在記憶體不足時提前丟棄資料。保留大量低重用掃描結果，會把真正熱門的工作集擠出，讓命中率下降並增加回源。因此先以租戶記憶體配額、最大 value 及入口限制隔離掃描，再評估是否採第二次存取才納入的 admission policy。若第二次存取也要計數，計數表本身同樣有容量上限；盲目替每個任意 key 保存完整 metadata，會把攻擊面移到另一張表。</p>

<p>最簡單的 <code class="language-plaintext highlighter-rouge">hash(key) mod N</code> 會在 N 改變時大量改路由。若從十六變十七，均勻雜湊下只有約 1/17 保持相同編號，約 94.1% key 會換位置。這會讓原本的記憶體命中大幅消失。改用一致性雜湊，可把新增節點影響限在其取得的區間；Amazon 的 2007 年 Dynamo 論文描述了這類分區與 virtual node 思路，這裡只借用放置機制，不採用其完整儲存一致性模型。<a href="https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf#page=5">Dynamo §4.2</a></p>

<p>本設計把 key 先雜湊到固定 4,096 個邏輯 bucket，再以版本化表映射到物理節點；bucket 的 key 集合保持穩定，擴容只改其 owner。它達到有限搬動的效果，也方便逐 bucket 控制進度。理想均衡增加第十七台約需移動 241 個 bucket，即 5.88%；這是主副本 placement 之外的單一 owner 算例，兩份資料的故障域安排另受放置規則限制。</p>

<p>bucket 數量多有助於平均配置，卻無法切開同一 key。若一個商品占每秒 90,000 次讀取，該 key 仍只落到一個主 owner。這時在三十二台 API 各放 0.5 秒 L1，並做 process 內同 key 合併，理想穩態只需約 <code class="language-plaintext highlighter-rouge">32/0.5=64</code> 次／秒到 shared cache；代價是多份 payload 與版本通知。L1 仍沿用 hard deadline，沒有因短 TTL 重建新的三十秒。</p>

<h2 id="新節點加入時先給它可承擔的冷流量">新節點加入時，先給它可承擔的冷流量</h2>

<p>搬動 5.88% key 看似不大，仍可能移走約 118 萬筆熱資料。依前述 1,536 bytes 算，單份 payload 約 1.81 GB。若真的以 100 MB/s 可用搬移頻寬連續複製，至少需要約十八秒，實際還有源端讀取、metadata、節流與競爭。快取可重建，所以也能不複製，但來源就必須承擔冷資料回填。</p>

<p>用數字決定切換節奏：假設被搬 bucket 的 5.88% 流量原先大多命中，一次冷切可能新增約每秒 17,640 次回源，加上原本約 3,000 次，超出 20,000 的安全預算。若每次只切一個均衡 bucket，瞬間新增約 <code class="language-plaintext highlighter-rouge">300,000/4,096≈73</code> 次／秒，並在命中率回升後才切下一批，來源就有控制空間。熱門 bucket 要用實際請求率估計，按 key 數平均會低估它。</p>

<p>遷移採「準備、暖機、切路由、排空」四步。新 owner 先接收資料副本及版本通知，所有複製值保留原 hard deadline，不搬 active token。複製途中若 v42 事件先到，新 owner 先提高最低版本，晚到的 v41 複本也要經版本比較。尚未建立足夠失效進度的新 owner，可以直接冷起並只接受從權威來源讀回的新資料。</p>

<p>到切換點，管理平面發布新的 bucket map epoch，舊 owner 停止替該 bucket 發出新回填權，撤銷未完成 token；新 owner 以自己的 incarnation 與 epoch 發放 token。舊路由請求會得到 MOVED 或在原期限內讀到既有副本。若節點失聯導致短暫分裂路由，本設計接受重複快取與重複回源，仍由絕對期限維持展示新鮮度，來源入口的總預算則限制額外負載。</p>

<figure>
  <img src="/images/distributed-systems/2026-10-16/cache-bucket-cutover.svg" alt="穩定 bucket 由舊 owner 複製資料至新 owner，保留硬期限，切換 epoch 時舊 token 作廢，新 owner 重新取得回填權" style="max-width:100%;height:auto;" />
  <figcaption>圖 3｜參考設計的單 bucket 搬移。穩定分區與放置思路參考 <a href="https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf#page=5">Dynamo §4.2</a>；分批暖機、token 作廢與截止時間繼承為本案例設計。</figcaption>
</figure>

<p>失效事件在過渡期送到舊、新兩組 owner，直到舊路由與在途操作排空。切換後回滾也發布更高 epoch，重新冷起或驗證仍在期限內的資料，保留已知版本下限；不直接把舊 map 與舊 token 一起復活。若失效進度不清楚，就丟棄受影響副本再有界回源。這比搬權威資料庫簡單，原因是允許犧牲命中率重建，商品資料本身仍在來源。</p>

<h2 id="一台快取失效也可能超過整個來源預算">一台快取失效，也可能超過整個來源預算</h2>

<p>第二個完整故障是某節點重啟。即使資料與讀取完全均衡，單份 owner 的十六分之一流量約為每秒 18,750 次。若沒有可用第二份資料，與穩態回源相加的保守上界約為 21,750 次／秒，已超過來源預算；全 cache 失效時更是每秒 300,000 次，等於安全容量十五倍。</p>

<p>節點重啟留下空記憶體、新 incarnation、API 上各不相同的 L1 子集；來源商品仍完整。使用者先看到部分延遲增加，接著冷門 miss 可能收到 503，熱門商品可能靠 L1 或未過期限的第二份資料繼續服務。回源率、來源排隊與 cache timeout 搭配健康探針觀測，才能在來源資源耗盡前開始拒絕。</p>

<p>來源入口總上限假設為每秒 20,000 次，前景讀取最多使用 12,000、背景更新與暖機最多使用 8,000，且總 in-flight 再設硬上限。這些額度由有限 owner 分配或共同准入維持，不能讓三十二台 API 各自擁有完整兩萬次。其配額機制可接續<a href="/networking/2026/09/30/multi-tenant-rate-limiting-quota-boundaries.html">多租戶限流服務</a>；此處額外限制實際併行，以免來源由 5 ms 變成 500 ms 後累積大量工作。</p>

<p>同 key 的 token 合併可減少重複回源，卻擋不住隨機掃描的不同 key。來源逾時先停止背景暖機，有效但過 soft deadline 的值繼續用到原 hard deadline，無值或已過期就快速拒絕。每個 miss 等待者也設數量與 deadline 上限；token holder 中斷時等一秒權利到期，由新 holder 接手。重試只交給直接呼叫來源的一層，以有界次數及 jitter 執行。<a href="https://sre.google/sre-book/addressing-cascading-failures/">Google SRE Addressing Cascading Failures</a>說明了限制佇列、併行與重試放大的原則；前景與暖機分級則可參照 <a href="https://sre.google/sre-book/handling-overload/">Handling Overload</a> 的請求重要性與資源配額。</p>

<p>修復時先確認來源延遲回穩、前景拒絕率下降，再逐步恢復 8,000 次背景預算。以 2,000 萬筆、每秒 8,000 個互異 key 的理想條件，全工作集重建至少需要 2,500 秒，約 41.7 分鐘；不能承諾一分鐘就恢復原命中率。實務先暖熱門子集，避免為填滿所有記憶體而推遲有效流量恢復。</p>

<h2 id="當要求改成管理者讀己之寫沿用版本就能縮小代價">當要求改成管理者讀己之寫，沿用版本就能縮小代價</h2>

<p>若管理頁只要求「自己的更新立即可見」，不必把所有訪客都改為強讀。更新回版本 42，後續 GET 攜帶 <code class="language-plaintext highlighter-rouge">min_version=42</code>；L1 或 shared cache 若版本較低，就跳過該值，在來源預算內查到至少 42。這把一致性需求放在具體使用流程，而非全站停用快取。</p>

<p>假設這類讀取占尖峰的 1%，最多額外需要每秒 3,000 次來源查詢，與一般 3,000 次合計約 6,000，仍低於前景 12,000 預算。若增加到 10%，額外 30,000 次就已超過總容量，必須增加來源、改善版本化副本，或調整功能承諾。min_version 也要限制在可信 API 回傳的版本或受控範圍，避免任意巨大數字造成持續回源。</p>

<p>另一個替代是 write-through，把更新先寫來源再同步寫快取，降低常態失效延遲；但來源成功、快取失敗仍會留下裂縫，成功回應的意義需要重新定義。若選版本不可變 key，例如 <code class="language-plaintext highlighter-rouge">item:42</code>，舊回填覆寫的問題會減少，卻仍需為「目前版本是幾」建立新鮮度規則。資料變成不可變，沒有讓版本指標消失。</p>

<p>在這個讀多寫少、展示允許三十秒落後的案例，cache-aside 加版本失效與有界 stale 比同步雙寫更簡單。若改成權限撤銷、立即下架的安全判定，應讓該判定經過最新權威狀態，或在確認成功前完成受控服務集合的切換；不要沿用展示資料的陳舊政策。</p>

<h2 id="把故障交錯做成可重跑的檢查">把故障交錯做成可重跑的檢查</h2>

<p>隨文提供的 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/ds04_cache_refill_demo.py">狀態模型程式</a>只用 Python 標準函式庫，以可控制的虛擬時間測試回填。本次執行的十項測試全數通過，覆蓋失效後舊值回填、亂序事件、lease 到期、新 token 接手、owner 重啟、路由切換、metadata 淘汰與 hard deadline 繼承，另檢查單次 token 與租戶 key 隔離。這是協定局部的可執行範例，並未啟動實際 Redis／Memcached 或網路叢集。</p>

<p>整合測試還要加入均勻及熱門分布、資料大小偏斜與隨機不存在 key；在讀來源後暫停 reader，插入更新、重啟或搬移，再放行舊回填。逐步把來源延遲拉高，核對總准入與 in-flight 仍受控；中斷版本事件傳遞，確認各層 hard deadline 一致，超過後回 503。讀取抽樣與權威版本比對時，記錄真正來源觀測時間，避免以 cache 最近命中時間冒充資料年齡。</p>

<p>日常指標應同時包含有效讀取成功率與 P99、fresh／stale 命中比例、hard-expired 拒絕、回源 QPS／併行、版本拒絕、失效 lag、top bucket 流量、暖機進度與租戶記憶體占用。高基數 item ID 放抽樣 trace，不放所有 metrics labels；租戶 key 空間、最大 value、並行回填及記憶體皆有配額，避免一家租戶的掃描把其他資料全部擠出。</p>

<p>上線先做影子讀取，抽樣比較版本與期限，再逐租戶提高使用比例。快取回滾與來源入口限流一起切換，避免「暫時繞過快取」瞬間將三十萬次讀取送到來源。schema 升級使用新命名空間但共用來源預算，舊命名空間依期限排空；源端更新仍維持相同商品版本，不因快取格式改版重置。</p>

<p>回到商家更新與訪客讀取，這個方案讓資料庫只承擔權威更新與有界回源，快取承擔大量可重建的讀副本。版本與單次 token 擋住已知失效後的舊回填，固定 bucket 減少擴容搬動，原始截止時間限制跨層與搬移的陳舊程度；任何故障下，來源容量都由入口預算保護。下一個問題才是：若資料本身由 key-value 儲存服務保存，寫入確認要如何跨故障留下來？那將進入 WAL、複寫確認與耐久性。</p>

<h2 id="證據範圍">證據範圍</h2>

<p>商品目錄、API、資料模型、token 格式、遷移流程、SLO 與全部容量數字均為參考設計或假設算例，不是任何公司的內部架構或實測容量。狀態模型通過只支持其列出的交錯與局部規則，無法替代網路隔離、時鐘、程序中斷、資料庫接手及完整負載測試；硬期限的推導依賴來源讀取新鮮度、每端時鐘誤差不超過 100 ms，以及 API 在送出前的期限檢查。</p>

<p>兩份快取資料提高部分故障下的命中機會，並未提供權威資料耐久性或副本線性一致性。短暫分裂路由可造成重複查詢及不同版本，仍須在來源時間期限內；全站版本立即可見、安全撤銷與跨區域多活不在基線承諾內。Memcached 文件僅支持其中的 CAS／stale 機制，完整協定仍是本案例設計。本文沒有執行實際叢集 benchmark。</p>

<h2 id="references">References</h2>

<ol>
  <li><a href="https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf">Rajesh Nishtala 等人，Facebook，Scaling Memcache at Facebook，NSDI 2013</a>，cache-aside、stale set 與 lease。</li>
  <li><a href="https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf">Giuseppe DeCandia 等人，Amazon，Dynamo: Amazon’s Highly Available Key-value Store，SOSP 2007</a>，§4.2 分區與 virtual nodes。</li>
  <li><a href="https://aws.amazon.com/builders-library/caching-challenges-and-strategies/">AWS Builders’ Library，Caching challenges and strategies</a>，容量相依、雙 TTL 與失效時的取捨。</li>
  <li><a href="https://docs.memcached.org/protocols/meta/">Memcached 官方文件，Meta Text Protocol</a>，CAS、anti-stampede 與 stale serving；查核於 2026-10-16。</li>
  <li><a href="https://www.rfc-editor.org/rfc/rfc9111.html">IETF，RFC 9111 HTTP Caching，2022</a>，§4.2.3 age 計算。</li>
  <li><a href="https://sre.google/sre-book/handling-overload/">Google SRE，Handling Overload，2016</a>，資源配額、請求重要性與客戶端節流。</li>
  <li><a href="https://sre.google/sre-book/addressing-cascading-failures/">Google SRE，Addressing Cascading Failures，2016</a>，佇列、in-flight 與重試放大。</li>
</ol>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="distributed-systems" /><summary type="html"><![CDATA[從多租戶商品目錄的讀取與更新需求，推導快取容量、回填 token、版本失效及分區搬移；用明確的陳舊期限與回源預算，處理熱門 key、節點重啟及擴容後的冷資料。]]></summary></entry><entry><title type="html">RoCE 用 PFC 接住在途資料，用 ECN 降低持續進入的流量</title><link href="https://rightson.github.io/networking/2026/10/14/roce-pfc-ecn-feedback-buffer-budget.html" rel="alternate" type="text/html" title="RoCE 用 PFC 接住在途資料，用 ECN 降低持續進入的流量" /><published>2026-10-14T19:13:05+08:00</published><updated>2026-10-14T19:13:05+08:00</updated><id>https://rightson.github.io/networking/2026/10/14/roce-pfc-ecn-feedback-buffer-budget</id><content type="html" xml:base="https://rightson.github.io/networking/2026/10/14/roce-pfc-ecn-feedback-buffer-budget.html"><![CDATA[<p>一個 RoCE fabric 可以同時做到沒有壅塞丟包、鏈路持續忙碌，卻讓不相關的小型請求等很久。PFC 保護的是相鄰設備間、指定優先級的接收空間；ECN 則把壅塞訊號送到端點，讓來源減少後續流量。兩者作用的距離與時間不同，部署時必須分別準備緩衝，並檢查它們如何影響完成時間。</p>

<p>先把工作具體化。四台伺服器各有一個大型 RDMA WRITE，要把結果送進同一台接收者；每條輸入及接收者的出口都以 400 Gb/s 作為理想資料率。這可以代表參數或快取資料的一次匯聚，也能作為 collective 某個匯聚階段的簡化模型。四條輸入同時開始，合計 1.6 Tb/s 爭用 400 Gb/s 出口。即使交換器內部轉送能力足夠，目的地前的出口仍要排隊。</p>

<p>下面先沿藍色資料路徑讀：四個 ingress priority group 的資料，匯入一個 egress queue，再抵達 receiver。橘色 PFC 往相鄰發送者返回；紫色 CNP 則由 receiver 發回原始 sender。這些控制路徑各有一段尚未生效的時間，buffer 就用來承接那段時間產生的資料。</p>

<p><img src="/images/networking/2026-10-14/roce-two-feedback-loops.svg" alt="四個發送者經不同 ingress priority group 匯入同一出口，PFC 返回相鄰設備，ECN 標記抵達接收者後以 CNP 回饋來源" /></p>

<p>圖一：參考設計，省略中間 hop；400 Gb/s、8 μs 與 2 μs 都是後文的假設值。協定分工依據 <a href="https://1.ieee802.org/dcb/802-1qbb/">IEEE 802.1Qbb</a>、<a href="https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-517/Layer-1-and-Switch-Ports/Quality-of-Service/RDMA-over-Converged-Ethernet-RoCE/">NVIDIA RoCE 文件</a>。</p>

<p>這篇接續 <a href="/networking/congestion-control/2026/09/25/csig-bottleneck-signaling.html">CSIG 的路徑壅塞訊號</a> 與 <a href="/networking/rdma/2026/09/27/storm-rdma-nic-scheduling.html">STORM 的 RNIC 排程</a>。訊號回答 sender 如何得知網路狀態，排程決定誰先送；本篇補上的是它們生效前的資料量，以及逐跳暫停造成的共同等待。先理解這一層，才能判斷更快的訊號或更聰明的順序，實際省掉了哪段等待。</p>

<h2 id="接收空間與來源速率由兩條迴路控制">接收空間與來源速率由兩條迴路控制</h2>

<p><a href="https://1.ieee802.org/dcb/802-1qbb/">IEEE 802.1Qbb 的公開說明</a> 將 PFC 定義為全雙工鏈路上的 per-priority flow control。下游發出 pause，要求相鄰上游停止某個優先級的傳送，其他優先級仍可取得服務。它提供的操作是「現在先停」，粒度由鏈路與優先級決定。</p>

<p>ECN 使用 IP header 的 Congestion Experienced 標記表示壅塞，<a href="https://www.rfc-editor.org/rfc/rfc3168#section-5">RFC 3168 §5</a> 說明其 IP 層訊號。RoCEv2 receiver 收到標記後，可產生 CNP，由來源 RNIC 的控制器調整傳送速率。TCP 的 ACK 回饋與 RoCE 的 CNP 是不同 transport 路徑，共用 ECN 欄位並不要求相同的速率演算法。<a href="https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-517/Layer-1-and-Switch-Ports/Quality-of-Service/RDMA-over-Converged-Ethernet-RoCE/#roce-lossy-with-ecn">NVIDIA RoCE 的 lossy 模式說明</a> 可作介面參照。</p>

<p>這裡的時間起點要一致。對 ECN，把 Tcc 定義為「一包在壅塞出口被標記，到降低後的流量真正抵達該出口」；它包含標記包的等待與正向傳送、receiver 產生 CNP、回程、RNIC 反應，以及降速資料再走到瓶頸的時間。拿空載 ping RTT 填入 Tcc，會漏掉其中幾項。</p>

<p>對 PFC，把 Tp 定義為「下游決定發出 XOFF，到上游最後一批仍被允許送出的資料抵達下游」；它包含控制框的序列化、傳播、上游處理與資料回程。這個定義已涵蓋來回影響，因此另加 cable RTT 時要避免重複。兩個時間都應以資料面觀察核對。</p>

<p><a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf#page=4">2015 年 Yibo Zhu 等人的 DCQCN，SIGCOMM</a> 把交換器標記、receiver 通知與 sender 降速串成端到端控制。原始實作對每條 flow 抑制過密的 CNP，使用 50 μs 的通知間隔；第一個符合條件的標記包可立即觸發，後續通知才受間隔限制。這是當年實作參數，後文的 8 μs 只是理想化算例。</p>

<p>PFC 的逐跳阻擋與 DCQCN 的來源降速可以互補：前者處理來不及停住的資料，後者降低持續輸入的壓力。當暫停一路向上游擴散，ECN 回饋與 host pacing 能否及時降低輸入，便會影響有多少鏈路、多少工作被牽連。</p>

<h2 id="400-gbs-下的一微秒足以增加五萬-bytes">400 Gb/s 下的一微秒，足以增加五萬 bytes</h2>

<p>先只看一個出口，以十進位 bytes 計算，忽略 Ethernet、IP、UDP 與 RDMA header。400 Gb/s ÷ 8 = 50 GB/s，也就是每微秒 50,000 bytes。四條輸入合計每微秒 200,000 bytes，出口每微秒移走 50,000 bytes，淨增加 150,000 bytes。</p>

<p>令 A(t) 為進入這個 queue 的總速率，C(t) 為實際服務速率。只要 queue 非空，簡化流體關係是：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dq/dt = A(t) − C(t)
q(t) ≥ 0
</code></pre></div></div>

<p>當 queue 已空、服務能力大於輸入，q 維持零；多出的出口能力成為 idle capacity。這個守恆式可以先排除不合理設定：緩衝大小、控制速度及工作同步程度，要容納同一筆淨累積資料量。</p>

<p>若標記時刻 t0 的 queue 為 Kecn，控制生效前還會增加：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ΔQcc = ∫[t0, t0+Tcc] max(A(t) − C(t), 0) dt
</code></pre></div></div>

<p>這裡取正部是保守估計，沒有用中間的排空時段抵銷突發。若 A 與 C 固定且 A&gt;C，才簡化成 (A−C)Tcc。要避免抵達某個同一計帳域的壓力線 Qg，至少須滿足 Kecn+ΔQcc&lt;Qg。這只是首次反應前的必要餘裕；反應後若仍超額，queue 還會繼續增加。</p>

<p>對四對一、Tcc=8 μs 的假設，ΔQcc=1,200,000 bytes，也就是 1.2 MB。若 Kecn=256,000 bytes，第一次降速資料抵達之前，queue 可達 1.456 MB。ECN 已經標記並不會讓這些資料消失；它們已被來源送入網路。</p>

<p>較低的 Kecn 能早一點開始通知，但最激進的 Kecn=0，在這個模型仍留下 1.2 MB 的淨累積。若可用空間遠低於這個量級，就需要減少初始發送、縮短實際 Tcc、分散匯聚或啟動逐跳暫停。單改標記門檻有可推導的極限。</p>

<h2 id="一次完整突發把標記暫停與首次降速排在時間線上">一次完整突發，把標記、暫停與首次降速排在時間線上</h2>

<p>現在給簡化模型一組完整參數。四條 flow 在 t=0 同時以每條 50 GB/s 進入空 queue；出口維持 50 GB/s。到首次反應前，各 flow 都保持原速率。</p>

<table>
  <thead>
    <tr>
      <th>參數</th>
      <th style="text-align: right">假設值</th>
      <th>用途</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>每條 flow 的資料率</td>
      <td style="text-align: right">50 GB/s</td>
      <td>四條共 200 GB/s</td>
    </tr>
    <tr>
      <td>出口服務率</td>
      <td style="text-align: right">50 GB/s</td>
      <td>接收者前的瓶頸</td>
    </tr>
    <tr>
      <td>Kecn</td>
      <td style="text-align: right">256 kB</td>
      <td>首次標記的確定性門檻</td>
    </tr>
    <tr>
      <td>Qg</td>
      <td style="text-align: right">768 kB</td>
      <td>抽象的暫停觸發壓力線</td>
    </tr>
    <tr>
      <td>Tcc</td>
      <td style="text-align: right">8 μs</td>
      <td>標記到首次有效降速資料抵達</td>
    </tr>
    <tr>
      <td>Tp</td>
      <td style="text-align: right">2 μs</td>
      <td>暫停決定到最後舊資料抵達</td>
    </tr>
    <tr>
      <td>最大框與額外安全量</td>
      <td style="text-align: right">每入口 9 kB</td>
      <td>供獨立 headroom 試算</td>
    </tr>
  </tbody>
</table>

<p>所有 KB／MB 的算例數字皆採十進位 kB／MB。Qg 是單一計帳域的教學假設；下一節會把真正 ingress PG 與 egress queue 分開，它不是一套可直接填入交換器的設定。</p>

<p>queue 以每微秒 150 kB 增加，因此在 256/150=1.707 μs 跨過 Kecn。只靠這一次理想化 ECN 反應，降低後的流量要到 9.707 μs 才抵達。Qg 卻在 768/150=5.120 μs 已被跨過：即使標記先發生，仍要暫停。</p>

<p>若抽象控制器在 5.120 μs 對四條來源同時發出 pause，且每條都在 2 μs 後完全停住，峰值出現在 7.120 μs，為 1.068 MB；之後出口持續排空。這個首次暫停把峰值壓低，但付出所有四條 flow 一起停止的代價。此處只追到首次停住與排空，沒有模擬後續 XON、再突發或 DCQCN 的逐次收斂。</p>

<p><img src="/images/networking/2026-10-14/roce-first-response-queue.svg" alt="相同四對一流體負載下，只靠首次 ECN 反應會在9.707微秒達1.456MB；抽象暫停則在7.120微秒達1.068MB後排空" /></p>

<p>圖二：假設算例，以 <a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/roce_feedback_budget.py">可重跑腳本</a> 產生的分段線性函數繪製。紫線在首次 ECN 生效後假設總速率立即等於出口能力，是有利於 ECN 的理想化控制；橘線在首次 pause 生效後停止所有輸入。兩條曲線均非實體 RNIC benchmark。</p>

<p>公平性也要另外檢查。四條等速 flow 的理想持續分配是每條 12.5 GB/s，即 100 Gb/s；然而「總輸入剛好等於出口」只約束總量。四條速率為 35、5、5、5 GB/s，也同樣不會新增 queue，卻有不同完成時間。用 Jain index，前者為 1，後者為 0.481。queue 穩定、鏈路利用率高與 per-flow 公平，是三項分開的要求。</p>

<p>再假設每條只需要送 16 MB，接收者總共要接 64 MB；在理想 50 GB/s 出口上，完成全批資料至少需 1.28 ms。這個容量下界保留了大家最終都得通過同一出口的事實。減少 pause 可以改善期間的 idle gap 與尾端等待，無法把出口的容量下界一併消掉。</p>

<h2 id="ecn-與-pfc-門檻往往量的是不同集合">ECN 與 PFC 門檻，往往量的是不同集合</h2>

<p>真正的交換器會讓同一份 packet 同時被不同視角計帳。對以 ingress priority group 觸發 PFC、以 egress queue 做 ECN 的實作，可以定義 xij 為「從入口 i 收到、仍等著出口 j 服務」的 bytes：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>入口 PG i 的占用  Ii = Σj xij
出口 queue j 的占用  Qj = Σi xij
</code></pre></div></div>

<p>一個入口可把資料送往多個出口；一個出口也可接收多個入口。因此 Ii 與 Qj 是矩陣的列總和、欄總和。它們可能來自同一份共享記憶體，並不意味著額外儲存兩份 packet。原始 <a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf#page=6">DCQCN §4</a> 已明確分開這兩種計帳；現代 ASIC 的 pool、PG 與 queue mapping 還須逐平台核對。</p>

<p>這使「ECN 門檻數字小於 PFC 門檻」失去單獨保證。構造一個反例：某入口向四個出口各積累 48 kB；每個出口目前都只有這個入口的資料。若各出口 Kecn=80 kB、入口 XOFF=128 kB，數字上 80&lt;128，但入口已占 192 kB，四個出口卻都還低於 80 kB。PFC 可以先發生。</p>

<p><img src="/images/networking/2026-10-14/roce-ingress-egress-accounting.svg" alt="同一入口對四個出口各有48kB，入口列總和192kB超過128kB，而每個出口欄總和仍低於80kB的ECN門檻" /></p>

<p>圖三：假設算例，展示同一份資料的兩種計帳視角。每個出口只有單一入口貢獻；源自 <a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf#page=6">DCQCN 的 ingress／egress 區分</a>，非任一商用 ASIC 的 buffer 佈局圖。</p>

<p>反過來，多個入口各自只積一小部分，合計卻能讓單一出口先標記。部署時要核對的是可達的流量分布、入口與出口服務關係，以及共享 pool 隨其他 port 忙碌而改變的可用額度。把兩個 CLI 數字排大小，漏掉了這張計帳矩陣。</p>

<p>動態共享可以讓空閒 port 的空間支援忙碌 port，但分配會隨並行負載改變。一個 flow 在獨占 fabric 時通過測試，加入第二個 job 後可能更早暫停。要把這種變動放進模型，Qg 應改成與 pool 可用量及活動 PG 數相關的壓力線；單一常數只能代表已固定的情境。</p>

<h2 id="pfc-headroom-必須接住已經出發的資料">PFC headroom 必須接住已經出發的資料</h2>

<p>到達 XOFF 時還有資料在路上。對某入口 i，一個保守的原始 bytes 預算可以寫成：</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Hi ≥ Ci × Tpi + Mi
</code></pre></div></div>

<p>Ci 是入口可能抵達的速率；Tpi 必須涵蓋最後舊資料抵達；Mi 是未被時間模型涵蓋的最大框、門檻 overshoot 與安全量。若實際量測的 Tpi 已包含整框尾端，就應從 Mi 移除重複部分。這裡刻意假設該入口的 buffered bytes 在這段時間完全無法排出，得到保守需求。</p>

<p>400 Gb/s 的入口、2 μs 延遲與9 kB額外量，得到每入口 109 kB。四個入口同時需要 headroom，保守合計為436 kB。前一節的 queue 在 pause 決定後只增加300 kB，因為出口在2 μs內仍移走100 kB；headroom 的436 kB則保守地計入400 kB總到達與36 kB額外量。兩者回答不同問題，應保持同一組假設再比較。</p>

<p>共享 headroom 的配置可以小於所有 port 的最壞需求總和，代價是承擔同時暫停的重疊風險。假設四個入口各有32 kB專用空間，剩餘從200 kB共享池借用，每個仍需77 kB；四者共同要求308 kB，超過共享池108 kB。平均負載很低也無法消除這個同步峰值。</p>

<p><a href="https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-517/Layer-1-and-Switch-Ports/Quality-of-Service/#lossless-shared-headroom-pool">NVIDIA Cumulus 5.17 的 QoS 文件</a> 分開 required、exclusive 與 shared headroom；其 PFC 計算也包含介面延遲與線長。實際硬體以 cell 配置，packet 大小還會改變內部占用。上述 bytes 算式適合先查量級，正式 sizing 要加入 cell rounding、metadata、各 port 的實際延遲與可保證的共享額度。</p>

<p>把鏈路換成800 Gb/s而維持2 μs及9 kB額外量，原始需求變成每入口209 kB。速率升高使同一段控制延遲承載更多在途資料；若靠改善反應路徑把延遲縮到1 μs，才可在這個模型回到109 kB。這指出改善控制延遲與增加SRAM是在支付同一筆資料量，但成本位置不同。</p>

<h2 id="同優先級的其他目的地也可能一起停住">同優先級的其他目的地，也可能一起停住</h2>

<p>考慮一條上游鏈路同時送 A→D 的大型傳輸與 A→E 的64 kB小型請求；D 的出口壅塞，E 的出口空閒，兩筆流量卻被映到同一個 PFC priority。下游要求上游暫停這個priority時，上游停的是整個類別，送往E的資料也要等。</p>

<p>這不是只有單一 FIFO 的隊頭擋住後方packet。即使來源已按目的地分開排程，只要 pause 的作用域仍是鏈路上的同一priority，當下都可能失去傳送資格。若上游的同priority buffer接著累積，它再向自己的鄰居發出新PFC，等待範圍便往外擴張。每一跳產生自己的控制框，原來的PFC框在鄰接鏈路終止。<a href="https://community.networking.hpe.com/blogs/parthipan-ts/2025/11/17/lossless-ethernet-with-pfc-for-aiml-workloads">Juniper 2025 年工程說明</a> 描述了這種逐跳壓力傳遞。</p>

<p>64 kB在400 Gb/s理想出口的序列化時間只有1.28 μs。若同優先級pause讓它等20 μs，其額外等待已遠大於自身傳送時間。換算成「等待加單鏈路序列化」是21.28 μs；這仍只是一段路徑的假設算例，完整FCT還要加入其他hop與端點處理。</p>

<p>增加priority能把部分工作分開，卻會增加buffer預留、mapping與排程配置。多租戶環境也要決定誰可以把流量放進受保護類別，以及CNP本身是否能及時送出。對照 <a href="/networking/rdma/2026/09/27/storm-rdma-nic-scheduling.html">STORM</a>，更好的請求順序有助縮短等待，但整個類別被pause時，順序再精細也要先等鏈路重新提供服務。</p>

<h2 id="長期吞吐要連到每條-flow-的完成時間">長期吞吐要連到每條 flow 的完成時間</h2>

<p>2015年的<a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf#page=3">DCQCN原始測試，Figure 2與§6</a>，使用40 Gb/s、三層Clos與ConnectX-3 Pro；以背景工作混合incast，比較啟用與未啟用端到端控制，觀察吞吐及公平性。它提供的是指定hardware與traffic下的控制效果，研究理由則延續到高速fabric：來源減速可以減少持續pause及旁觀flow被拖住的情況。</p>

<p>本篇的流體算例只證明首次反應的資料預算。若要評估今日部署，合理的三組對照是：同一可靠transport只用PFC；同一transport加入已校準ECN／速率控制；再加入sender pacing或錯開啟動。前三者保持NIC、路由、port rate、MTU、buffer pool與接收者相同，才可把差異追到控制。</p>

<p>負載要同時含長期飽和與有限突發。四條持續flow測每條throughput與Jain index；四條固定bytes的匯聚測整批makespan及個別FCT；另外穿插一條送往空閒目的地的短flow，觀察P99與pause duration。同步與隨機錯開的開始時間應分開做，因為平均offered load相同，queue峰值可以很不同。</p>

<p>還要同步記錄CE標記、CNP、入口PG占用、出口queue占用、pool餘裕與NIC速率。低pause但高drop可能是headroom不足；高CE但持續高queue可能是回饋慢或減速不足；低CE卻大量PFC可能是mapping或不同計帳域先撞門檻。這些是假說判別方式，須以同一次傳輸的時間線核對。</p>

<p>當訓練或服務有同步點，應把communication FCT接回iteration或request latency。短flow變快可能只是背景flow被延後；一條receiver鏈路一直100%忙碌，也可能代表工作在網路持續排隊。改善的目標是相同工作量與隔離條件下更早交付，而非單獨最大化某個counter。</p>

<h2 id="持續暫停需要切斷等待並處理遺失資料">持續暫停需要切斷等待，並處理遺失資料</h2>

<p>短期壅塞通常會隨出口排空而解開。死鎖則出現一個相依環：buffer A裡的packet等B釋放空間，B等C，C又等A。若大家持續保留資料、又持續暫停對方，停止新流量仍可能留下互相等候的packet。</p>

<p><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/rdma_sigcomm2016.pdf#page=5">Chuanxiong Guo（Microsoft）等人的SIGCOMM 2016實務論文，§4.2</a> 報告Clos部署中，未知目的MAC的flooding打破預期up/down路由，形成PFC循環等待。這個前例說明，預設路由圖之外的例外轉送也須納入相依分析；只檢查正常unicast路徑會漏掉故障時的實際路徑。</p>

<p>另一類問題是receiver的接收管線停住，反覆發pause。它未必形成路由循環，仍可能把上游都拖住。偵測時要區分持續XOFF、幾乎沒有queue服務、buffer滯留與相鄰設備故障；僅憑pause框數量，難以辨認短而頻繁的正常突發與長時間不前進。</p>

<p><img src="/images/networking/2026-10-14/roce-wait-cycle-watchdog.svg" alt="三個buffer形成循環等待；持續XOFF且沒有服務時，watchdog暫時忽略暫停並依設定drop或forward，資料遺失再交由transport或job處理" /></p>

<p>圖四：參考設計。相依環是示意；watchdog的偵測、drop／forward與回復配置概念依據 <a href="https://github.com/sonic-net/SONiC/wiki/PFC-Watchdog-Design">SONiC PFC Watchdog Design</a>。圖中條件須依ASIC實際counter與平台行為實作。</p>

<p><a href="https://github.com/sonic-net/SONiC/wiki/PFC-Watchdog-Design#121-pfc-storm-detection">SONiC的watchdog設計文件，§1.2</a> 提供兩種處置：drop丟棄受影響queue的資料，或forward暫時忽略pause繼續服務；持續暫停消失後再回復PFC。其文件與<a href="https://github.com/sonic-net/sonic-utilities/blob/cc4fbb3e831358e5b3844490753d239797cf1611/pfcwd/main.py">目前CLI原始碼</a> 的時間尺度是毫秒，CLI預設detection time為200。這是故障隔離尺度，與前面的微秒級突發緩衝分開使用。</p>

<p>打斷等待可能帶來packet loss。參考設計中，網路先限制影響範圍、保留port／priority及drop紀錄，端點接著檢查operation完成狀態、重傳是否前進，以及QP是否回報失敗。若operation已失敗，應交給上層依工作語意中止或重建；部分資料可能已寫入接收buffer，僅憑鏈路重新傳得動就交付結果，會漏掉未完成工作。</p>

<p>重新放行也要觀察同一故障是否再度出現。receiver仍失效時立刻重啟原工作，會再次注入壓力。對不可接受半完成結果的collective，一個可操作策略是停住相關operation、保留失敗紀錄，確認端點正常後從安全輸入重做該階段；這是上層參考處置，具體成本由collective與應用的錯誤語意決定。</p>

<h2 id="選擇性重傳提供另一種付成本的位置">選擇性重傳提供另一種付成本的位置</h2>

<p>PFC降低壅塞丟包，但讓不同flow共享暫停範圍。<a href="https://arxiv.org/html/1806.08159v1#S3">Radhika Mittal（UC Berkeley）等人的IRN，SIGCOMM 2018</a> 改良接收失序與選擇性重傳，再用BDP-FC限制單flow的在途packet。它把較多責任移到NIC，減少大量重送已成功抵達資料的浪費。</p>

<p>其預設網路評估是54台server、40 Gb/s的三層fat-tree模擬；NIC邏輯另有硬體資源與RTL驗證。對照包含RoCE加PFC，以及IRN加或不加PFC，並分開測不同壅塞控制器。<a href="https://arxiv.org/html/1806.08159v1#S4">原文§4與§6</a> 提供條件。這種結果支持loss-tolerant transport的研究方向，仍需在目標NIC、速率及工作上重新比較。</p>

<table>
  <thead>
    <tr>
      <th>方案</th>
      <th>流量超出容量時怎麼付成本</th>
      <th>主要新增負擔</th>
      <th>適合先驗證的情境</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>PFC為主</td>
      <td>暫停相鄰設備的同priority資料</td>
      <td>headroom與共同等待</td>
      <td>既有loss-sensitive NIC、突發有限</td>
    </tr>
    <tr>
      <td>PFC加ECN／來源pacing</td>
      <td>逐跳承接首次突發，來源減少持續輸入</td>
      <td>回饋延遲與速率參數校準</td>
      <td>持續壅塞混合短工作、既有fabric</td>
    </tr>
    <tr>
      <td>選擇性重傳加在途上限</td>
      <td>接受遺失，端點補傳缺少的資料</td>
      <td>NIC狀態、完成語意與重傳成本</td>
      <td>可完整驗證loss及reordering的transport</td>
    </tr>
  </tbody>
</table>

<p>這是工程比較，前三欄並未替任何NIC宣告功能。NVIDIA Cumulus文件同時提供lossless及lossy RoCE配置，顯示switch可以採不同模式；端點是否能承擔損失，仍須以實際NIC功能及失敗注入測試確認。單把PFC關掉，保留其餘設計不動，無法取得IRN整套修改的效果。</p>

<p>接收端授予credit或工作排程錯開傳輸，也是可比較的選項。credit可以在資料進入fabric之前限制receiver負載，但引入請求、授權與credit不足時的等待；錯開啟動可降低同步峰值，卻把等待放到sender或runtime。用同一批64 MB及相同出口容量比較，才能看出等待移到哪裡、總完成時間是否下降。</p>

<h2 id="高速鏈路要求量測控制延遲的尾端">高速鏈路要求量測控制延遲的尾端</h2>

<p>未來一年，若某個fabric把400 Gb/s升到800 Gb/s，且實際Tp與同時暫停數保持不變，這個模型預期原始在途bytes項加倍；若增加的headroom遠小於推導值，必須由更短的實測反應時間、較低輸入或可保證的排空解釋。這是一項條件式工程預判，可以用pause注入與逐port最大占用直接檢查。</p>

<p>ECN也有相同量級壓力。應量的是「標記到新速率抵達瓶頸」的分布，包含CNP排程與receiver處理；尾端Tcc拉長時，更多bytes會在回饋生效前到達。較豐富的路徑訊號可以減少控制器猜測，較早的接收credit可以限制起始burst，但緩衝與端點控制仍須對同一條資料時間線負責。</p>

<p>RoCE調校最後可以收斂到三個可檢查的量：首次回饋前的淨累積、XOFF後的在途資料，以及暫停牽連的其他工作量。前兩項決定緩衝是否自洽，第三項決定零丟包換來多少服務延遲。把這三項接到具體工作與完成時間，就能選擇增加buffer、縮短控制路徑、改善端點重傳或調整傳輸時機各自應付的成本。</p>

<h2 id="證據範圍">證據範圍</h2>

<ul>
  <li>四對一400 Gb/s、8 μs／2 μs、256 kB／768 kB與9 kB安全量均為假設算例，未量測商用交換器或RNIC。腳本只計算守恆式、首次反應、headroom、Jain index及容量下界，沒有實作DCQCN、packet simulator或穩態PFC迴圈。</li>
  <li>模型忽略wire overhead、cell占用與離散packet；假設ECN首次反應後四條flow立即取得公平速率。Qg是抽象暫停壓力線，不是實際ingress XOFF。XON、接收credit、後續rate increase與多瓶頸均須額外建模。</li>
  <li>DCQCN採SIGCOMM 2015原文；IRN採2018年6月21日的arXiv extended version及其SIGCOMM工作。歷史40 Gb/s結果不外推為400／800 Gb/s增益。Microsoft 2016案例只支持其報告的故障機制，不推定今日所有NIC仍有相同問題。</li>
  <li>Cumulus配置說明以5.17版為定點參照；頁面已有5.18版連結，本篇未宣稱5.17為最新版。不同ASIC的pool、cell及門檻生效值要分開查；公開指令沒有在真實設備執行。</li>
  <li>SONiC設計頁為歷史規格；CLI原始碼固定於cc4fbb3e831358e5b3844490753d239797cf1611。不同ASIC對偵測、drop／forward及PFC恢復的支援可能不同，本文未宣稱整條故障處置已完成production驗證。</li>
  <li>本篇僅使用公開協定、研究與工程文件。端點operation失敗與重做階段的處理屬參考設計，應依實際completion及應用語意決定。</li>
</ul>

<h2 id="參考資料">參考資料</h2>

<ol>
  <li><a href="https://1.ieee802.org/dcb/802-1qbb/">IEEE 802.1Qbb — Priority-based Flow Control</a> — 2011年6月16日核准的標準項目說明。</li>
  <li><a href="https://www.rfc-editor.org/rfc/rfc3168">RFC 3168 — The Addition of Explicit Congestion Notification to IP</a> — 2001年9月。</li>
  <li><a href="https://conferences.sigcomm.org/sigcomm/2015/pdf/papers/p523.pdf">Yibo Zhu et al. — Congestion Control for Large-Scale RDMA Deployments</a> — SIGCOMM 2015，§3–6。</li>
  <li><a href="https://www.microsoft.com/en-us/research/wp-content/uploads/2016/11/rdma_sigcomm2016.pdf">Chuanxiong Guo et al. — RDMA over Commodity Ethernet at Scale</a> — Microsoft，SIGCOMM 2016，§4。</li>
  <li><a href="https://arxiv.org/html/1806.08159v1">Radhika Mittal et al. — Revisiting Network Support for RDMA</a> — arXiv v1，2018年6月21日；SIGCOMM 2018工作延伸版。</li>
  <li><a href="https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-517/Layer-1-and-Switch-Ports/Quality-of-Service/">NVIDIA Cumulus Linux 5.17 — Quality of Service</a> — PFC、ECN與shared headroom。</li>
  <li><a href="https://docs.nvidia.com/networking-ethernet-software/cumulus-linux-517/Layer-1-and-Switch-Ports/Quality-of-Service/RDMA-over-Converged-Ethernet-RoCE/">NVIDIA Cumulus Linux 5.17 — RoCE</a> — lossless／lossy與CNP。</li>
  <li><a href="https://community.networking.hpe.com/blogs/parthipan-ts/2025/11/17/lossless-ethernet-with-pfc-for-aiml-workloads">Juniper — Lossless Ethernet Fabrics with PFC for AI/ML Workloads</a> — 2025年11月17日工程說明。</li>
  <li><a href="https://github.com/sonic-net/SONiC/wiki/PFC-Watchdog-Design">SONiC — PFC Watchdog Design</a> — 偵測、處置與回復設計。</li>
  <li><a href="https://github.com/sonic-net/sonic-utilities/blob/cc4fbb3e831358e5b3844490753d239797cf1611/pfcwd/main.py">SONiC CLI — pfcwd/main.py</a> — 固定版本原始碼。</li>
  <li><a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/roce_feedback_budget.py">RoCE feedback budget 試算</a> — 本篇假設模型；<a href="https://github.com/rightson/rightson.github.io/blob/main/scripts/experiments/roce_feedback_budget.results.json">執行結果</a>。</li>
</ol>]]></content><author><name>Scott Yo-Ru Chen</name></author><category term="networking" /><summary type="html"><![CDATA[從四對一的 400 Gb/s incast 推導兩種控制延遲、headroom 與 buffer 計帳，解釋 ECN 標記後仍會暫停的原因，以及 PFC 如何波及其他流量。以可重跑算例、DCQCN 與 IRN 原始研究，連到公平性、死鎖與故障處置。]]></summary></entry></feed>