iT邦幫忙

2026 iThome 鐵人賽

DAY 25
0
AI Engineering

從零訓練到瀏覽器部署:30 天打造 Atari Breakout 強化學習 AI系列 第 25

Day 25|FP16 真的比較快嗎?模型縮小一半,我最後卻決定不用它

  • 分享至 

  • xImage
  •  

Day 24 我已經確認,這個 Breakout 模型做一次決策其實只需要幾毫秒。

接下來我很好奇另一個很常見的最佳化方法:如果把 FP32 換成 FP16,會不會更快?

直覺上很合理。

FP32 用 32 個位元保存一個浮點數,FP16 只用 16 個位元。數字變小之後,模型檔案通常會縮小,GPU 要處理的資料也比較少,所以很多深度學習工作都會使用 FP16 來加速。

但真正值得問的其實有兩件事:

  1. 模型有沒有真的變快?
  2. 精度降低之後,Agent 的實際表現會不會受到影響?

Day 25 就來實際測這兩件事。


先講結果:模型真的小一半,但速度沒有變快

這次 FP16 最明顯的優點,是模型真的變小很多:

FP32:13,175,034 bytes
FP16: 6,590,582 bytes

大約少了 49.98%

但另外兩個結果就沒有那麼漂亮:

  • 60 個完全相同的遊戲狀態中,FP16 有 4 次選到不同動作
  • batch=1,也就是一次只處理一個遊戲狀態時,FP16 沒有比較快,反而更慢

所以這不是一個「犧牲一點精度,換到很多速度」的故事。

比較像是:

檔案確實小了一半,但我沒有得到真正想要的速度收益。

下面這張圖就是這次實際測量的結果。

Day 25 FP32 與 FP16 的決策、延遲和模型大小比較


為什麼 FP16 可能讓某些動作改變?

Breakout Agent 每次會替四個動作算出分數,也就是 Q-value

可以先把它理解成:

模型估計現在做這個動作,之後大概能拿到多少回報。

最後 Agent 會選 Q-value 最高的動作。

問題在於,有時第一名和第二名非常接近。

例如:

RIGHT = 4.8123
LEFT  = 4.8122

RIGHT 只高一點點。

如果換成 FP16 之後,因為能表示的數字沒有 FP32 那麼細,可能變成:

RIGHT = 4.812
LEFT  = 4.812

甚至兩者順序稍微交換。

這時候最後選到的動作就可能不同。

我把同樣的 60 個遊戲狀態分別交給 FP32 和 FP16,得到:

執行方式 最大 Q-value 差異 最後動作一致率
PyTorch:FP32 vs FP16 0.002798 93.33%
ONNX Runtime:FP32 vs FP16 0.002784 93.33%

也就是說:

60 個固定狀態裡,有 4 個最後真的選到不同動作。

這是一個值得注意的訊號,但它不能單獨告訴我們 FP16 的整體遊戲能力一定比較差。

原因很簡單:強化學習不是只做一次分類,而是不斷和遊戲互動。


為什麼只差一個動作,後面的遊戲就會完全不同?

我也讓 FP32 和 FP16 從相同的遊戲起點開始玩。

只要前面某一步選到不同動作,後面就可能一路分開:

某一步選到不同動作
↓
球和板子的位置開始不同
↓
下一次看到的畫面也不同
↓
之後的決策繼續分岔

這是強化學習很典型的特性。

Agent 的動作會改變環境,而環境又會決定下一步看到什麼。

所以兩個版本只要在前面有一次選擇不同,後面就很難再逐步對照。

Day 25 的 15 局測試確實看到了這種現象:FP16 和 FP32 的遊戲路線很快分岔。

但這個結果比較適合解讀成:

FP16 的數值差異確實足以改變遊戲路線。

至於最後到底「比較會不會玩」,還是要看更多局的分數表現,而不是只看兩條路線有沒有完全一樣。


真正讓我放棄 FP16 的,是它根本沒有比較快

如果 FP16 真的能帶來明顯加速,那事情就值得繼續研究。

但 Day 25 的結果沒有走到這一步,因為 FP16 根本沒有速度優勢。

同一輪測試、一次處理一個遊戲狀態時:

執行方式 FP32 P50 FP16 P50 FP32 P95 FP16 P95
PyTorch 7.917 ms 9.268 ms 8.978 ms 10.690 ms
ONNX Runtime 4.140 ms 5.342 ms 5.541 ms 6.727 ms

P50 可以理解成一般情況下大概多快;P95 則是在看比較慢的那一小段情況。

這一輪裡:

  • PyTorch FP16 的 P95 約慢 19%
  • ONNX Runtime FP16 的 P95 約慢 21%

也就是:

我承擔了額外的數值差異,卻沒有換到速度。

這才是 Day 25 最直接的不採用理由。

另外,Day 25 這組絕對毫秒數不拿來取代 Day 24 的正式速度基準。

兩天執行時的系統狀態不同,絕對延遲有明顯變化;Day 25 真正要看的,是同一輪測試裡 FP32 和 FP16 的相對差異

而方向很清楚:FP16 沒有得到優勢。


為什麼位元變少,反而沒有更快?

因為「FP16 理論上計算量比較省」和「實際一次決策比較快」是兩件不同的事。

這個 Breakout 模型本身不大,而且一次只處理一個狀態。

真正的神經網路計算時間很短,這時候其他額外成本可能就變得很明顯,例如:

  • 資料格式轉換;
  • 把資料送到 GPU;
  • 啟動 GPU 計算;
  • 等待結果回來。

如果原本真正需要計算的工作就不多,FP16 理論上省下來的時間可能還不夠抵掉這些成本。

所以:

FP16 比較省,不代表每一種模型、每一種使用方式都一定比較快。


那模型小一半,還不值得嗎?

如果今天最大的問題是:

  • 下載大小;
  • 儲存空間;
  • 記憶體占用;

那模型小一半當然很有吸引力。

但這個 Breakout 模型原本只有大約 13 MB,檔案大小目前不是主要瓶頸。

相比之下,我更在意的是:

換成 FP16 之後,到底有沒有換到實際速度收益?

Day 25 的答案很清楚:沒有。

既然最期待的收益沒有出現,就沒有必要只為了把模型從 13 MB 壓到 6.6 MB,而額外接受更多數值差異。


今天真正學到的,不是「FP16 不好」

FP16 當然不是沒用。

大型模型、一次處理很多資料,或某些特別適合半精度運算的硬體與工作負載,都可能從 FP16 得到很大的收益。

但這次實驗讓我看到一個更實際的事情:

最佳化不能只看理論,也不能只看模型檔案大小。

「位元變少」可以推出模型會變小,卻不能直接推出:

模型變小
= 一定更快
= 實際表現一定更好

Day 25 真正得到的是:

模型大小      → ✅ 小約 50%
固定狀態決策  → ⚠️ 60 個狀態有 4 個改變
遊戲路線      → ⚠️ 很快分岔
決策速度      → ❌ 沒有變快,反而更慢

所以最後仍然是:

這個模型目前不採用 FP16,繼續保留 FP32。

不是因為 FP16 一定會讓 Agent 變差,而是因為在這個 batch=1 的 Breakout 工作負載裡,它沒有帶來真正的速度收益。


上一篇
Day 24|模型一次決策要多久?我才發現 GPU Benchmark 其實很容易量錯
下一篇
Day 26|TensorRT 真的比較快嗎?RL 部署不能只看「每一步一不一樣」
系列文
從零訓練到瀏覽器部署:30 天打造 Atari Breakout 強化學習 AI27
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言