国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁(yè) > 網(wǎng)易號(hào) > 正文 申請(qǐng)入駐

Life of a Token:像調(diào)試代碼一樣看懂大模型如何生成 Token

0
分享至


作者 | 孫照杰

Life of a Token: LLM's Next-Token Pipeline

Chrome 團(tuán)隊(duì)有一篇著名的Life of a Pixel,從一個(gè)

出發(fā)到屏幕像素,追蹤它在瀏覽器渲染管線中的旅程:DOM → Style → Layout → Paint → Raster → Composite,用每個(gè)階段串起引擎全貌。

我們做同樣的事,但追蹤的不是像素,是token。

Token 是 LLM 的最小處理單元:模型不看字符,不看單詞,只看 token。"The"是一個(gè) token," capital"是一個(gè) token,"unbelievable"會(huì)被切成"un"+"believ"+"able"三個(gè) token。Token 之于 LLM 管線,就像像素之于渲染管線。

我們追蹤的 Hello World 是:"The capital of France is"

你一眼就知道答案:巴黎。讀完 Ch7,你會(huì)看到" Paris"以 74.67% 的概率斷崖領(lǐng)先,模型僅憑矩陣乘法與非線性變換,逐層把這個(gè)答案算了出來(lái)。

這篇文章沿著這條管線,帶你走完一個(gè) token 從輸入到輸出的每一步。內(nèi)容對(duì)非算法同學(xué)友好。

全文用 GPT-2 Small 做 trace——不是因?yàn)樗鼜?qiáng),而是因?yàn)樗该鳎杭軜?gòu)與現(xiàn)代 LLM(GPT-4、LLaMA)完全同構(gòu),但參數(shù)少到可以在筆記本上秒級(jí)復(fù)現(xiàn)、逐層打印中間狀態(tài)。把它當(dāng)成管線的最小可運(yùn)行示例:理解了 12 層,擴(kuò)展到 32 層只是數(shù)字放大。 復(fù)現(xiàn)環(huán)境:MacBook M4 Max / Python 3.12 / PyTorch 2.5.1 / Transformers 4.48.3 / tiktoken 0.8.0。

Before the Trace

打開(kāi)你寫(xiě)過(guò)的一個(gè)程序。邏輯在if/else里,數(shù)據(jù)在變量里,兩者界限分明。判斷用戶是否登錄?一個(gè)布爾值加一個(gè)條件分支。查找首都?一個(gè) HashMap,key 是國(guó)家,value 是城市。

在大語(yǔ)言模型里,兩者是同一個(gè)東西

一切皆浮點(diǎn)

打開(kāi) GPT-2 Small 的權(quán)重文件:1.24 億個(gè)浮點(diǎn)數(shù)。沒(méi)有if/else,沒(méi)有switch,沒(méi)有一行代碼說(shuō)"如果問(wèn)法國(guó)首都就回答巴黎"。翻遍每一個(gè)字節(jié),找不到任何顯式的條件判斷。

那么,當(dāng)你輸入"The capital of France is",它怎么"知道"下一個(gè)詞是" Paris"?

答案反直覺(jué):它不"知道"。1.24 億個(gè)浮點(diǎn)數(shù)排成矩陣,輸入 token 變成向量,流過(guò) 12 層矩陣乘法和非線性變換。終點(diǎn)恰好落在詞表空間中" Paris"的方向上,概率 74.67%,斷崖式領(lǐng)先。

沒(méi)有任何一個(gè)參數(shù)單獨(dú)"負(fù)責(zé)"這個(gè)答案,答案是數(shù)值路徑的終點(diǎn)。

整條管線可以看作一個(gè)跑在 GPU 上的程序:權(quán)重加載后常駐顯存,只讀不改,類似進(jìn)程里的 .rodata 段;每次推理就是一次函數(shù)調(diào)用,輸入是 token 序列,輸出是下一個(gè) token 的概率分布。

它和你寫(xiě)的程序有什么區(qū)別?


推理系統(tǒng)的其余部分:采樣、終止判斷、KV Cache 管理,仍然是傳統(tǒng)的控制流代碼。

管線概覽

深入每一步之前,先看一眼完整管線。關(guān)注點(diǎn)不只是模型有哪些組件,更是數(shù)據(jù)在每一步的變換。


24 字節(jié)進(jìn)去,膨脹到 15 KB(FP32),穿過(guò) 12 層矩陣乘法,坍縮回 1 個(gè)整數(shù)。

下面是整條管線的偽代碼。不必現(xiàn)在逐行讀,它是全文的"可執(zhí)行目錄",每行注釋標(biāo)注了對(duì)應(yīng)章節(jié)。先掃一遍建立全局印象,后面每讀完一章回來(lái)看對(duì)應(yīng)的幾行,會(huì)越來(lái)越清晰:


記號(hào)約定:后文中方括號(hào) [...] 有兩種含義: 1. 值(元素內(nèi)容):[464, 3139, 286, 4881, 318] — 數(shù)組里裝的東西,這里是 5 個(gè)具體的 Token ID。特征:數(shù)字大、不規(guī)律。 2. 形狀(shape):float[1, 5, 768] — 多維數(shù)組的各維大小。特征:數(shù)字小、有結(jié)構(gòu)。三個(gè)維度含義:[batch_size, seq_len, hidden_dim],即 batch_size=1(單條請(qǐng)求)、seq_len=5(5 個(gè) token)、hidden_dim=768(每個(gè) token 的向量維度)。 全文 batch_size 始終為 1。遇到歧義處會(huì)加標(biāo)注。

管線就位,把"The capital of France is"喂進(jìn)去,看看會(huì)發(fā)生什么。

Tokenization:從文本到 Token ID


代碼的第一行是tokenizer.encode(text),管線從這里開(kāi)始。

GPU 的計(jì)算單元只做一件事:數(shù)值運(yùn)算。矩陣乘法、向量加法、激活函數(shù),全是數(shù)字。UTF-8 字符串?它看不懂。

所以第一步是把字符串變成整數(shù)序列,即Tokenization(分詞):把連續(xù)文本切分為模型詞表中的離散單元,就像編譯器的 lexer 把源代碼切成 token 流。

最樸素的做法是按字符編碼,每個(gè)字符一個(gè) ID,但一個(gè)詞動(dòng)輒拆成 5–10 個(gè) token,序列太長(zhǎng)。按單詞編碼呢?英文有幾十萬(wàn)個(gè)詞,詞表太大。

GPT-2 用的是Byte Pair Encoding(BPE),一種子詞分詞算法,在字符級(jí)和單詞級(jí)之間取平衡。訓(xùn)練時(shí)反復(fù)合并高頻字節(jié)對(duì)來(lái)構(gòu)建詞表(原理類似 gzip)。訓(xùn)練完成后詞表凍結(jié),本質(zhì)上就是一個(gè)靜態(tài) HashMap:token_string → token_id,50257 條記錄,只讀不改。推理時(shí)純查表。

50257 這個(gè)數(shù)字從哪來(lái)?它是 GPT-2 BPE 詞表的大小,訓(xùn)練時(shí)由合并輪數(shù)決定,之后固定不變。后文會(huì)反復(fù)遇到這個(gè)數(shù)字:Embedding 矩陣有 50257 行(每個(gè) token 一行),LM Head 輸出 50257 個(gè) logit(每個(gè)候選詞一個(gè)分?jǐn)?shù)),一頭一尾,同一個(gè)數(shù)字。

用 OpenAI 的tiktoken跑一遍:

    print(f"{t:>6d}  ->  {repr(enc.decode([t]))}")


5 個(gè) token,5 個(gè)整數(shù)。注意" capital"的前導(dǎo)空格:BPE 把空格編碼為 token 的一部分,讓模型能區(qū)分詞首與詞中。


Embedding:Token ID 膨脹為向量


France的 Token ID 是 4881,capital是 3139,差了 1742,這能告訴你任何語(yǔ)義關(guān)系嗎?

不能,這個(gè)差值是詞表構(gòu)建的偶然產(chǎn)物,跟語(yǔ)義沒(méi)有任何關(guān)系。要做數(shù)值運(yùn)算(矩陣乘法、點(diǎn)積、加法),每個(gè) token 必須從標(biāo)量編號(hào)變成高維向量。這就是Embedding(詞嵌入),把離散 Token ID 映射到連續(xù)向量空間中的一個(gè)點(diǎn),類似于把數(shù)據(jù)庫(kù)主鍵展開(kāi)成一行特征向量。

編號(hào)不可算,向量可以

用顏色打個(gè)比方,Pantone 色號(hào)186 C(紅)和293 C(藍(lán))。186 - 293 = -107,這個(gè)數(shù)字能告訴你紅和藍(lán)有什么關(guān)系嗎?什么都說(shuō)不了。色號(hào)只是查詢代號(hào),差值沒(méi)有語(yǔ)義。Token ID 也一樣,4881 - 3139毫無(wú)意義。

但 RGB 不同:(255, 0, 0)是紅,(0, 0, 255)是藍(lán)。現(xiàn)在你可以算距離、做混色、判斷相似度,因?yàn)槊總€(gè)分量都有意義(紅綠藍(lán)三個(gè)通道的亮度),它們構(gòu)成一個(gè)可計(jì)算的向量空間。


Token ID → Embedding 做的就是這件事:把編號(hào)變成向量。只不過(guò)不是 3 維 RGB,而是 768 維(RGB 各維度有明確含義,Embedding 的 768 維沒(méi)有人工賦予的含義,它們是訓(xùn)練過(guò)程中自動(dòng)涌現(xiàn)的)。

GPT-2 Small 有一個(gè) Embedding 矩陣wte,shape 為[50257, 768],詞表中每個(gè) token 一行(50257 行,Ch2 的詞表大?。啃?768 個(gè)浮點(diǎn)數(shù)。

768 這個(gè)數(shù)字是什么?它是 GPT-2 Small 的"隱藏維度"(hidden_dim),模型配置里寫(xiě)死的超參數(shù),決定了每個(gè) token 用多少維的向量來(lái)表示。768 是全文出現(xiàn)頻率最高的數(shù)字:從 Embedding 查表到最后 LM Head 投影,所有中間狀態(tài)的向量寬度都是 768。你可以把它理解為這條管線里的"總線寬度",貫穿始終。

把 Token ID 4881 送進(jìn)去,取出第 4881 行,得到一個(gè) 768 維向量。操作本身極其簡(jiǎn)單:查表,沒(méi)有計(jì)算,沒(méi)有學(xué)習(xí),就是用整數(shù)做索引取出一行。在 GPU 上,這是一次純內(nèi)存操作,nn.Embedding在推理時(shí)等價(jià)于一次gather。

但這張矩陣不是隨機(jī)的,它是訓(xùn)練過(guò)程收斂后的結(jié)果。第 4881 行(" France")和第 6342 行(" Paris")在 768 維空間中的幾何關(guān)系,恰好編碼了"法國(guó) - 首都 - 巴黎"這一知識(shí)。回到我們的追蹤對(duì)象:5 個(gè) Token ID 變成 5 個(gè) 768 維向量后," France"" capital"不再是差了 1742 的兩個(gè)整數(shù),它們之間的方向和距離攜帶著語(yǔ)義信息。

知識(shí)是向量空間中的方向

RGB 的三個(gè)維度有明確的物理含義。相比之下,Embedding 的 768 維沒(méi)有任何一維叫"國(guó)籍"或"詞性",單個(gè)維度沒(méi)有人類可讀的含義,但方向有。

最經(jīng)典的例子:

背后的規(guī)律:語(yǔ)義關(guān)系在向量空間中表現(xiàn)為方向。"男性→女性"是一個(gè)方向,"國(guó)家→首都"又是一個(gè)方向。訓(xùn)練過(guò)程不會(huì)"告訴"模型"把性別編碼成某個(gè)方向",但統(tǒng)計(jì)壓力迫使它這么做:當(dāng)模型必須從上下文預(yù)測(cè)下一個(gè)詞時(shí),把同類關(guān)系安排到平行的向量位移上是最高效的信息壓縮方式。

研究者稱之為線性表征假說(shuō):概念在向量空間中對(duì)應(yīng)一個(gè)方向,不是一個(gè)"存儲(chǔ)位置"。存在一個(gè)"法國(guó)方向"、一個(gè)"首都方向",它們之間有可計(jì)算的幾何關(guān)系。

768 維夠編碼成千上萬(wàn)個(gè)概念嗎?夠的。高維空間中"幾乎正交"的方向遠(yuǎn)超 768 個(gè),多個(gè)概念通過(guò)稀疏疊加(Superposition)共享同一組維度,只要它們不經(jīng)常同時(shí)激活。代價(jià)是單個(gè)維度不再對(duì)應(yīng)單一含義,這正是 Embedding 不像 RGB 那樣"每維語(yǔ)義透明"的原因。

768 維空間里的加減法

聽(tīng)起來(lái)很抽象,用 GPT-2 的真實(shí)權(quán)重驗(yàn)證一下



實(shí)驗(yàn) 1:減掉"男性方向"、加上"女性方向",queen出現(xiàn)在前幾名。實(shí)驗(yàn) 2:把"日本→東京"的位移方向加到"法國(guó)"上,Paris也在前幾名。這些不是 Embedding 層刻意設(shè)計(jì)的功能,而是訓(xùn)練過(guò)程中自然涌現(xiàn)的幾何結(jié)構(gòu),768 個(gè)維度里,加減法就是語(yǔ)義運(yùn)算。

位置編碼:給向量加上門(mén)牌號(hào)

還有一個(gè)問(wèn)題沒(méi)解決:" capital of France"" France of capital"用了完全相同的 token,查出完全相同的向量,但語(yǔ)義天差地別。Embedding 查表是逐 token 獨(dú)立的:" France"在位置 3 和位置 0 查出來(lái)的向量完全一樣。模型怎么知道誰(shuí)在前誰(shuí)在后?

GPT-2 的解決方案直截了當(dāng):再加一個(gè)矩陣——位置編碼(Positional Encoding)是向 token 向量注入序列位置信息的機(jī)制,就像給數(shù)組元素同時(shí)記住值和下標(biāo)。

GPT-2 的位置編碼矩陣wpeshape 為[1024, 768],1024 是 GPT-2 的最大上下文窗口(位置編碼表只有 1024 行,輸入超過(guò) 1024 個(gè) token 就沒(méi)有對(duì)應(yīng)的位置向量,相當(dāng)于數(shù)組越界),每個(gè)位置一個(gè) 768 維向量。Token Embedding 和 Position Embedding 逐元素相加:最終向量 =token_embedding[token_id] + position_embedding[position]

位置 0 的" The"和位置 3 的" The"雖然 Token ID 相同,但加上不同的位置向量后,它們?cè)?768 維空間中的坐標(biāo)不同,后續(xù)所有計(jì)算都能區(qū)分它們。

GPT-2 用絕對(duì)位置編碼;現(xiàn)代模型用 RoPE(旋轉(zhuǎn)位置編碼),通過(guò)旋轉(zhuǎn)矩陣將位置信息編碼到 Attention 的點(diǎn)積中,天然支持長(zhǎng)度外推。機(jī)制不同但目標(biāo)一致:讓模型區(qū)分同一個(gè) token 在不同位置的出現(xiàn)。


Self-Attention:讓向量互相看見(jiàn)


從這里開(kāi)始,token 進(jìn)入 Transformer 的核心結(jié)構(gòu):Transformer Block(通常簡(jiǎn)稱"層")。GPT-2 Small 有 12 個(gè) Block,編號(hào) Layer 0 到 Layer 11,依次串聯(lián)。每個(gè) Block 內(nèi)部分兩步:① Self-Attention(跨位置信息路由)→② FFN(單位置知識(shí)注入)。我們當(dāng)前在 Layer 0,從步驟 ① 開(kāi)始。

為什么"互相看見(jiàn)"很重要?" capital"的向量里同時(shí)擠著"首都 / 大寫(xiě)字母 / 資本 / 極刑"四種含義,僅憑自身無(wú)法消歧,必須看到" France"才知道該取"首都"。" is"必須看到整句話才能預(yù)測(cè)下一個(gè)詞。

Self-Attention(自注意力)就是做這件事的機(jī)制:每個(gè)位置發(fā)出一個(gè)查詢,檢索所有前序位置的相關(guān)信息,按相關(guān)性加權(quán)匯總,一個(gè)可學(xué)習(xí)的內(nèi)部搜索引擎。

Q / K / V:一個(gè)向量的三種身份

搜索引擎有三個(gè)要素:查詢?cè)~、索引、文檔內(nèi)容。Self-Attention 也一樣,但每個(gè)位置同時(shí)扮演搜索者和被搜索者,因此需要三套獨(dú)立的表征。以" is"(位置 4)為例,它收集信息的過(guò)程可以拆成三個(gè)問(wèn)題:

  1. 我需要什么信息?(Query)——" is"的需求:我在"The ___ of ___ is"句式中,需要找到"主語(yǔ)是什么"和"在問(wèn)什么屬性"

  2. 每個(gè) token 能提供什么線索?(Key)——" France"作為被搜索者的身份標(biāo)簽:我是一個(gè)國(guó)家名

  3. 每個(gè) token 的實(shí)際內(nèi)容是什么?(Value)——" France"作為信息載體:法國(guó)這個(gè)概念的全部語(yǔ)義信息

注意:Key 和 Value 不是同一個(gè)東西。Key是搜索結(jié)果的標(biāo)題摘要,標(biāo)明"我能回答什么問(wèn)題";Value是點(diǎn)進(jìn)去之后的完整頁(yè)面內(nèi)容。搜索靠標(biāo)題匹配,但你真正要的是頁(yè)面里的信息。

為什么需要三個(gè)獨(dú)立的投影矩陣?因?yàn)橥粋€(gè)向量要同時(shí)扮演三種角色。" France"也是查詢者,它同樣要從別的 token 收集信息;但它的 Query("我需要什么")和它的 Key("我能提供什么")完全是兩件事。共用同一組參數(shù)會(huì)讓三種信號(hào)互相干擾,所以 $W_Q$、$W_K$、$W_V$ 各自把輸入投影到不同的子空間。

投影到多少維?GPT-2 Small 有 12 個(gè)并行的 Attention Head(下一節(jié)展開(kāi)),768 維被均分給 12 個(gè) Head,每個(gè) Head 分到 64 維(768 ÷ 12 = 64,不是獨(dú)立超參數(shù),而是均分的結(jié)果)。每個(gè) Head 的投影矩陣為[768, 64],把 768 維輸入投影到該 Head 自己的 64 維工作空間:

V = x · W_V    # [768] → [64]  "我的實(shí)際信息"

12 個(gè) Head 各自輸出 64 維結(jié)果,拼接后恰好回到 768 維(12 × 64 = 768),維度先拆后拼,總量守恒。


上面說(shuō) " is" 的"需求"是找主語(yǔ)、找屬性,那這個(gè)需求哪來(lái)的?不是人為規(guī)定的," is" 的向量本身并不知道該去匹配什么;是 在訓(xùn)練中被反復(fù)調(diào)整,學(xué)會(huì)了把 " is" 投影到 64 維空間里的某個(gè)方向,恰好讓它和攜帶主語(yǔ) / 屬性信息的 Key 點(diǎn)積最大、loss 最低。"找主語(yǔ)" "找屬性"并不是模型里的顯式指令,而是我們對(duì)訓(xùn)練后形成方向的一種事后語(yǔ)義解讀。

4.2 Attention Score:從點(diǎn)積到權(quán)重

Q、K、V 就緒,下一步是打分:" is"的 Query 要和每個(gè)前序 token 的 Key 做點(diǎn)積,算出"該從誰(shuí)那里拿多少信息"。

整個(gè)過(guò)程:Q·K 點(diǎn)積打分 → Mask 遮掉未來(lái) → softmax 歸一化 → 加權(quán)求和 V。逐步展開(kāi)。

Ch3 說(shuō)過(guò)語(yǔ)義關(guān)系是向量空間中的方向。點(diǎn)積(dot product)度量的就是兩個(gè)向量方向的一致程度,逐維相乘再求和。方向越一致,點(diǎn)積越大;正交則趨近零。Ch3 的king ? man + woman ≈ queen用的是向量加減法,這里 Q·K 打分用的是點(diǎn)積,同一個(gè)空間,不同的幾何運(yùn)算。


  1. 點(diǎn)積打分與縮放:每對(duì)位置 的相關(guān)性分?jǐn)?shù):


除以 ( ,即每個(gè) Head 的維度)是為了防止點(diǎn)積過(guò)大導(dǎo)致 softmax 飽和,這就是"ScaledDot-Product Attention"名字的由來(lái)。

  1. Causal Mask(因果遮罩):自回歸生成中,后續(xù) token 尚未產(chǎn)生,不能引用——位置 只能看到位置 的 token。實(shí)現(xiàn)方式:將上三角的分?jǐn)?shù)設(shè)為 ,softmax 后自然變成 0:


" is"(位置 4)能看到全部 5 個(gè) token,"The"(位置 0)只能看到自己。重要推論:只有最后一個(gè)位置看到了完整上下文,這就是為什么最終預(yù)測(cè)只取最后一個(gè)位置的輸出(Ch.7 會(huì)回到這一點(diǎn))。

3. softmax → 加權(quán)求和: Mask 之后,softmax 將分?jǐn)?shù)歸一化為概率分布——這就是 Attention 權(quán)重。權(quán)重越高,從該位置收集的信息越多。最終,按權(quán)重對(duì)所有位置的 Value 加權(quán)求和,得到這個(gè)位置的 Attention 輸出。

整個(gè) Attention 可以理解為一個(gè)可學(xué)習(xí)的信息路由網(wǎng)絡(luò):投影矩陣是路由表,點(diǎn)積算出匹配分?jǐn)?shù),softmax 歸一化為權(quán)重,Value 加權(quán)求和完成信息搬運(yùn)。用 SQL 類比(僅直覺(jué)對(duì)比):SELECT weighted_avg(V) FROM all_previous_tokens WHERE dot(my_Q, their_K) IS HIGH

為什么點(diǎn)積能度量"語(yǔ)義相關(guān)性"? 它本身不能,兩個(gè)隨機(jī)向量的點(diǎn)積是噪聲。讓點(diǎn)積有意義的是 和 這兩個(gè)投影矩陣:訓(xùn)練過(guò)程迫使它們學(xué)會(huì)把語(yǔ)義相關(guān)的 Q 和 K 投影到相似方向上,點(diǎn)積自然就高。這不是數(shù)學(xué)天然做到的,是訓(xùn)練出來(lái)的能力。

跑一遍:" is"到底在看誰(shuí)?

原理講完了,拿 GPT-2 的真實(shí)權(quán)重跑一遍。

我們?nèi)?GPT-2 Layer 0 的Head 6,計(jì)算" is"(位置 4)的 Query 與每個(gè) token 的 Key 的點(diǎn)積,經(jīng)縮放和 softmax,看權(quán)重落在誰(shuí)身上。為什么選 Head 6?12 個(gè) Head 中它的語(yǔ)義路由模式最鮮明,下一節(jié)打印全部 12 個(gè) Head 就能看到對(duì)比。

預(yù)期結(jié)果:" France"" capital"拿走約 70% 的 Attention 權(quán)重,功能詞" of"" is"自身加起來(lái)約 8%。


運(yùn)行輸出(GPT-2):


全是負(fù)數(shù),完全正常。softmax 只看相對(duì)差距,不在乎絕對(duì)值正負(fù)。" France"的 ?5.20 和" capital"的 ?5.34 最接近零,遠(yuǎn)領(lǐng)先于" of"的 ?24.02。縮放后經(jīng) softmax 歸一化:" France"35%," capital"35%,"The"22%,內(nèi)容詞并列第一,功能詞加起來(lái)約 8%。

權(quán)重確定了每個(gè)位置的信息配比。Head 6 的最終輸出 = 各位置 Value 向量的加權(quán)混合:

Head 6 把權(quán)重集中在" France"" capital"上,路由模式明顯偏語(yǔ)義。但這只是 12 個(gè) Head 中的一個(gè)。

Multi-Head:12 雙眼睛同時(shí)看

12 層 vs 12 頭,別搞混。GPT-2 Small 有 12 層(Transformer Block 的堆疊次數(shù),決定模型深度)和 12 頭(同一層內(nèi)并行的注意力子空間數(shù))。兩者恰好相等只是該模型的配置巧合,沒(méi)有必須相等的理論要求。

一個(gè) Head 只能學(xué)一種路由模式。GPT-2 Small 用 12 個(gè) Attention Head 并行運(yùn)行,即Multi-Head Attention(多頭注意力),每個(gè) Head 用獨(dú)立的 、 、 (均為[768, 64])學(xué)習(xí)不同的模式。12 雙眼睛同時(shí)盯著同一句話,各自在自己的 64 維子空間中捕捉不同信號(hào)。

打印 Layer 0 全部 12 個(gè) Head 中," is"對(duì)各 token 的 Attention 權(quán)重:


運(yùn)行輸出(GPT-2):


掃一眼右側(cè)標(biāo)注的模式類型,12 個(gè) Head 清晰地分成幾種路由模式

  • 自注意力型(Head 1 / 3 / 5):80–98% 權(quán)重給了" is"自身,保留本位置原始信號(hào),不從別處搬運(yùn)。

  • 首 token 偏好型(Head 0 / 2 / 9 / 10 / 11):40–61% 權(quán)重給了"The",Layer 0 中首 token 常充當(dāng)"默認(rèn)錨點(diǎn)"(后續(xù)層可能改寫(xiě)這一偏好)。

  • 內(nèi)容路由型(Head 6):" France"35% +" capital"35%,上一節(jié)展開(kāi)的那個(gè) Head,唯一明顯按語(yǔ)義打分的。

  • 分散型(Head 4 / 7):權(quán)重在各 token 間相對(duì)均勻,沒(méi)有突出的贏家。

Layer 0 多數(shù) Head 仍在做位置級(jí)粗調(diào),看自己或看句首,只有少數(shù)開(kāi)始做語(yǔ)義路由。也正常:輸入還是靜態(tài) Embedding,沒(méi)有足夠上下文支撐精細(xì)的語(yǔ)義匹配。更深層的 Head 會(huì)在前序各層積累的上下文基礎(chǔ)上,做更精確的路由。

注意:不要過(guò)度解讀單個(gè) Head 的模式。實(shí)際中 Head 的行為高度重疊且隨輸入變化,沒(méi)有固定的"職責(zé)名"。但 Multi-Head 比 Single-Head 學(xué)到更豐富的路由模式,這一結(jié)論經(jīng)過(guò)消融實(shí)驗(yàn)驗(yàn)證。

12 個(gè) Head 各自輸出 64 維結(jié)果,拼接回 768 維,再過(guò)輸出投影矩陣 ([768, 768])混合 ,Multi-Head Attention 到此完成。

那這些權(quán)重到底改變了什么?

效果:" capital"不再歧義

回到 Ch3 的" capital":不管上下文是"France"還是"venture",Embedding 層取出的都是同一個(gè) 768 維向量,"首都""資本""大寫(xiě)"這些含義都疊在同一組坐標(biāo)里。Embedding 本身不感知上下文,因此無(wú)法消歧。Attention 的作用就在這里:把上下文加進(jìn)來(lái),讓"首都"這個(gè)含義被進(jìn)一步強(qiáng)化。

上一節(jié) Head 6 已經(jīng)展示了過(guò)程:" is"把 35% 的注意力分給" France"、35% 分給" capital",從這兩個(gè)關(guān)鍵詞收集信號(hào)。Attention 按權(quán)重對(duì) Value 加權(quán)求和,產(chǎn)生一個(gè)增量向量,通過(guò)殘差連接(Ch6 詳解)疊加到" is"的原向量上。" capital"" France"的語(yǔ)義在" is"處融合,"首都"方向被增強(qiáng),"資本"、"大寫(xiě)"方向被稀釋。

Embedding 表本身沒(méi)有變," capital" 在詞表第 3139 行的 768 個(gè)浮點(diǎn)數(shù)原封不動(dòng),變的是各位置上的向量:Attention 給每個(gè)位置都疊加了來(lái)自上下文的增量。

多義消歧不靠規(guī)則,靠 Attention 把正確的上下文路由到正確的位置,通過(guò)向量加法改變坐標(biāo)。這就是「讓向量互相看見(jiàn)」的實(shí)際效果。


FFN:用上下文檢索知識(shí)


還在 Layer 0,Attention 完成了第一步," is"的向量已聚合了" France"" capital"的信號(hào),模型"知道"了在問(wèn)法國(guó)的首都。但搬運(yùn)不等于回答:Attention 在位置間路由已有信息,本身不產(chǎn)生新知識(shí)。

答案藏在同一層的第二步——Feed-Forward Network(FFN)。分工很簡(jiǎn)單:Attention 決定“看誰(shuí)”,F(xiàn)FN 決定“看完之后想起什么”。前者跨位置路由,后者逐位置獨(dú)立加工;進(jìn)了 FFN,token 之間不再通信。

別被它樸素的結(jié)構(gòu)騙了:GPT-2 每層中 FFN 的參數(shù)量是 Attention 的兩倍;12 層總計(jì),FFN 占模型約 2/3 的參數(shù)。大部分參數(shù)不在路由,在記憶。

FFN = Key-Value Memory

先給結(jié)論:FFN 是一張寫(xiě)死在權(quán)重里的 Key-Value 查找表(Geva et al., 2021),共 3072 行,每行存一個(gè)"模式"(Key)和一個(gè)對(duì)應(yīng)的"知識(shí)片段"(Value)。輸入向量和 3072 個(gè)模式逐一比對(duì),命中的就把對(duì)應(yīng)知識(shí)注入輸出。

具體三步:

第一步:匹配—和 3072 個(gè)模式逐一比對(duì)。權(quán)重矩陣 $W_1$(shape[768, 3072])存著 3072 個(gè) 768 維"模式向量"。輸入向量x和它們逐一做點(diǎn)積,點(diǎn)積越大表示越匹配,得到 3072 個(gè)匹配分?jǐn)?shù)。

# x: [768]  →  W?: [768, 3072]  →  scores: [3072]

3072 從哪來(lái)?3072 = 768 × 4。4× 擴(kuò)展是 Transformer 原論文的設(shè)計(jì)慣例:中間層越寬 → 模式檢測(cè)器越多 → 知識(shí)容量越大,但參數(shù)量線性增長(zhǎng)。4× 是論文作者在能力和成本之間取的平衡點(diǎn),它是可調(diào)的超參數(shù)。

第二步:過(guò)濾—GELU 只放行命中的模式。3072 個(gè)分?jǐn)?shù)里大部分為負(fù),表示"不匹配"。GELU 激活函數(shù)充當(dāng)門(mén)控:正分?jǐn)?shù)基本放行,負(fù)分?jǐn)?shù)壓到接近零——類似WHERE score > 0。實(shí)際激活非常稀疏,多數(shù)模式被拒之門(mén)外。

第三步:注入—把命中的知識(shí)寫(xiě)入輸出。另一個(gè)權(quán)重矩陣 (shape[3072, 768])存著 3072 個(gè) 768 維的"知識(shí)向量",和第一步的模式一一對(duì)應(yīng)。第 個(gè)模式命中,對(duì)應(yīng)的知識(shí)向量就按匹配分?jǐn)?shù)加權(quán)注入輸出。

# filtered_scores: [3072]  →  W?: [3072, 768]  →  output: [768]

三步合成一個(gè)公式:

形狀變化768 → 3072 → 768:先升維做匹配和過(guò)濾,再降維寫(xiě)回。3072 只存在于 FFN 內(nèi)部的瞬態(tài),進(jìn)出都是 768,和 Attention 一樣不改變 shape。

回到例子。" is"經(jīng)過(guò) Attention 后攜帶了" capital"" France"的信號(hào),流入 FFN,和 的 3072 個(gè)模式逐一匹配,某些模式可能對(duì)應(yīng)"X 的首都是___"這類句式。命中后, 中對(duì)應(yīng)的知識(shí)向量被激活并注入,這就是"用上下文檢索知識(shí)"的物理過(guò)程。

回看三步:匹配、過(guò)濾、注入,這就像一次 Key-Value 查找:


每層 3072 個(gè)模式 - 知識(shí)對(duì);GPT-2 Small 12 層共 36,864 個(gè);LLaMA 3.1 8B 32 層、每層 14336 個(gè),共 458752 個(gè)。模型越大,查找表行數(shù)越多,這就是"scaling"的物理含義之一。

Layer 0 完成:Attention + FFN

至此,Layer 0 的兩個(gè)步驟(Attention 和 FFN)全部完成。兩者分工互補(bǔ):


Layer 0 的完整數(shù)據(jù)流:


形狀沒(méi)變,進(jìn)去[1, 5, 768],出來(lái)還是[1, 5, 768]。但每個(gè)向量的內(nèi)容已經(jīng)大不一樣:帶上了上下文(Attention 搬來(lái)的)和知識(shí)增量(FFN 注入的)。圖中兩處[+]是殘差連接,子層只產(chǎn)出增量,原始信息不丟。Ch6 展開(kāi)。


Layers: 12 層到 " Paris"


Layer 0 走完了:Attention 搬運(yùn)信息,F(xiàn)FN 檢索知識(shí)。但 12 層 Block 結(jié)構(gòu)完全相同,shape 始終[1, 5, 768],剩下 11 層在干什么?

答案在層與層之間的連接方式里。取" is"位置的向量,Layer 0 出來(lái)的和 Layer 11 出來(lái)的做余弦相似度極低,方向幾乎無(wú)關(guān)。同樣 768 維,每一個(gè)數(shù)字都被改寫(xiě)了

殘差流:不過(guò)收費(fèi)站,只進(jìn)服務(wù)區(qū)

殘差連接解決兩個(gè)問(wèn)題:防信息遺忘、防梯度消失。先看機(jī)制,再看為什么。

對(duì)"深度網(wǎng)絡(luò)"的常見(jiàn)直覺(jué)是數(shù)據(jù)必須串行穿過(guò)每一層:像過(guò)高速公路收費(fèi)站,層層攔截、層層變換。殘差流不是這樣。

殘差流(Residual Stream)是一條從 Embedding 層直通輸出層的信息主干道。數(shù)據(jù)始終沿主干道流動(dòng)。Attention 和 FFN 是旁邊的服務(wù)區(qū):拐進(jìn)去加工,產(chǎn)出增量(delta),合并回主干道繼續(xù)前進(jìn)。每一層不"替換"數(shù)據(jù),只往主干道上追加增量。


每個(gè)[+]是一次殘差加法:Attn 和 FFN 從殘差流讀取當(dāng)前狀態(tài),計(jì)算增量,再寫(xiě)回。Layer 0 寫(xiě)入的信息不會(huì)被 Layer 11 覆蓋,它始終留在主干道上,被后續(xù)增量持續(xù)疊加。

用公式把 12 層全部展開(kāi):

最終輸出 = 原始 Embedding +所有層所有子層的增量之和。 和 分別是第 層 Attention 和 FFN 寫(xiě)入殘差流的增量。

為什么這樣設(shè)計(jì)?如果沒(méi)有殘差連接(即去掉[+]旁路,讓每層直接串聯(lián)),會(huì)有兩個(gè)致命問(wèn)題:

  1. 信息遺忘。沒(méi)有殘差連接時(shí),每一層必須在輸出中同時(shí)保留舊信息和寫(xiě)入新信息——如果 Layer 5 的變換恰好丟失了 Layer 0 寫(xiě)入的句法信號(hào),后續(xù)層就再也找不回來(lái)。殘差連接讓每一層只需要輸出增量,原始信息始終留在主干道上。Layer 11 可以直接讀到 Embedding 層寫(xiě)入的信號(hào),不依賴中間層的完美傳遞。

  2. 梯度消失(訓(xùn)練視角的補(bǔ)充,趕時(shí)間可跳過(guò))。訓(xùn)練時(shí)梯度從最后一層反向傳播回第一層,每穿過(guò)一層非線性變換就乘一次導(dǎo)數(shù),12 層連乘,梯度指數(shù)級(jí)衰減,淺層參數(shù)學(xué)不到東西。殘差連接提供了一條梯度高速公路:加法的導(dǎo)數(shù)恒為 1,梯度沿殘差路徑直接回傳,無(wú)需穿過(guò)非線性:這是 Transformer 能堆到 96 層還能訓(xùn)練的原因之一。

簡(jiǎn)言之:殘差流讓加工和傳輸解耦:主干道負(fù)責(zé)無(wú)損傳輸,服務(wù)區(qū)只負(fù)責(zé)增量加工。

每層只追加增量,那 12 層追加的東西有什么不同?研究者通過(guò) Probing(給每層的輸出接一個(gè)簡(jiǎn)單分類器做"單元測(cè)試")揭示了大致的分工梯度:


實(shí)際各層功能大量重疊,但"淺層偏句法、深層偏預(yù)測(cè)"的總趨勢(shì)成立。

Layer 11 結(jié)束時(shí)," is"位置的 768 維向量同時(shí)攜帶了句法、語(yǔ)義、預(yù)測(cè)三類信號(hào),多種概念共享 768 個(gè)維度,借助近似正交避免互相干擾。

原理講完了,跑一遍代碼看看" Paris"怎么一步步浮現(xiàn)。

跑一遍:" Paris"怎么出現(xiàn)的?

" Paris"到底怎么一步步浮現(xiàn)的?Logit Lens提供了一種直觀的探測(cè)手段:對(duì)每一層的隱藏狀態(tài)直接應(yīng)用最終的 LN + LM Head,看"如果推理到此為止,模型會(huì)預(yù)測(cè)什么"。它不反映模型的真實(shí)決策路徑(中間層不是為直接解碼設(shè)計(jì)的),但像 X 光一樣透視了殘差流中信息的逐層積累。

關(guān)于 Prompt:GPT-2 Small 只有 124M 參數(shù),裸句 "The capital of France is" 不足以形成高置信預(yù)測(cè)。從這里開(kāi)始,在 prompt 前面補(bǔ)一條 few-shot 示例 "The capital of China is Beijing."——和我們?nèi)粘=o大模型加示例是同一個(gè)思路。換成更大模型,單句即可。后續(xù) Ch7 的代碼使用同樣的 prompt。


運(yùn)行輸出(GPT-2):


" Paris"在 50257 個(gè)候選 token 中的排名變化:


三個(gè)觀察:

  1. Layer 8 是關(guān)鍵拐點(diǎn)。Paris 從 直接跳到 ,概率從 0.55% 飆升至 88.35%?;叵?Ch5 的 FFN-as-Memory:Layer 8 激活的那幾個(gè) FFN 神經(jīng)元恰好編碼了"法國(guó)→巴黎"的關(guān)聯(lián),正是 Key-Value Memory 的實(shí)際運(yùn)作。每層只有少數(shù)神經(jīng)元被激活,這一層命中的恰好是"X 的首都"類模式。

  2. 多層接力,不是重復(fù)。每層只能做一步有限變換:一次 Attention 路由 + 一次 FFN 模式匹配。從"The capital of France is"" Paris"登頂需要多步:句法綁定 → 實(shí)體關(guān)系識(shí)別 → 知識(shí)檢索 → 預(yù)測(cè)信號(hào)組合。Layer 0–7 完成前三步,Layer 8 完成關(guān)鍵注入,Layer 9–10 鞏固和校準(zhǔn)。更多層 = 更多加工步驟 = 更復(fù)雜的推理鏈。

  3. Logit Lens 是近似,不是精確。中間層的隱藏狀態(tài)不是為直接解碼設(shè)計(jì)的——Layer 8 的 88% 不代表模型在那一刻"決定了 Paris",只說(shuō)明殘差流在那個(gè)階段已積累了大量指向 Paris 的信號(hào)。


LM Head:從向量到概率


12 層 Transformer Block 走完,5 個(gè)位置各留下一個(gè) 768 維向量。最后一步:把向量映射回詞表中的 50257 個(gè)候選詞。

翻譯哪個(gè)位置?只取最后一個(gè)。回憶 Ch4 的 Causal Mask:每個(gè)位置只能看到自己及之前的 token。位置 0("The")只看到自己,位置 1(" capital")只看過(guò)前兩個(gè) token,而位置 4(" is")是唯一看過(guò)完整上下文的位置,信息最完整的向量,才有資格做預(yù)測(cè)。

接下來(lái),一次矩陣乘法完成翻譯。

Unembedding:從向量回到詞表

取最后一個(gè)位置的 768 維向量 ,乘以[768, 50257]LM Head矩陣:

得到 50257 個(gè)標(biāo)量,每個(gè)對(duì)應(yīng)詞表中一個(gè) token 的logit(未歸一化的對(duì)數(shù)分?jǐn)?shù))。幾何上看:每個(gè) logit 就是 與第 個(gè) token 向量的點(diǎn)積,點(diǎn)積越大,說(shuō)明隱藏狀態(tài)越靠近該 token 的方向,對(duì)應(yīng)概率越高。

這一步是 Ch3 Embedding 的鏡像。Embedding 把 Token ID 查表變成 768 維向量(整數(shù) → 向量);LM Head 把 768 維向量投影到 50257 個(gè)詞表方向上(向量 → 整數(shù))。GPT-2 中兩者共享同一個(gè)矩陣: (weight tying),一張表,兩個(gè)方向。

跑一遍:Next-Token 概率分布

Ch6 的 Logit Lens 追蹤了" Paris"從第 28383 名逐層攀升至第 1 名的過(guò)程,但那只是盯著單個(gè) token 的排名。50257 個(gè)候選 token 的完整概率分布長(zhǎng)什么樣?

拿 GPT-2 的真實(shí)權(quán)重跑一遍。

    print(f"  {prob.item():>8.2%}  {repr(token)}")


輸出(GPT-2,prompt 與 Ch6 相同,含 few-shot 前綴):


兩個(gè)特征:斷崖式長(zhǎng)尾。" Paris"獨(dú)占 74.67%,第二名不到 4%。Top-10 合計(jì)約 87%:50257 個(gè)候選中,絕大多數(shù) token 分到的概率幾乎為零。12 層變換把隱藏狀態(tài)雕刻得非常"尖銳":768 維向量在詞表空間中幾乎只指向一個(gè)方向。語(yǔ)義聚類。排名 2–4 的" Marse"(馬賽)、" Lyon"(里昂)、" Nice"(尼斯)全是法國(guó)城市。高概率候選不是隨機(jī)散落,而是形成了語(yǔ)義鄰域:這印證了 Ch3 Embedding 空間的結(jié)構(gòu):含義相近的 token,向量方向也相近,投影得分自然接近。

50257 個(gè)概率擺在面前。這個(gè)例子里" Paris"74.67% 一騎絕塵,但不是所有分布都這么尖銳。開(kāi)放式續(xù)寫(xiě)時(shí)頭部可能有多個(gè)旗鼓相當(dāng)?shù)暮蜻x,采樣策略的選擇就變得重要了。

采樣:從概率到 Token

LM Head 輸出了 50257 個(gè) logits。從這里開(kāi)始不再是神經(jīng)網(wǎng)絡(luò),而是經(jīng)典的概率采樣,從候選中選出 1 個(gè) token。兩個(gè)旋鈕控制"怎么選":

Temperature:在 softmax 之前,先把每個(gè) logit 除以溫度系數(shù) 。借用熱力學(xué)的類比:溫度越低,粒子越安分、只待在能量最低點(diǎn);溫度越高,粒子越躁動(dòng)、去哪都可能。 就是 greedy decoding(直接取最高分), 是原始分布, 讓低概率 token 也有機(jī)會(huì)。

Top-K / Top-P:softmax 之后裁剪候選集。Top-K 只保留概率最高的 K 個(gè)候選;Top-P(Nucleus Sampling)保留累積概率剛達(dá)到 P 的最小集合。兩者可以疊加使用。

在我們的例子里,無(wú)論 greedy 還是 Top-K=10," Paris"都會(huì)被選中。選中后 Token ID = 6342,解碼回" Paris",追加到輸入序列。


自回歸:LLM 的斐波那契

上一章跑完了一次前向推理:5 個(gè) token 穿過(guò)整條管線," Paris"以 74.67% 被選出,Token ID = 6342 追加到輸入——序列變?yōu)?code>[464, 3139, 286, 4881, 318, 6342](6 個(gè) Token ID)。句子還沒(méi)完,能不能一口氣把剩下的詞全部生成?

為什么不一次全生成?

非不為也,實(shí)不能也。原因是一條繞不過(guò)的因果鏈:第 N 個(gè)生成的 token 必須作為第 N+1 步的輸入。

模型剛輸出" Paris",下一步要預(yù)測(cè)它之后是什么,但" Paris"本身會(huì)改變后續(xù)每個(gè)詞的概率分布,必須先把它送回輸入才能繼續(xù)。輸出反饋為輸入,這就是自回歸(Autoregressive

每個(gè)


依賴前面所有詞,包括模型自己剛生成的。這是經(jīng)典的 loop-carried dependency(循環(huán)攜帶依賴):第 次迭代的輸出是第 次的輸入,就像斐波那契數(shù)列: 依賴 , 依賴 ,不能跳步,不能并行。

因此,生成 100 個(gè) token 就要跑 100 次前向推理,每次只產(chǎn)出 1 個(gè)。這是語(yǔ)言生成的因果約束。

兩個(gè)階段:Prefill 與 Decode

生成必須逐個(gè)進(jìn)行,但輸入可以一次性并行處理,這一區(qū)別把 LLM 推理劃分為兩個(gè)階段:

  • Prefill(預(yù)填充):把用戶輸入的所有 token一次性喂給模型,算出第一個(gè)生成詞,這一步是"讀題"。輸入 token 全部已知,沒(méi)有因果依賴,可以并行。

  • Decode(解碼):之后每步只處理上一步剛生成的1 個(gè)token,產(chǎn)出下一個(gè)詞,這一步是"逐字作答"。每個(gè)詞依賴前一個(gè)的輸出,只能串行。

兩個(gè)階段的硬件行為區(qū)別很大:


一個(gè) compute-bound,一個(gè) memory-bound;Decode 每步仍要從顯存搬運(yùn)整個(gè)模型的權(quán)重,但計(jì)算量驟降為一行矩陣乘法,數(shù)千 CUDA 核心等著數(shù)據(jù)送過(guò)來(lái)(Ch9 分析這個(gè)比例)。這直接決定了成本結(jié)構(gòu):輸入 token 便宜,輸出 token 貴,各家 API 的輸出定價(jià)都顯著高于輸入。

但 Decode 還有一個(gè)性能問(wèn)題:每步的 Attention 需要所有前序 token 的 Key 和 Value,而這些值上一步剛算過(guò),能不能緩存復(fù)用?

KV Cache:空間換時(shí)間

生成第 7 個(gè) token 時(shí),需要對(duì)所有 7 個(gè)位置計(jì)算 Attention。但前 6 個(gè) token 的 Key 和 Value上一步已經(jīng)算過(guò)了,而且由于 Causal Mask,前面位置的 K/V 不受新 token 影響,值不會(huì)變。

KV Cache就是這層 memoization:把每一層、每個(gè) Head 算過(guò)的 K 和 V 向量緩存起來(lái),就像給純函數(shù)的返回值做備忘錄。每一步只需要:

  1. 為新 token 計(jì)算 Q、K、V

  2. 把新 K、V追加到緩存尾部

  3. 用新 token 的 Q 和全部緩存的 K做 Attention,得到權(quán)重后和全部緩存的 V加權(quán)求和

類似動(dòng)態(tài)規(guī)劃里的備忘錄:fib(99)算完先存起來(lái),下一步算fib(100)直接復(fù)用,不用把 99 再算一遍。

這樣就避免了對(duì)前序 token 的重復(fù)計(jì)算。時(shí)間節(jié)省巨大,但空間代價(jià)也巨大:每生成一個(gè) token,就往 KV Cache 追加一行。在請(qǐng)求存活期間只mallocfree,顯存單調(diào)遞增。

以下數(shù)字以 LLaMA 3.1 8B(FP16)為例:32 層,dim=4096,32 Query Head / 8 KV Head(GQA),總參數(shù)約 8B。GPT-2 Small 太小,不足以體現(xiàn) KV Cache 的顯存壓力。

每 各 一 份 層 數(shù) 數(shù) 字 節(jié)


128K 上下文時(shí)一張 A100 只能并發(fā)約 4 個(gè)對(duì)話,容量規(guī)劃的瓶頸從 QPS 變成了"并發(fā)對(duì)話數(shù) × 上下文長(zhǎng)度"。由此催生 PagedAttention、KV Cache 量化、GQA/MQA 等優(yōu)化。

KV Cache 還帶來(lái)一個(gè)副產(chǎn)品:Prompt Cache。如果多次請(qǐng)求的 prompt 前綴相同,Prefill 階段已緩存的 KV 可以跨請(qǐng)求復(fù)用,無(wú)需重新計(jì)算。實(shí)踐建議:system prompt 放最前面且保持穩(wěn)定,可變部分(用戶輸入、few-shot 動(dòng)態(tài)選擇)放后面:前綴命中時(shí),輸入成本會(huì)顯著下降。


GPU 執(zhí)行:算力都去哪了?

Ch8 留下一個(gè)懸念:Decode 階段 GPU 利用率只有個(gè)位數(shù)。本章從芯片層分析這個(gè)現(xiàn)象。GPU 標(biāo)稱 312 TFLOPS(每秒可執(zhí)行 312 萬(wàn)億次乘加操作),逐 token 生成時(shí)實(shí)際用了不到 1%。瓶頸在哪?怎么緩解?

本章沿用 Ch8 引入的 LLaMA 3.1 8B(32 層,dim=4096,F(xiàn)P16 權(quán)重 ~16 GB)與 A100 80GB配置。新出現(xiàn)的硬件參數(shù):A100 FP16 峰值算力 312 TFLOPS,HBM 帶寬 2 TB/s

一次矩陣乘法的旅程

一個(gè)關(guān)鍵直覺(jué):GPU 不是"一塊很快的芯片",而是存儲(chǔ)系統(tǒng) + 計(jì)算系統(tǒng)。計(jì)算單元(Tensor Core)速度極快,但只能處理片上高速緩存(SRAM)里的數(shù)據(jù);模型權(quán)重太大,只能常駐顯存(HBM)。每次計(jì)算前,數(shù)據(jù)必須從 HBM 搬到 SRAM,這趟搬運(yùn)的速度,決定了一切。

以 Decode 階段的一次 FFN 上投影為例:[1, 4096] × [4096, 14336],一個(gè) token 的 4096 維隱藏向量乘以 FFN 的 權(quán)重矩陣,權(quán)重約 112 MB。這次乘法必須穿過(guò)以下存儲(chǔ)層次:


執(zhí)行過(guò)程:

  1. 搬運(yùn)權(quán)重(HBM → SRAM):112 MB 權(quán)重以 2 TB/s 帶寬分塊傳入 SRAM,耗時(shí) ≈ 56 μs

  2. 計(jì)算:Tensor Core 執(zhí)行乘 - 加融合,總計(jì)算量 ≈ 117 MFLOPs,312 TFLOPS 算力下耗時(shí) ≈ 0.4 μs

  3. 輸入向量?jī)H 8 KB、輸出僅 28 KB,傳輸成本可忽略

搬運(yùn) 56 μs,計(jì)算 0.4 μs——比值約 140:1。Tensor Core 在 99.3% 的時(shí)間里等數(shù)據(jù)送過(guò)來(lái)。

這不是個(gè)例,而是 Decode 階段所有算子的通病。性能分析中有一個(gè)判斷指標(biāo)叫算術(shù)強(qiáng)度(Arithmetic Intensity):每搬運(yùn) 1 字節(jié)數(shù)據(jù)能做多少次浮點(diǎn)運(yùn)算。A100 的分界線是 312 TFLOPS ÷ 2 TB/s ≈156 FLOPs/Byte,低于此值,GPU 被帶寬而非算力卡住。Decode 一個(gè) token 需搬運(yùn)全部 ~16 GB 權(quán)重,計(jì)算量 ~16 GFLOPs,算術(shù)強(qiáng)度 ≈1 FLOPs/Byte,離分界線差兩個(gè)數(shù)量級(jí)。

Batching:請(qǐng)求拼一刀

算術(shù)強(qiáng)度 = FLOPs / Bytes。分母(權(quán)重搬運(yùn)量)跟模型綁定,動(dòng)不了;但分子可以。同時(shí)處理 32 個(gè)請(qǐng)求,矩陣乘法變成[32, 4096] × [4096, 14336],同樣搬一次 112 MB 權(quán)重,32 個(gè)輸入共享復(fù)用,算術(shù)強(qiáng)度從 1 升到 32。Batching(批處理)的本質(zhì)不是軟件優(yōu)化是讓搬來(lái)的權(quán)重被更多 token 復(fù)用。

但最樸素的 Static Batching(把一批請(qǐng)求湊齊再一起跑)有個(gè)問(wèn)題:所有請(qǐng)求必須同時(shí)開(kāi)始、同時(shí)結(jié)束,短請(qǐng)求得陪長(zhǎng)請(qǐng)求空轉(zhuǎn)。


Continuous Batching解決了這個(gè)問(wèn)題:請(qǐng)求跑完立即退出 batch,空位立即插入新請(qǐng)求。


吞吐量可提升 2–4×,是 vLLM、TGI、TensorRT-LLM 等推理框架的核心調(diào)度策略。

顯存里都住了誰(shuí)?

Batch 越大利用率越高,但上限不是算力——是顯存。80 GB HBM 里住著三類"居民":


  • 權(quán)重:只讀,加載后常駐,所有請(qǐng)求共享,上文中等待搬運(yùn)的就是這 16 GB

  • KV Cache:每請(qǐng)求獨(dú)立分配,生命周期內(nèi)單調(diào)增長(zhǎng)。128K 上下文時(shí)單對(duì)話 KV 達(dá) 16 GB

  • 激活值:層間臨時(shí)數(shù)據(jù),前一層用完即釋放給下一層。占用小但峰值隨 batch 線性增長(zhǎng)

Batch=64 時(shí) KV Cache 膨脹到數(shù)十 GB,直接擠壓可服務(wù)的并發(fā)數(shù)。PagedAttention 用虛擬內(nèi)存的思路按頁(yè)分配 KV Cache(按需分配、減少碎片),在同樣 80 GB 里塞進(jìn)更多請(qǐng)求。


After the Trace

一個(gè) token 從輸入到輸出走完了。工程師會(huì)問(wèn)兩件事:能 debug 嗎?該怎么用它?

能 Debug 嗎?

每一層的中間狀態(tài)都可以截獲:隱藏狀態(tài)[1, 5, 768]、Attention 權(quán)重矩陣、最終概率分布,數(shù)值一個(gè)不少。

但數(shù)值不等于理解。你看不出某個(gè) Head 為什么給了高權(quán)重,不知道 FFN 哪些神經(jīng)元編碼了什么語(yǔ)義。768 維向量可以打印,卻不能直接讀出里面編碼了什么,就像拿到一個(gè)巨型操作系統(tǒng)的二進(jìn)制文件,每條指令都在,但你幾乎不可能從機(jī)器碼還原出設(shè)計(jì)意圖。

研究者在嘗試間接手段:在隱藏狀態(tài)上訓(xùn)練線性分類器(Probing),探測(cè)某個(gè)位置是否編碼了詞性;替換某一層的激活、觀察輸出變化(Activation Patching),定位關(guān)鍵層;用稀疏自編碼器(SAE)把激活分解為可解釋的特征方向。這些工具在進(jìn)步,但老實(shí)說(shuō)——我們離真正 debug 一個(gè) LLM 還很遠(yuǎn)。小模型上已有零星突破,但主流規(guī)模的模型內(nèi)部機(jī)制仍是高維黑箱。

變量全能讀,但沒(méi)有符號(hào)表,怎么辦?

工程師的 Takeaway

一:測(cè)試靠行為,護(hù)欄放外面1.24 億個(gè)浮點(diǎn)數(shù)里沒(méi)有任何一條規(guī)則說(shuō)"巴黎是法國(guó)首都",只有數(shù)值路徑,路徑的終點(diǎn)就是答案。你無(wú)法通過(guò)檢查參數(shù)來(lái)預(yù)測(cè)邊緣場(chǎng)景的行為。唯一可靠的方法與測(cè)試沒(méi)有源碼的黑盒 API 無(wú)異:構(gòu)造輸入,檢查輸出。

實(shí)操原則:安全過(guò)濾、格式驗(yàn)證、事實(shí)核查,都應(yīng)作為模型外部的 pipeline 組件實(shí)現(xiàn)。模型是協(xié)處理器:喂數(shù)據(jù)、收結(jié)果、你來(lái)兜底。

二:善用 CacheCh8 展開(kāi)了兩層 cache:KV Cache 避免 Decode 逐步重算;Prompt Cache 在前綴相同時(shí)跨請(qǐng)求復(fù)用 Prefill。實(shí)操原則:system prompt 固定、放最前,最大化前綴命中率;用結(jié)構(gòu)化輸出讓模型只返回需要的字段,每少一個(gè)輸出 token,就少一次串行 Decode、少搬運(yùn)一次全部權(quán)重。輸出 token 是最貴的資源,各家 API 的輸出定價(jià)都顯著高于輸入。

三:語(yǔ)義是幾何:Prompt 調(diào)優(yōu)是路徑工程king - man + woman ≈ queen不是巧合,訓(xùn)練壓力把同類關(guān)系編碼為平行的向量位移。"巴黎是法國(guó)首都"不占某個(gè)參數(shù)的某一位,而是一個(gè)幾何性質(zhì):向量經(jīng)過(guò) 12 層變換后,殘差流的疊加結(jié)果恰好落在" Paris"附近。這個(gè)結(jié)構(gòu)不是設(shè)計(jì)出來(lái)的,是數(shù)十億句子的統(tǒng)計(jì)壓力壓出來(lái)的。

同一組權(quán)重,不同的輸入走出完全不同的數(shù)值路徑。Prompt Engineering 本質(zhì)上是在操控路徑的起點(diǎn):few-shot examples 示范路徑走向,system prompt 約束搜索空間。理解了這條管線,prompt 調(diào)優(yōu)就不是玄學(xué),而是路徑工程:你改變的不是模型,是矩陣乘法的輸入端。

Review

Ch1 的表格是宏觀對(duì)比,走完管線后可以做更細(xì)粒度的映射:函數(shù)簽名、rodata、stack、heap,每個(gè)概念在管線里都有對(duì)應(yīng)物。


偽代碼已在 Ch1 給出,對(duì)照這張表重讀一遍,會(huì)覺(jué)得很親切。

從 Pixel 到 Token

開(kāi)篇借了 Chrome 團(tuán)隊(duì)的比喻:追蹤一個(gè)像素走完渲染管線的旅程。現(xiàn)在,這枚 token 也走完了它的一生:字符串 → 整數(shù) → 向量 → 12 層變換 → 概率分布 → 采樣 →" Paris"

Pixel 和 Token 最終都落在同一塊芯片上:GPU。渲染管線里它把頂點(diǎn)變成像素,LLM 管線里它把浮點(diǎn)變成下一個(gè) token。同一塊硬件,同一種矩陣乘法,產(chǎn)出截然不同的東西:一個(gè)是你看見(jiàn)的畫(huà)面,一個(gè)是你讀到的文字。

單看一次矩陣乘法,什么也看不出來(lái)。但 1.24 億個(gè)參數(shù)做上億次乘加,知識(shí)就從數(shù)值中浮現(xiàn)了。

沒(méi)有哪一個(gè)參數(shù)獨(dú)自“記住”了巴黎是法國(guó)首都。1.24 億個(gè)浮點(diǎn)數(shù)歷經(jīng) 12 層變換,把"France""capital"的向量一步步推向" Paris"所在的方向。知識(shí)不是被存儲(chǔ)的,是被矩陣乘法一層一層算出來(lái)的。

每一點(diǎn)都平凡,但走完整條管線再回望:恰是足夠多的平凡,堆成了非凡。

當(dāng)前文章內(nèi)容與結(jié)構(gòu)經(jīng)過(guò)調(diào)整,原文見(jiàn):

Life of a Token: LLM's Next-Token Pipeline(https://kcnrpnk9jqxn.feishu.cn/wiki/LDSUwt1Gfi5uOmkhRXScfIExnBb)

會(huì)議推薦

QCon 全球軟件開(kāi)發(fā)大會(huì)·2026 北京站將于 4 月 16 日 -18 日正式舉辦。本屆大會(huì)以“Agentic AI 時(shí)代的軟件工程重塑”為主題,聚焦 100+ 重磅議題,匯聚來(lái)自阿里、騰訊、字節(jié)跳動(dòng)、小米、百度等一線科技企業(yè)與創(chuàng)新團(tuán)隊(duì)的技術(shù)專家,圍繞 AI 工程化、系統(tǒng)架構(gòu)與研發(fā)模式演進(jìn)展開(kāi)深入探討。更多詳情可掃碼或聯(lián)系票務(wù)經(jīng)理 18514549229 進(jìn)行咨詢。

今日薦文

你也「在看」嗎?

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點(diǎn)推薦
其實(shí)從某個(gè)角度來(lái)說(shuō),李自成才是真正挽救了華夏民族的人

其實(shí)從某個(gè)角度來(lái)說(shuō),李自成才是真正挽救了華夏民族的人

掠影后有感
2026-05-06 09:58:38
汽油稅幾乎占了油價(jià)的5成,如果未來(lái)路上都是電動(dòng)車,稅從哪收?

汽油稅幾乎占了油價(jià)的5成,如果未來(lái)路上都是電動(dòng)車,稅從哪收?

講者普拉斯
2026-05-04 17:58:00
FIFA急瘋了!2000萬(wàn)美元打發(fā)叫花子?許多國(guó)家和中國(guó)一樣不買單了

FIFA急瘋了!2000萬(wàn)美元打發(fā)叫花子?許多國(guó)家和中國(guó)一樣不買單了

春序娛樂(lè)
2026-05-07 04:52:17
吳宜澤奪冠后首度現(xiàn)身國(guó)內(nèi),在西安機(jī)場(chǎng)受球迷接機(jī)送花,之后還將舉行見(jiàn)面會(huì),此前他曾表示想回國(guó)吃美食、見(jiàn)朋友

吳宜澤奪冠后首度現(xiàn)身國(guó)內(nèi),在西安機(jī)場(chǎng)受球迷接機(jī)送花,之后還將舉行見(jiàn)面會(huì),此前他曾表示想回國(guó)吃美食、見(jiàn)朋友

極目新聞
2026-05-07 07:12:51
申京再遭打擊!場(chǎng)均20+9+6仍不被認(rèn)可?最被高估球員榜,他排第一

申京再遭打擊!場(chǎng)均20+9+6仍不被認(rèn)可?最被高估球員榜,他排第一

熊哥愛(ài)籃球
2026-05-07 12:38:28
炸裂!32歲長(zhǎng)子弒殺全家!父母三弟全遇害,二弟死里逃生!

炸裂!32歲長(zhǎng)子弒殺全家!父母三弟全遇害,二弟死里逃生!

北國(guó)向錫安
2026-05-07 09:54:40
英國(guó)車手哈蒙德飛赴上海試駕張雪機(jī)車,直言燃油時(shí)代已無(wú)長(zhǎng)久!

英國(guó)車手哈蒙德飛赴上海試駕張雪機(jī)車,直言燃油時(shí)代已無(wú)長(zhǎng)久!

林子說(shuō)事
2026-05-07 10:48:53
中美同時(shí)向全球下達(dá)禁令,各國(guó)都傻眼了!美媒:中國(guó)此舉史無(wú)前例

中美同時(shí)向全球下達(dá)禁令,各國(guó)都傻眼了!美媒:中國(guó)此舉史無(wú)前例

桑啟紅原
2026-05-06 05:00:41
“機(jī)車女神”痞幼拿下張雪!評(píng)論區(qū)淪陷了!

“機(jī)車女神”痞幼拿下張雪!評(píng)論區(qū)淪陷了!

4A廣告文案
2026-05-07 09:13:48
俄羅斯尷尬了!5月9日勝利日核心嘉賓拒絕參加!

俄羅斯尷尬了!5月9日勝利日核心嘉賓拒絕參加!

回京歷史夢(mèng)
2026-05-07 12:36:26
東體:內(nèi)地媒體遲遲無(wú)法辦理世界杯簽證,體育版權(quán)定價(jià)應(yīng)回歸理性

東體:內(nèi)地媒體遲遲無(wú)法辦理世界杯簽證,體育版權(quán)定價(jià)應(yīng)回歸理性

懂球帝
2026-05-07 11:16:09
奪冠僅1天,人民日?qǐng)?bào)接連點(diǎn)名吳宜澤,釋放3個(gè)強(qiáng)烈信號(hào),字字珠璣

奪冠僅1天,人民日?qǐng)?bào)接連點(diǎn)名吳宜澤,釋放3個(gè)強(qiáng)烈信號(hào),字字珠璣

尋墨閣
2026-05-06 06:33:51
“臺(tái)獨(dú)”頑固分子劉世芳親屬已被在大陸臺(tái)企解職

“臺(tái)獨(dú)”頑固分子劉世芳親屬已被在大陸臺(tái)企解職

界面新聞
2026-05-06 21:01:54
游戲中的中國(guó)背景永遠(yuǎn)都是臟亂差,“不隨地吐痰”顯得格外刺眼

游戲中的中國(guó)背景永遠(yuǎn)都是臟亂差,“不隨地吐痰”顯得格外刺眼

街機(jī)時(shí)代
2026-05-06 15:00:03
馬克龍說(shuō)已向伊朗提議法英牽頭霍爾木茲海峽護(hù)航行動(dòng)

馬克龍說(shuō)已向伊朗提議法英牽頭霍爾木茲海峽護(hù)航行動(dòng)

新華社
2026-05-07 10:42:05
東北一家五一游蘇州,曬8菜一湯團(tuán)餐引熱議,網(wǎng)友:餓急眼了才吃

東北一家五一游蘇州,曬8菜一湯團(tuán)餐引熱議,網(wǎng)友:餓急眼了才吃

神牛
2026-05-06 09:53:44
高市這一跪,“里外不是人”!

高市這一跪,“里外不是人”!

國(guó)是直通車
2026-05-06 17:38:18
突然發(fā)現(xiàn)一個(gè)殘忍真相:極度自律,每天鍛煉的人,不一定能長(zhǎng)壽,但是,極度自私,不為任何人、任何事操心的人很可能長(zhǎng)壽

突然發(fā)現(xiàn)一個(gè)殘忍真相:極度自律,每天鍛煉的人,不一定能長(zhǎng)壽,但是,極度自私,不為任何人、任何事操心的人很可能長(zhǎng)壽

LULU生活家
2026-05-02 08:35:04
特德·特納逝世

特德·特納逝世

澎湃新聞
2026-05-07 09:56:09
把瑜伽褲穿成日常的松弛感美女

把瑜伽褲穿成日常的松弛感美女

只要高興就好
2026-04-13 14:30:30
2026-05-07 13:15:00
AI前線 incentive-icons
AI前線
面向AI愛(ài)好者、開(kāi)發(fā)者和科學(xué)家,提供AI領(lǐng)域技術(shù)資訊。
1476文章數(shù) 149關(guān)注度
往期回顧 全部

科技要聞

凌晨突發(fā)!馬斯克租22萬(wàn)塊GPU給“死敵”

頭條要聞

北京三位女大學(xué)生青海自駕游2死1傷 傷者一審獲刑4年

頭條要聞

北京三位女大學(xué)生青海自駕游2死1傷 傷者一審獲刑4年

體育要聞

阿森納巴黎會(huì)師歐冠決賽!5月31日開(kāi)戰(zhàn)

娛樂(lè)要聞

小S阿雅重返大S母校,翻看大S畢業(yè)照

財(cái)經(jīng)要聞

特朗普:美伊“很有可能”達(dá)成協(xié)議

汽車要聞

理想為什么不做轎車,有了解釋……

態(tài)度原創(chuàng)

時(shí)尚
數(shù)碼
房產(chǎn)
教育
手機(jī)

“白色闊腿褲”今年夏天又火了!這樣穿時(shí)髦又高級(jí)

數(shù)碼要聞

三星筆記本版Exynos 2800芯片曝光:1.4nm十核CPU

房產(chǎn)要聞

五一海南樓市,太淡了!

教育要聞

推開(kāi)門(mén),世界廣闊!廈門(mén)2026屆初三“二檢”語(yǔ)文作文題出爐

手機(jī)要聞

iPhone Air 2曝光:搭載4800萬(wàn)像素雙攝,明年春季問(wèn)世

無(wú)障礙瀏覽 進(jìn)入關(guān)懷版