<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>BF16 on KnightLi的博客</title>
        <link>https://www.knightli.com/zh-tw/tags/bf16/</link>
        <description>Recent content in BF16 on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-tw</language>
        <lastBuildDate>Wed, 22 Apr 2026 22:40:00 +0800</lastBuildDate><atom:link href="https://www.knightli.com/zh-tw/tags/bf16/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>大模型常見張量類型入門：FP32、FP16、BF16、TF32 與 FP8</title>
        <link>https://www.knightli.com/zh-tw/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/</link>
        <pubDate>Wed, 22 Apr 2026 22:40:00 +0800</pubDate>
        
        <guid>https://www.knightli.com/zh-tw/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/</guid>
        <description>&lt;p&gt;只要你開始接觸大模型訓練、推理或部署，很快就會遇到一組高頻縮寫：&lt;code&gt;FP32&lt;/code&gt;、&lt;code&gt;FP16&lt;/code&gt;、&lt;code&gt;BF16&lt;/code&gt;、&lt;code&gt;TF32&lt;/code&gt;、&lt;code&gt;FP8&lt;/code&gt;。它們看起來像是模型頁面上的幾個附加標籤，但實際影響遠不只是「寫法不同」。&lt;/p&gt;
&lt;p&gt;這些類型決定了數字在顯存裡怎麼存、在計算中怎麼表示，也直接影響模型訓練是否穩定、推理速度如何，以及一張顯示卡到底能裝下多大的模型。&lt;/p&gt;
&lt;p&gt;所以如果你想真正理解大模型裡的精度取捨，最值得先補的一課，不是某個具體模型的跑分，而是先把這些常見張量類型各自是什麼、為什麼會這樣設計搞清楚。&lt;/p&gt;
&lt;h2 id=&#34;張量類型到底在決定什麼&#34;&gt;張量類型到底在決定什麼
&lt;/h2&gt;&lt;p&gt;大模型本質上是海量參數參與的矩陣運算，而張量類型就是這些數字在顯存裡如何存、在計算中如何表示。&lt;/p&gt;
&lt;p&gt;它的核心取捨通常圍繞三個維度展開：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;精度&lt;/li&gt;
&lt;li&gt;顯存占用&lt;/li&gt;
&lt;li&gt;計算速度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這和圖片格式其實很像。無損格式保留細節更多，但體積大、載入慢；壓縮格式會丟掉一部分人眼不敏感的資訊，換來更小的體積與更快的處理速度。大模型之所以能接受這種取捨，是因為在極大量參數裡，很多微小數值變化並不會明顯影響最終輸出。&lt;/p&gt;
&lt;p&gt;也正因如此，模型世界裡才會出現一整套不同精度的張量格式。&lt;/p&gt;
&lt;h2 id=&#34;一個數字是怎麼被表示的&#34;&gt;一個數字是怎麼被表示的
&lt;/h2&gt;&lt;p&gt;理解這些格式之前，可以先記住一個非常基礎的結構。一個浮點數通常由三部分組成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;符號位：決定正負&lt;/li&gt;
&lt;li&gt;指數位：決定數值範圍&lt;/li&gt;
&lt;li&gt;尾數位：決定數值精細程度&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在大模型裡，尾數精度當然重要，但很多時候模型更怕的是數值範圍不夠，也就是指數位太小，導致溢出或訓練不穩定。很多張量格式的設計，本質上就是在「範圍」與「細節」之間重新分配有限的 bit 數。&lt;/p&gt;
&lt;p&gt;下面這張圖可以先幫你建立一個整體印象：&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/tensor-format-overview.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;FP32、FP16、BF16、TF32 與 FP8 的位寬結構總覽&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;fp32最穩但最貴&#34;&gt;FP32：最穩，但最貴
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;FP32&lt;/code&gt; 是最傳統的單精度浮點格式，總共 32 bit，也就是 4 個位元組。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/fp32-layout.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;FP32 位寬結構示意圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;它的優點很直接：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;數值範圍大&lt;/li&gt;
&lt;li&gt;精度高&lt;/li&gt;
&lt;li&gt;訓練最穩&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但問題也同樣明顯：太占顯存。&lt;/p&gt;
&lt;p&gt;一個非常粗略的估算方式是：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;顯存占用 ≈ 參數量 × 每個參數的位元組數
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果一個 27B 模型完全用 &lt;code&gt;FP32&lt;/code&gt; 存權重，那麼光權重本身就大約需要：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;27B × 4 bytes ≈ 108GB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這還沒算激活值、KV Cache、優化器狀態與其他執行期開銷。也就是說，&lt;code&gt;FP32&lt;/code&gt; 在今天的大模型推理與訓練裡，已經不是「預設選擇」，而更像是「最穩的基線格式」。&lt;/p&gt;
&lt;h2 id=&#34;fp16體積減半但穩定性一般&#34;&gt;FP16：體積減半，但穩定性一般
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;FP16&lt;/code&gt; 把每個參數壓縮到 2 個位元組，顯存占用相較 &lt;code&gt;FP32&lt;/code&gt; 直接減半。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/fp16-layout.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;FP16 位寬結構示意圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;對同一個 27B 模型來說，如果只看權重體積：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;27B × 2 bytes ≈ 54GB
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;這就已經能解釋為什麼很多部署說明裡，27B 模型的顯存需求會落在 50GB 左右。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FP16&lt;/code&gt; 的優勢很明顯：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顯存壓力大幅下降&lt;/li&gt;
&lt;li&gt;吞吐更高&lt;/li&gt;
&lt;li&gt;早期混合精度訓練大量使用&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;但它的問題在於指數位偏小，動態範圍不夠大。對大模型訓練來說，這會讓溢出更容易發生，需要額外依賴 loss scaling 一類技巧來補救，工程上比較麻煩。&lt;/p&gt;
&lt;p&gt;所以現在 &lt;code&gt;FP16&lt;/code&gt; 仍然常見，但在很多場景裡，它已經不再是最舒服的選擇。&lt;/p&gt;
&lt;h2 id=&#34;bf16大模型時代更實用的半精度&#34;&gt;BF16：大模型時代更實用的半精度
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;BF16&lt;/code&gt; 同樣只占 2 個位元組，但和 &lt;code&gt;FP16&lt;/code&gt; 的設計重點不一樣。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/bf16-layout.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;BF16 位寬結構示意圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;它保留了更大的指數範圍，讓它在動態範圍上更接近 &lt;code&gt;FP32&lt;/code&gt;，只是犧牲了一部分尾數精度。這種取捨對大模型尤其友好，因為很多時候模型對「範圍」更敏感，對尾數少幾位反而沒那麼敏感。&lt;/p&gt;
&lt;p&gt;這也是為什麼現在很多訓練框架、很多大模型論文與大量實際部署方案，都更偏向 &lt;code&gt;BF16&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;你可以把它理解成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顯存成本接近 &lt;code&gt;FP16&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;穩定性體驗更接近 &lt;code&gt;FP32&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;如果一套 27B 部署方案寫的是 50GB 左右顯存，而另一套經過進一步優化後接近 30GB，前者往往還停留在 &lt;code&gt;FP16/BF16&lt;/code&gt; 這一層，後者則通常已經繼續往更低精度或量化方向走了。&lt;/p&gt;
&lt;h2 id=&#34;tf32不是省顯存而是加速-fp32-工作流&#34;&gt;TF32：不是省顯存，而是加速 FP32 工作流
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;TF32&lt;/code&gt; 很容易被誤會成「又一種更省的格式」，但它的定位其實不太一樣。&lt;/p&gt;
&lt;p&gt;從常見理解上看，它可以近似視為一種保留較大指數範圍、但縮短尾數精度的計算格式。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/tf32-layout.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;TF32 計算格式示意圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;不過要注意，&lt;code&gt;TF32&lt;/code&gt; 更像是一條 Tensor Core 計算路徑裡的內部計算格式，而不是像 &lt;code&gt;FP16/BF16&lt;/code&gt; 那樣主要拿來做權重存儲。&lt;/p&gt;
&lt;p&gt;它主要是 NVIDIA 在較新的 GPU 上提供的一種計算模式，目標不是減少顯存占用，而是讓原本基於 &lt;code&gt;FP32&lt;/code&gt; 的訓練流程，在盡量不大改程式碼的前提下跑得更快。&lt;/p&gt;
&lt;p&gt;它的特點可以概括成一句話：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;對外看起來還是 &lt;code&gt;FP32&lt;/code&gt; 工作流&lt;/li&gt;
&lt;li&gt;底層在矩陣乘法時做了更快的近似計算&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以 &lt;code&gt;TF32&lt;/code&gt; 主要解決的是「&lt;code&gt;FP32&lt;/code&gt; 太慢」的問題，而不是「&lt;code&gt;FP32&lt;/code&gt; 太占顯存」的問題。如果你關心的是為什麼同一個模型部署時顯存需求不一樣，&lt;code&gt;TF32&lt;/code&gt; 不是最主要的答案。&lt;/p&gt;
&lt;h2 id=&#34;fp8進一步壓縮但更考驗工程能力&#34;&gt;FP8：進一步壓縮，但更考驗工程能力
&lt;/h2&gt;&lt;p&gt;再往下走就是 &lt;code&gt;FP8&lt;/code&gt;。它把單個數值繼續壓縮到更少 bit 數，進一步降低顯存頻寬與存儲成本。&lt;/p&gt;
&lt;p&gt;它常見的不是單一一種格式，而是兩類變體：&lt;code&gt;E4M3&lt;/code&gt; 和 &lt;code&gt;E5M2&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/fp8-layout.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;FP8 兩種常見變體示意圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;但 &lt;code&gt;FP8&lt;/code&gt; 的代價也很明顯：位數太少以後，你很難同時兼顧範圍和精度，因此實際工程裡通常會針對不同階段採用不同變體，分別照顧前向、反向與梯度的穩定性。&lt;/p&gt;
&lt;p&gt;這類格式代表的是一種更激進的思路：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;願意犧牲更多精度&lt;/li&gt;
&lt;li&gt;換取更低的存儲與更高的吞吐&lt;/li&gt;
&lt;li&gt;需要更成熟的硬體與訓練框架配合&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;它很有前景，但對一般使用者來說，日常最常碰到的核心分界點，通常還是 &lt;code&gt;FP32&lt;/code&gt;、&lt;code&gt;FP16&lt;/code&gt; 和 &lt;code&gt;BF16&lt;/code&gt;。&lt;/p&gt;
&lt;h2 id=&#34;為什麼理解這些類型很重要&#34;&gt;為什麼理解這些類型很重要
&lt;/h2&gt;&lt;p&gt;很多人第一次看到這些縮寫，會把它們理解成「模型下載頁上的一些實作細節」。但實際上，它們會直接改變你對模型訓練與部署的理解方式。&lt;/p&gt;
&lt;p&gt;例如同樣一張顯示卡：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;為什麼有些模型訓練必須強調數值穩定性&lt;/li&gt;
&lt;li&gt;為什麼有些推理方案會優先談量化與低精度&lt;/li&gt;
&lt;li&gt;為什麼看起來參數量相近的模型，部署門檻卻差很多&lt;/li&gt;
&lt;li&gt;為什麼有些格式適合存權重，有些格式更適合做計算路徑&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;這些問題往下拆，最後幾乎都會回到同一個核心：你到底怎麼在「精度、範圍、顯存和速度」之間做取捨。&lt;/p&gt;
&lt;p&gt;也正因如此，理解 &lt;code&gt;FP32&lt;/code&gt;、&lt;code&gt;FP16&lt;/code&gt;、&lt;code&gt;BF16&lt;/code&gt;、&lt;code&gt;TF32&lt;/code&gt; 和 &lt;code&gt;FP8&lt;/code&gt;，不只是為了看懂術語表，而是為了在面對訓練配置、推理引擎與部署門檻時，知道這些數字背後到底在交換什麼。&lt;/p&gt;
&lt;h2 id=&#34;一個實用的理解框架&#34;&gt;一個實用的理解框架
&lt;/h2&gt;&lt;p&gt;如果你不想一開始就記一堆格式細節，可以先用下面這個順序理解：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FP32&lt;/code&gt;：最穩、最貴&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FP16&lt;/code&gt;：更省顯存，但範圍偏小&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BF16&lt;/code&gt;：顯存接近 &lt;code&gt;FP16&lt;/code&gt;，穩定性更適合大模型&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TF32&lt;/code&gt;：主要解決 &lt;code&gt;FP32&lt;/code&gt; 太慢，不主要解決顯存&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FP8&lt;/code&gt;：更激進的壓縮與加速路線&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;https://www.knightli.com/2026/04/22/common-tensor-formats-fp32-fp16-bf16-tf32-fp8/tensor-format-summary.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;常見張量類型總結圖&#34;
	
	
&gt;&lt;/p&gt;
&lt;p&gt;當你以後再看到模型下載頁裡寫著 &lt;code&gt;fp16&lt;/code&gt;、&lt;code&gt;bf16&lt;/code&gt;、&lt;code&gt;fp8&lt;/code&gt;，或者看到不同部署教學給出完全不一樣的顯存門檻時，就不會再覺得那只是「寫法不同」。它們背後其實對應的是完全不同的精度預算與工程取捨。&lt;/p&gt;
&lt;h2 id=&#34;結語&#34;&gt;結語
&lt;/h2&gt;&lt;p&gt;大模型裡的張量類型，表面上是在討論 bit 數，實際上討論的是一整套工程取捨。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;FP32&lt;/code&gt;、&lt;code&gt;FP16&lt;/code&gt;、&lt;code&gt;BF16&lt;/code&gt;、&lt;code&gt;TF32&lt;/code&gt; 和 &lt;code&gt;FP8&lt;/code&gt; 沒有絕對的好壞，它們只是分別站在不同的位置上，幫你在穩定性、範圍、精度、顯存和速度之間做平衡。&lt;/p&gt;
&lt;p&gt;如果把這一層看懂，後面無論你是在讀訓練論文、調推理參數，還是比較不同部署方案，都會更容易抓住重點。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
