執行人: Lisa304
專題解說錄影
Booker-Chen
對於 Mistral 1.1B 的實驗中,為什麼調換評估順序之後就可以解決無法產生回應的問題?
yinghuaxia
F16 (FP16) 指的是 16 位 浮點表示。與傳統的 32 位浮點數 (FP32) 相比,它是一種更緊湊的表示方式,允許更快的計算和減少記憶體使用。Q8_0 指的是 8 位元量化權重,模型權重使用 8 位元表示。量化有助於減小模型大小並提高推理速度,同時保持合理的精度。
傳統的浮點數 (FP32) 轉換成 FP16 或 Q8 可以讓計算更快也減少記憶體的使用,同時也保持合理的精度,然而是否在其他地方會有 tradeoff?不然一開始為何不使用這兩種方式呢?
aa860630
在解說影片提到使用 union 來改進浮點數運算的程式碼是有效的,但簡化程式碼後具體得到的好處是什麼呢?
yy214123
下方提到,相較於 llama.cpp,當使用 F16 和 Q8_0 的權重時,可提昇 30%~500% 的指令運算時間,想詢問級距這麼大有什麼原因嗎?
vestata
關於你提到的
Q: 解決了記憶體頻寬問題,不是就不需要進行量化了嗎?這也比較能跟下一句說,本地 LM 不再需要為了速度犧牲知識性能接上,為什麼內文說解決記憶體頻寬問題,會導致量化成為瓶頸呢?
這邊的瓶頸會是指對困惑度的表現嗎?
閱讀 LLaMA Now Goes Faster on CPUs 並紀錄問題,定位出效能瓶頸
聚焦上方任務,不要張貼不直接相關的材料。
老師,那個是你之前給的第一個 TODO,實作 IEEE 754乘法程式碼,還是就不貼了
詳見上方描述。
重現相關實驗
作者為 llamafile 開發了 84 new matrix multiplication kernels,旨在顯著提高在各類型的 CPU 上讀取提示/圖像的速度。在 CPU 上使用 F16 和 Q8_0 的權重時,相較於 llama.cpp,在指令計算時間上將提升 30%~500% 的速度。
bit 是「位元」,而非「位」,後者是量詞。
務必使用課程規範的詞彙,和閱讀相關說明。
F16 (FP16) 指的是 16 位 浮點表示。與傳統的 32 位浮點數 (FP32) 相比,它是一種更緊湊的表示方式,允許更快的計算和減少記憶體使用。Q8_0 指的是 8 位元量化權重,模型權重使用 8 位元表示。量化有助於減小模型大小並提高推理速度,同時保持合理的精度。
模型量化(quantization)是將模型從原本高精度資料格式轉換為低精度格式儲存的一種模型最佳化(model optimization)手段。目前在電腦上訓練模型時使用的資料格式多為 32 位元單精度浮點數(32-bit single-precision floating-point, FP32),訓練完畢後經過模型量化轉換為 8 位元整數(8-bit integer, INT8)格式儲存。
量化主要包含兩個步驟:
- 選定準備進行量化的實數範圍(FP32),範圍外的數字 clip 到上限或下限;
- 將實數對應到低位元代表的整數(INT8)。
引用權威材料來說明模型量化。
The improvements are most dramatic for ARMv8.2+ (e.g. RPI 5), Intel (e.g. Alderlake), and AVX512 (e.g. Zen 4) computers.
注意用語:
不要誤用。
作者的核心 使用 Level 2 Cache 時比 MKL(Math Kernel Library) 快兩倍,如果任務是少於 1000 個 token 的話,能提供可觀的加速。
Background
注意用語:
llamafile 是作者在 2023.11 在 Mozilla 啟動的本地 LLM 專案。他們使用 Cosmopolitan Libc 來把 llama.cpp 打包成單檔跨平台二進制文件 ,可在 AMD64(x86-64) 和 ARM64 的六種作業系統上運行,同時對其進行少量修改。
llamafile 和 Cosmopolitan Libc 都是由 Mozilla 贊助作者的。
聚焦在我們要解決的 LLaMA 推論議題上面。
Performance Gains on Enterprise Hardware
HP Intel® Core™ i9-9900 ($439) w/ 2200 MT/s RAM c. 2020
via, through 不該翻譯為「通過」,否則無法區分 pass
引入了 mmap()
支持,這使得權重加載變得即時,並且內存 佔用減少了一半,但對於評估速度的提升幫助不大。後來作者通過 優化內核 ,實現 了更大的性能提升,特別是在特定數據類型(如 q8_0 和 f16)上。
注意用語!
改進你的漢語表達。
在這裡,我們看到在 Skylake 平台上(硬體部分),軟體部分 llamafile 的用戶可以期待看到 2 倍的速度提升,而 llama.cpp 用戶則可以期待性能提升 50%,表格中同樣是權重 4 量化格式的時候,根據軟體部分個更改,指令處理速度從 12 上升到 28。
不要濫用「優化」,詳見: https://hackmd.io/@sysprog/it-vocabulary
但是這只適用於某些權重。到目前為止,作者只為 q8_0、f16、q4_1、q4_0 和 f32 這些數據類型編寫了優化 的內核。認為 q8_0 和 f16 是非常穩健的選擇,他們在參數量提升的同時,指令處理速度竟然也有提升 205 和 171。如果你有足夠的內存 ,可能 f32 也不錯。
prompt tok/sec | eval tok/sec | model | weights data type | software |
---|---|---|---|---|
28 | 7 | Mistral 7b | q4_0 | llamafile-0.7 |
17 | 7 | Mistral 7b | q4_0 | llama.cpp 2024-03-26 |
12 | 7 | Mistral 7b | q4_0 | llamafile-0.6.2 |
32 | 4 | Mistral 7b | q8_0 | llamafile-0.7 |
23 | 2 | Mistral 7b | f16 | llamafile-0.7 |
205 | 26 | TinyLlama 1.1B | q8_0 | llamafile-0.7 |
171 | 15 | TinyLlama 1.1B | f16 | llamafile-0.7 |
That's because my new kernels change the rules. They're doing such a good job fixing the memory bandwidth quants always solved, that quantization could become the bigger bottleck.That would be great news for the future of local language models, since it means less need to trade away knowledge for speed.
作者的新方法能夠解決 memory bandwidth quants 的問題,但是在量化上是一個更大的瓶頸。這對於本地語言模型的未來是個好消息,因為這意味著減少了為了速度而犧牲知識的必要性。
memory bandwidth quants 內存帶寬 問題指的是處理器從內存中讀取或向內存寫入數據的速度受限,內存帶寬不足可能導致處理器等待數據的時間增加,對於 LLM 頻繁訪問 大量數據時,此問題會很明顯。
注意用語:
在語言模型中,量化是一種常見技術,用於減少模型的內存和計算需求。量化通過將浮點數據轉換為較低精度的數據格式(如 8 位或 4 位)來實現。儘管這可以顯著減少模型的內存佔用和計算負擔,但也可能導致模型性能下降,即犧牲了一部分模型的“知識性”,因為量化過程中可能會丟失一些細節信息。
注意用語!
Q: 解決了內存帶寬問題,不是就不需要進行量化了嗎?這也比較能跟下一句說,本地 LM 不再需要為了速度犧牲知識性能接上,為什麼內文說解決內存帶寬問題,會導致量化成為瓶頸呢?
Performance Gains on Hobbyist Hardware
$100 Raspberry Pi v5 (ARMv8.2) and v4 (ARMv8.0)
Raspberry Pi 是當今商店中最好的個人電腦之一。它們以優惠的價格提供良好的性能,並且功耗極低。
表格是 100 美元的 Raspberry Pi v5 (ARMv8.2) 和 v4 (ARMv8.0) 上的表現:
prompt tok/sec | eval tok/sec | model | weights data type | hardware | software |
---|---|---|---|---|---|
62 | 5 | TinyLlama 1.1B | f16 | RPI5 | llamafile-0.7 |
45 | 9 | TinyLlama 1.1B | q8_0 | RPI5 | llamafile-0.7 |
10 | 3 | TinyLlama 1.1B | q8_0 | RPI4 | llamafile-0.7 |
3 | 2 | TinyLlama 1.1B | f16 | RPI4 | llamafile-0.7 |
Raspberry Pi 幾個月前發布了他們的第五代產品,相較於之前的型號速度快得令人難以置信。他們還引入了對 ARMv8.2 dotprod 和 fp16 算術 ISA(指令集架構)的支持,這對於大規模語言模型(LLM)非常有用。僅這兩個特性就讓 llama.cpp 在去年針對 f16 權重達成 10 倍的性能提升。
不該使用機器翻譯,用你對文章的認知,重新書寫。
本週我在此基礎上又實現了額外的 2 倍性能提升,所以總共是提升了二十倍(3 => 62),使用的是原本打算用於 AVX512 (指令擴展集,從 256-bit 擴展到 512-bit)的內核 。強大的數據中心 設備設計的內核能在微小的 Raspberry Pi 上工作,因為兩者的 CPU 都有 32 個向量寄存器 (32 vector registers)。
注意用語!
新 ARMv8.2 fp16 ISA 可能會引入更多的誤差,因為它使得 llamafile 使用 fp16 字 (fp16 words),並且我們沒有使用 Kahan 求和來計算點積。fp16(16 位浮點數)因為精度較低,容易在累加大量數據時產生較大的數值誤差。
Kahan 求和演算法,又稱為補償求和或進位求和演算法,是一個用來降低有限精度浮點數序列累加值誤差的演算法。
在電腦程式中,我們需要用有限位數對實數做近似表示,如今的大多數電腦都使用 IEEE-754 規定的浮點數來作為這個近似表示。對於 ,由於我們無法在有限位數內對它進行精準表示,因此在使用 IEEE-754 表示法時,必須四捨五入一部分數值(truncate)。這種舍入誤差(Rounding off error)是浮點計算的特徵。
使用課程指定的程式碼縮排風格。
因此,Q8_0 (8位整數量化)權重實際上會有略好一些的困惑度,因為它使用的是 dotprod ISA,這使我們能將有符號的 8 位整數升到 32 位的計算類型,從而吸收誤差。這意味著在某些情況下,使用 Q8_0 權重可以得到比 fp16 權重更準確的結果。然而,這並不意味著更快的 fp16 權重不能有用。許多這個領域的開發者認為這些差異是微不足道的。
你如何驗證上面陳述是否有效?
建立數學模型,探討量化過程中的誤差議題。拿出你的數理素養出來,避免人云亦云。
例如,假設在 pihole 上設置一個郵件伺服器並讓 TinyLLaMA 過濾垃圾郵件。可以配置 Postfix 來使用 shell 腳本來過濾內容,透過運行 llamafile 命令,詳細的內容請看原文 hobbyist 段落。
Performance Gains on Gaming Hardware
Intel® Core™ i9-14900K ($530) w/ 6400 MT/s RAM
prompt tok/sec | eval tok/sec | model | weights data type | hardware | software |
---|---|---|---|---|---|
406 | 67 | TinyLlama 1.1B | q8_0 | Alderlake | llamafile-0.7 |
407 | 42 | TinyLlama 1.1B | f16 | Alderlake | llamafile-0.7 |
Performance Gains on Apple Hardware
Mac Studio CPU w/ 24-core M2 Ultra ($5000)
prompt tok/sec | eval tok/sec | model | weights data type | hardware | software |
---|---|---|---|---|---|
419 | 66 | TinyLlama 1.1B | q8_0 | M2 Ultra | llamafile-0.7 |
457 | 95 | TinyLlama 1.1B | f16 | M2 Ultra | llamafile-0.7 |
Performance Gains on Professional Hardware
AMD Ryzen Threadripper PRO 7995WX w/ 96 cores ($10,000)
prompt tok/sec | eval tok/sec | model | weights data type | hardware | software |
---|---|---|---|---|---|
1268 | 60 | TinyLlama 1.1B | q8_0 | 7995WX | llamafile-0.7 |
1819 | 52 | TinyLlama 1.1B | f16 | M7995WX | llamafile-0.7 |
在 Intel 軟體方面都是較新版本的 llamafile-0.7(發布在 03-31) 表現較好,對於 Mac(108) 在 llama.cpp 2024-03-26 表現最好,而 7995WX(93) 在 llamafile-0.6.2 表現得最好,三種硬體的最佳表現不是都發生在最新版本,會是因為什麼原因?
How I Improved Prompt Eval Time on CPUs
矩陣乘法是 transformer 模型中的基礎運算之一,通常消耗大量的計算資源。作者研究各種實作方式,做性能優化,並探索不同實現中的權衡。
How I Got Multiple Threads to Work
確保矩陣乘法的高效計算,同時與 Llama.cpp 的線程模型兼容,避免了傳統 BLAS 庫帶來的延遲問題。
注意用語:
在 Linux 上執行以下命令才能可靠地對 llamafile 進行基準測試。
作者有像 BLIS 那樣用彙編語言 編寫內核,配置了 Emacs 可以把組合語言直接反編譯成 C++ 程式碼。
重現實驗、量化分析
Intel® Xeon® CPU E5-2650 v4 @ 2.20GHz
Launch Date | Total Cores | Max Turbo Frequency | Processor Base Frequency | Cache | TDP |
---|---|---|---|---|---|
Q1'16 | 12 | 2.90 GHz | 2.20 GHz | 30 MB Intel® Smart Cache | 105 W |
./llava-v1.5-7b-q4.llamafile
的畫面:
./llamafile.exe -m mistral.gguf -ngl 99
Quantization type | description |
---|---|
Q4_0 | 4-bit round-to-nearest quantization (q). Each block has 32 weights. |
Q4_K | 4-bit quantization(q). Super-blocks with 8 blocks, each block has 32 weights. |
Q8_0 | 8-bit round-to-nearest quantization (q). Each block has 32 weights. |
F16 (FP16) | 16-bit standard IEEE 754 half-precision floating-point number. |
conda create -n linuxLLama python=3.8
conda activate linuxLLama
對於 Mistral 7B 的實驗
weights data type | creater |
---|---|
q4_0 | TheBloke/Mistral-7B-v0.1-GGUF |
q8_0 | TheBloke/Mistral-7B-v0.1-GGUF |
fp_16 | Undi95/Mistral-RP-0.1-7B-GGUF |
Mistral 7B llamafile 實驗結果:
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
22.03 | 5.99 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
25.04 | 5.42 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
13.25 | 2.89 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | llamafile |
31.85 | 7.10 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
38.20 | 6.77 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
30.75 | 3.02 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
實驗觀察
eval
會隨著權重增加而下降,跟原本實驗的觀察相符。
關於額外的斷詞實驗,由於 Mistral 模型的斷詞方式會加入許多特殊字元,例如 "hi im Lisa" 會被轉換成 '</s>▁[INST]▁hi▁im▁Lisa▁[/INST]'
,長度為 11,這使得 eval
的結果可能高於使用 LlamaFile 斷詞的情況。
對於 Mistral 1.1B 的實驗
然而,在發送跟先前 7B 大小模型的相同請求時,發現了模型完全不產生回應的情況。即使嘗試將 n_predict 數值調高,或加入 minkeep 參數,模型仍然無法生成回應。因此,我決定調換評估順序,並在 prompt 中輸入文字。
關於 prompt/tok 的計算方法並沒有更改,但是在 eval/tok 函數上做了一些調整:
weights data type | creater |
---|---|
q4_k | afrideva/malaysian-mistral-1.1B-4096-GGUF |
q8_0 | afrideva/malaysian-mistral-1.1B-4096-GGUF |
fp_16 | afrideva/malaysian-mistral-1.1B-4096-GGUF |
Mistral 1.1B llamafile 實驗結果:
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
100.64 | 35.05 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llamafile-0.8 | llamafile |
158.68 | 29.26 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
129.98 | 8.74 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | llamafile |
138.14 | 32.26 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
185.32 | 24.89 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
130.87 | 11.25 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | Mistral Common |
評估過程記錄
我發現 llama.cpp 的伺服器 API 與 llamafile 完全相容,最初計劃直接使用相同的程式碼來進行效能評估。
以下是基於 llama.cpp 伺服器 API 和原本 Mistral 模型所使用的斷詞器的兩種斷詞方法所得到的輸出結果:
Mistral 1.1B llama.cpp 實驗結果:
使用兩種斷詞方法的比較實驗:
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
169.21 | 33.68 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
154.77 | 22.68 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
132.90 | 13.84 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
218.59 | 36.09 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
202.57 | 23.57 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
214.27 | 14.15 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
Mistral 7B llama.cpp 實驗結果:
使用兩種斷詞方法的比較實驗:
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
21.38 | 5.66 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
21.51 | 3.78 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
14.80 | 2.19 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
35.61 | 6.03 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
35.32 | 4.15 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
22.58 | 2.37 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | Mistral Common |
關於兩種軟體的實作實驗,通過實驗數據我們可以得出以下結論:
先前是不同斷詞方式的對照實驗,再來進入到兩種軟體的對照實驗:
Mistral 7b 兩種軟體對照結果表格
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
22.03 | 5.99 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
21.38 | 5.66 | Mistral 7B v0.1 | q4_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
25.04 | 5.42 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
21.51 | 3.78 | Mistral 7B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
13.25 | 2.89 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | llamafile |
14.80 | 2.19 | Mistral 7B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
Mistral 1.1B 兩種軟體對照結果表格
prompt (tok/sec) | eval (tok/sec) | model | weights data type | hardware | software | tokenizer |
---|---|---|---|---|---|---|
100.64 | 35.05 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llamafile-0.8 | llamafile |
169.21 | 33.68 | Mistral 1.1B v0.1 | q4_k | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
158.68 | 29.26 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llamafile-0.8 | llamafile |
154.77 | 22.68 | Mistral 1.1B v0.1 | q8_0 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
143.88 | 21.87 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llamafile-0.8 | llamafile |
132.90 | 13.84 | Mistral 1.1B v0.1 | fp_16 | Products formerly Broadwell | llama.cpp 2024-6-19 | llamafile |
上下測試模型皆為 Mistral,只是上方參數大小為 7B,而下方為 1.1B。
第一個實驗 Mistral 7B v0.1:
第二個實驗 Mistral 1.1B v0.1:
開發紀錄務必依據以下: