編者按:
隻需不到 9 行代碼,就能在 CPU 上實現出色的 LLM 推理性能。英特爾 ® Extension for Transformer 創新工具包中的 LLM Runtime 爲諸多模型顯著降低時延,且首個 token 和下一個 token 的推理速度分别提升多達 40 倍和 2.68 倍,還能滿足更多場景應用需求。
英特爾 ® Extension for Transformer 是什麽?
英特爾 ® Extension for Transformers [ 1 ] 是英特爾推出的一個創新工具包,可基于英特爾 ® 架構平台,尤其是第四代英特爾 ® 至強 ® 可擴展處理器(代号 Sapphire Rapids [ 2 ] ,SPR)顯著加速基于 Transformer 的大語言模型 ( Large Language Model,LLM ) 。其主要特性包括:
通過擴展 Hugging Face transformers API [ 3 ] 和利用英特爾 ® Neural Compressor [ 4 ] ,爲用戶提供無縫的模型壓縮體驗;
提供采用低位量化内核(NeurIPS 2023:在 CPU 上實現高效 LLM 推理 [ 5 ] )的 LLM 推理運行時,支持 Falcon、LLaMA、MPT、Llama2、 BLOOM、OPT、ChatGLM2、GPT-J-6B、Baichuan-13B-Base、Baichuan2-13B-Base、Qwen-7B、Qwen-14B 和 Dolly-v2-3B 等常見的 LLM [ 6 ] ;
先進的壓縮感知運行時 [ 7 ] (NeurIPS 2022:在 CPU 上實現快速蒸餾和 QuaLA-MiniLM:量化長度自适應 MiniLM;NeurIPS 2021:一次剪枝,一勞永逸:對預訓練語言模型進行稀疏 / 剪枝)。
本文将重點介紹其中的 LLM 推理運行時(簡稱爲 "LLM 運行時 "),以及如何利用基于 Transformer 的 API 在英特爾 ® 至強 ® 可擴展處理器上實現更高效的 LLM 推理和如何應對 LLM 在聊天場景中的應用難題。
LLM 運行時 ( LLM Runtime )
英特爾 ® Extension for Transformers 提供的 LLM Runtime [ 8 ] 是一種輕量級但高效的 LLM 推理運行時,其靈感源于 GGML [ 9 ] ,且與 llama.cpp [ 10 ] 兼容,具有如下特性:
内核已針對英特爾 ® 至強 ® CPU 内置的多種 AI 加速技術(如 AMX、VNNI)以及 AVX512F 和 AVX2 指令集進行了優化;
可提供更多量化選擇,例如:不同的粒度(按通道或按組)、不同的組大小(如:32/128);
擁有更優的 KV 緩存訪問以及内存分配策略;
具備張量并行化功能,可助力在多路系統中進行分布式推理。
LLM Runtime 的簡化架構圖如下:
△圖 1. 英特爾 ® Extension for Transformers 的 LLM Runtime 簡化架構圖使用基于 Transformer 的 API,在 CPU 上實現 LLM 高效推理
隻需不到 9 行代碼,即可讓您在 CPU 上實現更出色的 LLM 推理性能。用戶可以輕松地啓用與 Transformer 類似的 API 來進行量化和推理。隻需将 ‘ load_in_4bit ’設爲 true,然後從 HuggingFace URL 或本地路徑輸入模型即可。下方提供了啓用僅限權重的 ( weight-only ) INT4 量化的示例代碼:
from transformers import AutoTokenizer, TextStreamer
from intel_extension_for_transformers.transformers import AutoModelForCausalLM
model_name = "Intel/neural-chat-7b-v3-1"
prompt = "Once upon a time, there existed a little girl,"
tokenizer = AutoTokenizer.from_pretrained ( model_name, trust_remote_code=True )
inputs = tokenizer ( prompt, return_tensors="
pt" ) .input_ids
streamer = TextStreamer ( tokenizer )
model = AutoModelForCausalLM.from_pretrained ( model_name, load_in_4bit=True )
outputs = model.generate ( inputs, streamer=streamer, max_new_tokens=300 )
△可左滑看完整版
默認設置爲:将權重存儲爲 4 位,以 8 位進行計算。但也支持不同計算數據類型 ( dtype ) 和權重數據類型組合,用戶可以按需修改設置。下方提供了如何使用這一功能的示例代碼:
from transformers import AutoTokenizer, TextStreamer
from intel_extension_for_transformers.transformers import AutoModelForCausalLM, WeightOnlyQuantConfig
model_name = "Intel/neural-chat-7b-v3-1"
prompt = "Once upon a time, there existed a little girl,"
woq_config = WeightOnlyQuantConfig ( compute_dtype="
int8", weight_dtype="int4" )
tokenizer = AutoTokenizer.from_pretrained ( model_name, trust_remote_code=True )
inputs = tokenizer ( prompt, return_tensors="pt" ) .input_ids
streamer = TextStreamer ( tokenizer )
model = AutoModelForCausalLM.from_pretrained ( model_name,quantization_config=woq_config )
outputs = model.generate ( inputs, streamer=streamer, max_new_tokens=300 )
△可左滑看完整版性能測試
經過持續努力,上述優化方案的 INT4 性能得到了顯著提升。本文在搭載英特爾 ® 至強 ® 鉑金 8480+ 的系統上與 llama.cpp 進行了性能比較;系統配置詳情如下:@3.8GHz,56 核 / 路,啓用超線程,啓用睿頻,總内存 256 GB ( 16 x 16 GB DDR5 4800 MT/s [ 4800 MT/s ] ) ,BIOS 3A14.TEL2P1,微代碼 0x2b0001b0,CentOS Stream 8。
當輸入大小爲 32、輸出大小爲 32、beam 爲 1 時的推理性能測試結果,詳見下表:
△表 1.LLM Runtime 與 llama.cpp 推理性能比較(輸入大小 =32,輸出大小 =32,beam=1)
輸入大小爲 1024、輸出大小爲 32、beam 爲 1 時的推理性能的測試結果,詳見下表:
△表 2.LLM Runtime 與 llama.cpp 推理性能比較(輸入大小 =1024,輸出大小 =32,beam=1)
根據上表 2 可見:與同樣運行在第四代英特爾 ® 至強 ® 可擴展處理器上的 llama.cpp 相比,無論是首個 token 還是下一個 token,LLM Runtime 都能顯著降低時延,且首個 token 和下一個 token 的推理速度分别提升多達 40 倍 [ a ] (Baichuan-13B,輸入爲 1024)和 2.68 倍 [ b ] (MPT-7B,輸入爲 1024)。llama.cpp 的測試采用的是默認代碼庫 [ 10 ] 。
而綜合表 1 和表 2 的測試結果,可得:與同樣運行在第四代英特爾 ® 至強 ® 可擴展處理器上的 llama.cpp 相比,LLM Runtime 能顯著提升諸多常見 LLM 的整體性能:在輸入大小爲 1024 時,實現 3.58 到 21.5 倍的提升;在輸入大小爲 32 時,實現 1.76 到 3.43 倍的提升 [ c ] 。
準确性測試
英特爾 ® Extension for Transformers 可利用英特爾 ® Neural Compressor 中的 SignRound [ 11 ] 、RTN 和 GPTQ [ 12 ] 等量化方法,并使用 lambada_openai、piqa、winogrande 和 hellaswag 數據集驗證了 INT4 推理準确性。下表是測試結果平均值與 FP32 準确性的比較。
△表 3.INT4 與 FP32 準确性對比
從上表 3 可以看出,多個模型基于 LLM Runtime 進行的 INT4 推理準确性損失微小,幾乎可以忽略不記。我們驗證了很多模型,但由于篇幅限制此處僅羅列了部分内容。如您欲了解更多信息或細節,請訪問此鏈接:https://medium.com/@NeuralCompressor/llm-performance-of-intel-extension-for-transformers-f7d061556176。
更先進的功能:滿足 LLM 更多場景應用需求
同時,LLM Runtime [ 8 ] 還具備雙路 CPU 的張量并行化功能,是較早具備此類功能的産品之一。未來,還會進一步支持雙節點。
然而,LLM Runtime 的優勢不僅在于其更出色的性能和準确性,我們也投入了大量的精力來增強其在聊天應用場景中的功能,并且解決了 LLM 在聊天場景中可能會遇到的以下應用難題:
對話不僅關乎 LLM 推理,對話曆史也很有用。
輸出長度有限:LLM 模型預訓練主要基于有限的序列長度。因此,當序列長度超出預訓練時使用的注意力窗口大小時,其準确性便會降低。
效率低下:在解碼階段,基于 Transformer 的 LLM 會存儲所有先前生成的 token 的鍵值狀态 ( KV ) ,從而導緻内存使用過度,解碼時延增加。
關于第一個問題,LLM Runtime 的對話功能通過納入更多對話曆史數據以及生成更多輸出加以解決,而 llama.cpp 目前尚未能很好地應對這一問題。
關于第二和第三個問題,我們将流式 LLM(Steaming LLM ) 集成到英特爾 ® Extension for Transformers 中,從而能顯著優化内存使用并降低推理時延。
Streaming LLM
與傳統 KV 緩存算法不同,我們的方法結合了注意力彙聚 ( Attention Sink ) (4 個初始 token)以提升注意力計算的穩定性,并借助滾動 KV 緩存保留最新的 token,這對語言建模至關重要。該設計具有強大的靈活性,可無縫集成到能夠利用旋轉位置編碼 RoPE 和相對位置編碼 ALiBi 的自回歸語言模型中。
△圖 2.Steaming LLM 的 KV 緩存(圖片來源:通過注意力下沉實現高效流式語言模型 [ 13 ] )
此外,與 llama.cpp 不同,本優化方案還引入了 "n_keep" 和 "n_discard" 等參數來增強 Streaming LLM 策略。用戶可使用前者來指定要在 KV 緩存中保留的 token 數量,并使用後者來确定在已生成的 token 中要舍棄的數量。爲了更好地平衡性能和準确性,系統默認在 KV 緩存中舍棄一半的最新 token。
同時,爲進一步提高性能,我們還将 Streaming LLM 添加到了 MHA 融合模式中。如果模型是采用旋轉位置編碼 ( RoPE ) 來實現位置嵌入,那麽隻需針對現有的 K-Cache 應用 " 移位運算(shift operation)",即可避免對先前生成的、未被舍棄的 token 進行重複計算。這一方法不僅充分利用了長文本生成時的完整上下文大小,還能在 KV 緩存上下文完全被填滿前不産生額外開銷。
"shift operation" 依賴于旋轉的交換性和關聯性,或複數乘法。例如:如果某個 token 的 K- 張量初始放置位置爲 m 并且旋轉了 m ×θ i for i ∈ [ 0,d/2),那麽當它需要移動到 m-1 這個位置時,則可以旋轉回到(-1)×θ i for i ∈ [ 0,d/2)。這正是每次舍棄 n_discard 個 token 的緩存時發生的事情,而此時剩餘的每個 token 都需要 " 移動 "n_discard 個位置。下圖以 "n_keep=4、n_ctx=16、n_discard=1" 爲例,展示了這一過程。
△圖 3.Ring-Buffer KV-Cache 和 Shift-RoPE 工作原理
需要注意的是:融合注意力層無需了解上述過程。如果對 K-cache 和 V-cache 進行相同的洗牌,注意力層會輸出幾乎相同的結果(可能存在因浮點誤差導緻的微小差異)。
您可通過以下代碼啓動 Streaming LLM:
from transformers import AutoTokenizer, TextStreamer
from intel_extension_for_transformers.transformers import AutoModelForCausalLM, WeightOnlyQuantConfig
model_name = "Intel/neural-chat-7b-v1-1" # Hugging Face model_id or local model
woq_config = WeightOnlyQuantConfig ( compute_dtype="int8", weight_dtype="int4" )
prompt = "Once upon a time, a little girl"
tokenizer = AutoTokenizer.from_pretrained ( model_name, trust_remote_code=True )
inputs = tokenizer ( prompt, return_tensors="pt" ) .input_ids
streamer = TextStreamer ( tokenizer )
model = AutoModelForCausalLM.from_pretrained ( model_name, quantization_config=woq_config, trust_remote_code=True )
# Recommend n_keep=4 to do attention sinks ( four initial tokens ) and n_discard=-1 to drop half rencetly tokens when meet length threshold
outputs = model.generate ( inputs, streamer=streamer, max_new_tokens=300, ctx_size=100, n_keep=4, n_discard=-1 )
△可左滑看完整版結論與展望
本文基于上述實踐經驗,提供了一個在英特爾 ® 至強 ® 可擴展處理器上實現高效的低位 ( INT4 ) LLM 推理的解決方案,并且在一系列常見 LLM 上驗證了其通用性以及展現了其相對于其他基于 CPU 的開源解決方案的性能優勢。未來,我們還将進一步提升 CPU 張量庫和跨節點并行性能。
歡迎您試用英特爾 ® Extension for Transformers [ 1 ] ,并在英特爾 ® 平台上更高效地運行 LLM 推理!也歡迎您向代碼倉庫 ( repository ) 提交修改請求 ( pull request ) 、問題或疑問。期待您的反饋!
特别緻謝
在此緻謝爲此篇文章做出貢獻的英特爾公司人工智能資深經理張瀚文及工程師許震中、餘振滔、劉振衛、丁藝、王哲、劉宇澄。
[ a ] 根據表 2 Baichuan-13B 的首個 token 測試結果計算而得。
[ b ] 根據表 2 MPT-7B 的下一個 token 測試結果計算而得。
[ c ] 當輸入大小爲 1024 時,整體性能 = 首個 token 性能 +1023 下一個 token 性能;當輸入大小爲 32 時,整體性能 = 首個 token 性能 +31 下一個 token 性能。
參考鏈接:
[ 1 ] 英特爾 ® Extension for Transformers
https://github.com/intel/intel-extension-for-transformers
[ 2 ] Sapphire Rapids
https://www.intel.cn/content/www/cn/zh/products/docs/processors/xeon-accelerated/4th-gen-xeon-scalable-processors.html
[ 3 ] Hugging Face transformers
https://github.com/huggingface/transformers
[ 4 ] 英特爾 ® Neural Compressor
https://github.com/intel/neural-compressor
[ 5 ] NeurIPS 2023:在 CPU 上實現高效 LLM 推理
https://arxiv.org/pdf/2311.00502.pdf
[ 6 ] 常見 LLM:
Falcon: https://falconllm.tii.ae/
LLaMA:https://ai.meta.com/blog/large-language-model-llama-meta-ai/
MPT:https://www.mosaicml.com/blog/mpt-7b
Llama2:https://ai.meta.com/llama/
BLOOM:https://huggingface.co/bigscience/bloom
OPT:https://arxiv.org/abs/2205.01068
ChatGLM2:https://github.com/THUDM/ChatGLM2-6B
GPT-J-6B:https://huggingface.co/EleutherAI/gpt-j-6b
Baichuan-13B-Base:https://huggingface.co/baichuan-inc/Baichuan-13B-Base
Baichuan2-13B-Base:https://huggingface.co/baichuan-inc/Baichuan2-13B-Base
Qwen-7B:https://huggingface.co/Qwen/Qwen-7B
Qwen-14B:https://huggingface.co/Qwen/Qwen-14B
Dolly-v2-3B:https://huggingface.co/databricks/dolly-v2-3b
[ 7 ] 先進的壓縮感知運行時
NeurIPS 2022:在 CPU 上實現快速蒸餾
https://arxiv.org/abs/2211.07715
QuaLA-MiniLM:量化長度自适應 MiniLM
https://arxiv.org/abs/2210.17114
NeurIPS 2021:一次剪枝,一勞永逸:對預訓練語言模型進行稀疏 / 剪枝
https://arxiv.org/abs/2111.05754
[ 8 ] LLM Runtime
https://github.com/intel/intel-extension-for-transformers/tree/main/intel_extension_for_transformers/llm/runtime/graph
[ 9 ] GGML
https://github.com/ggerganov/ggml
[ 10 ] llama.cpp
https://github.com/ggerganov/llama.cpp
[ 11 ] SignRound
https://arxiv.org/abs/2309.05516
[ 12 ] GPTQ
https://arxiv.org/abs/2210.17323
[ 13 ] 通過注意力下沉實現高效流式語言模型
http://arxiv.org/abs/2309.17453
* 本文系量子位獲授權刊載,觀點僅爲作者所有。
— 完 —
一鍵三連「分享」、「點贊」和「在看」
科技前沿進展日日相見 ~