JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

把一切連起來:晶片網路與資料流

在第 4、5 階,你學會了如何打造快速的核心與精巧的加速器分塊。但一顆塞滿了厲害區塊、彼此卻無法溝通的晶片,不過是一塊昂貴的紙鎮。這一階談的是**區塊之間的線路**——為什麼樸實的匯流排會在自身重量下崩潰、工程師如何把網際網路的概念縮小到矽晶上,以及為什麼最激進的 AI 晶片乾脆丟掉程式計數器,讓**資料本身**決定下一步該執行什麼。

當匯流排無路可走

想像一個只有一條主街的小鎮。兩間商店、一所學校、一座鎮公所——一條路把它們全連起來,大家共用。這就是匯流排:一組單一的線路,晶片上每個區塊都接上去。數十年來它都運作得很好。當只有兩三個主控者在搶路時,仲裁器一次放行一個,日子過得很愜意。但現在把視野拉遠,看看現代的多核心處理器:64 個核心、一堆AI 加速器、記憶體控制器與 I/O——全擠在同一條街上。路塞死了,更糟的是,這條街還一直在變長

匯流排有三種病,而且全都隨規模惡化。第一是仲裁:一次只能跑一筆交易,所以頻寬是被瓜分而非倍增——多加核心,每個分到的就更薄。第二是電容:每個區塊都掛在同一條線上,所以每多接一個分支,這條線在電氣上就更重,拉低了最高時脈。第三是長度:一條必須實體連到 600 mm² 晶粒每個角落的線非常長,而在先進製程上,長線又慢、又耗電、又難以收斂時序。這正是晶片尺度版的互連縮放問題:電晶體每一代都更快,線卻沒有——相對而言反而更糟了。

把網際網路縮到矽晶上

網際網路在城市尺度解決了一模一樣的問題:數百萬台電腦如何在沒有一條巨大共用纜線的情況下溝通?答案是封包交換——把訊息切成帶有位址的封包,讓一張由小型路由器組成的織網一跳一跳地傳遞。大約在 2000 年,研究者問了一個顯而易見的問題:為什麼不在晶片上這麼做?成果就是晶片網路(NoC)。每個區塊——核心、快取切片、加速器——都連到一個小小的路由器,而路由器只與相鄰者相連。要傳資料,你把它包成封包,交給你本地的路由器,網路就一次一小跳地把它運過去。

注意這帶來的好處。線路現在又短又在地——是路由器到路由器,而非角落到角落——所以在先進製程上仍能保持快速。頻寬會累加:許多封包在同一瞬間走在不同的鏈路上,所以容量隨鏈路數量擴展,而非被主控者瓜分。整件事還是模組化的:要把晶片做大,只要再放入更多分塊,網路就跟著一起長大。匯流排的三種病——仲裁、電容、長度——靠一招就治好了:拒絕共用一條線,改為共用一張織網

A 3x3 mesh NoC.  R = router, C = compute/cache/accel tile.
Each R links only to its N/S/E/W neighbors -> all wires are SHORT.

   C---C---C
   |   |   |
   R---R---R     A packet from the top-left tile to the
   |   |   |     bottom-right tile takes 4 hops, e.g.
   R---R---R       (0,0) -> E -> (1,0) -> E -> (2,0)
   |   |   |              -> S -> (2,1) -> S -> (2,2)
   R---R---R     'X-then-Y' (dimension-order) routing:
   |   |   |     go east until aligned, then go south.
   C---C---C     Simple, and provably deadlock-free.
二維網格,是 NoC 最主力的拓樸。只連相鄰的短鏈路加上維度序繞線,讓它既簡單又可擴展。

拓樸、繞線,以及你必須避開的死結

拓樸是網路的平面配置圖——路由器如何相連。二維網格是最受歡迎的:它能乾淨地對映到矩形晶粒上、每條鏈路都是一樣的短長度、布局也容易。它的弱點在角落——一個封包要斜跨 8×8 網格,最多需要 14 跳。環面(torus)靠把邊緣繞回來修正這點,像小精靈(Pac-Man)的畫面那樣,把最壞情況的距離砍半——但那些繞回的鏈路實體上很長,部分抵銷了好處。其他形狀(環、胖樹、交叉開關)在面積、延遲與頻寬上各有不同取捨;正確的選擇取決於流量樣態。

繞線是每個路由器用來挑下一跳的規則。最簡單的維度序(X-Y)繞線規定:先往東/西走直到行對齊,再往南/北走。它是確定性的,而且——關鍵在於——可被證明不會發生死結,那是 NoC 工程師反覆出現的惡夢。死結發生在:封包 A 佔著一個緩衝區、等著 B 的緩衝區,而 B 佔著一個緩衝區、等著 A 的——一個誰都動不了的循環僵局,永遠卡死。適應性繞線可以靠繞道閃避壅塞,但必須小心限制(或給予額外的虛擬通道),才不會製造出這種循環。

  1. 注入:來源分塊組好封包、切成 flit,並把頭 flit 交給它本地的路由器。
  2. 繞線:每個路由器從目的地位址算出輸出埠(例如先 X、後 Y)並請求該埠。
  3. 配置:路由器的仲裁器把輸出埠與一個緩衝槽(虛擬通道)授予競爭中的其中一個 flit。
  4. 穿越:flit 越過路由器內部的交叉開關與通往下一個路由器的鏈路;若下一個緩衝區已滿,反向壓力(back-pressure)會讓它暫停。
  5. 彈出:在目的地路由器,尾 flit 排出,封包在接收分塊處重組。

離開晶粒、走上封裝:小晶片與 UCIe

現代的劇情轉折在這裡。當單一晶粒長到超過約 600 mm² 時,會撞上光罩極限——一次微影曝光所能印出的最大面積——而良率也急墜,因為一個致命缺陷就能毀掉整片巨大晶粒。業界的答案:別再造一顆巨大晶片。把它切成數顆較小的小晶片,每顆都用最適合它的製程節點製造,再在封裝上把它們重新縫合起來。一顆大型 CPU 的運算晶粒、I/O 晶粒與記憶體堆疊,可以各自是獨立、單獨測試過的小晶片。這就是異質整合,它已悄悄成為高階矽晶的預設做法。

但現在網路得離開晶粒了。原本在一顆晶片內連接分塊的 NoC,必須延伸到整個封裝,去連接不同小晶片上的分塊。多年來每家廠商都有私有的晶粒對晶粒協定,所以你只能混搭同一家公司的小晶片。UCIe(通用小晶片互連 Express)正是修正這點的開放標準——一套共通的實體層與協定層,讓 A 廠的小晶片能插進 B 廠的封裝,就像封裝內部的 USB。它的夢想是打造一個真正可互通的小晶片市集,而封裝內互連就是那把偉大的均衡尺。

當決定執行什麼的是資料,而非計數器

目前為止的一切,都假設了一台控制流機器——你見過的每顆 CPU 都是這個模型。有一個單一的程式計數器,依序走過指令:抓取指令 1、執行、抓取指令 2、執行。即使加上多核心與亂序的把戲,腦中的模型仍是*一串依計數器規定的順序執行的命令*。資料只是被指令伸手抓來的東西。計數器才是老大。

資料流架構把這一切翻轉過來。這裡沒有程式計數器。取而代之,程式是一張圖:節點是運算,邊則顯示哪個結果餵給下一個運算。一個運算會在它所有的輸入運算元一抵達的瞬間就觸發(fire)——而非在計數器走到它時。如果兩個運算的輸入都備齊了,它們就同時觸發,不需要排程器叫它們動。平行不是你外加上去的東西;它是自然狀態,只要資料相依允許,就會自動顯露出來。

Compute  d = (a + b) * (a - c)

CONTROL FLOW (a CPU):           DATAFLOW (fire on operands):
  t1 = a + b   ; step 1            (a)__   __(b)      (a)__   __(c)
  t2 = a - c   ; step 2               \ /                 \ /
  d  = t1 * t2 ; step 3              [ + ]               [ - ]
  PC walks 1 -> 2 -> 3                  \____   t1   ____/
  (3 sequential steps,                      \        /
   even though + and -                       [  *  ]   <- fires only
   are independent!)                            |         when BOTH
                                               (d)        t1 AND t2
                                                          have arrived
  '+' and '-' have no data dependence, so dataflow runs them
  AT THE SAME TIME with no scheduler. The '*' waits for both.
同樣的算術,兩種世界觀。控制流強加了順序;資料流則讓彼此獨立的運算在運算元一落地的瞬間就平行觸發。

為什麼這對 AI 重要?一個神經網路本身就是一張資料流圖——一張固定的乘加(multiply-accumulate)網格,每個結果都是下一層的輸入,帶著龐大、規律的平行度,又幾乎沒有資料相依的分支。對控制流 CPU(擅長多分支、不規則的程式碼)來說這是最壞情況,對資料流硬體而言卻是最佳情況。現代的AI 加速器狠狠地擁抱這點:一片處理單元的網格,每個單元不去抓取指令,而是等運算元從鄰居流進來、計算、再把結果往前傳。你在第 5 階見過的脈動陣列(systolic array),本質上就是一台寫死的資料流引擎,而NoC正是把運算元送進送出這些分塊的東西。

從區塊到一整顆晶片——以及打造它的工具

退一步,看清這趟旅程的形狀。第 1–3 階教你單一區塊如何運算。第 4–5 階把這些區塊倍增為核心與加速器分塊。這一階給了你結締組織:用NoC在晶粒上的分塊間搬資料、用 UCIe 鏈路在封裝上的小晶片間搬資料,以及那個在最特化的引擎上決定什麼該在何時移動的資料流模型。一顆晶片不再是單一設計;它是一種組合——一個由分塊以及綁住它們的網路所組裝起來的系統。

而這是通往第 7 階的懸念。一張 64 分塊的網格有數千個路由器、數十萬條線,時序還必須跨越一片巨大的晶粒、甚至跨越小晶片邊界收斂。沒有人能徒手畫出這個。擺放分塊、繞接網路、平衡時脈、檢查每一條時序路徑,並簽核它真的能全速運作——這一切都由 EDA(電子設計自動化)完成:那條驚人的軟體流水線,把你剛學到的這類架構,變成可製造的光罩組。下一站,我們就走進那條流水線。