iT邦幫忙

2024 iThome 鐵人賽

DAY 23
1
生成式 AI

Local LLM infra & Inference 一部曲系列 第 23

Day23 - vLLM實作篇PART2:模型平行化 / 預測推理 / 其他設定

  • 分享至 

  • xImage
  •  

前言

昨天的教學中,已經學會設定基本的OpenAI-Compatible Server方法了。

簡單回顧一下,若是什麼也沒設定,預設會是使用一個GPU。 🎮
https://ithelp.ithome.com.tw/upload/images/20240923/20168115LAkWthmIrz.png

筆者拿了一個閱讀測驗QA問答集測試 📚,一筆一筆發,請vLLM生成回應,一共跑了16分鐘。 ⏱️
(時間僅供參考用,每個人的電腦設備和設定都不同)

  • 但是......電腦有兩個GPU耶! 🖥️
  • 說好的分散式計算在哪裡? 🔀
  • 現在跑的速度,應該還可以再更快、更快對吧! 🚀
  • 還想跑更長context length的模型欸! 📜
  • 量化的模型怎麼跑? 🧮

這一章就要來看這些可以手動設定、調整的部分,也就是進階篇章。


⚙️ Model Parallelization

回顧一下 Day11 提過的兩種模型平行化設定方式。而官方文件的解說在這裡。

如果要使用多個GPU,數量設定公式是:你有幾張GPU = tensor-parallel-size * pipeline-parallel-size

  • 🧠 Tensor parallelism

首先,如果VRAM夠大,並且想要推理速度快一些的話,可以設定--tensor-parallel-size
因為筆者的GPU只有2,所以一次只能開一個示範。

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --port 8503 \
    --tensor-parallel-size 2

如果把GPU開好開滿,他也會用好用滿,速度上明顯有變快,筆者的QA資料集從16分鐘變成8分鐘,直接快兩倍

https://ithelp.ithome.com.tw/upload/images/20240924/201681153GhaKXiCBx.png

因為Tensor Parallelism是將模型的計算部分分散到多個GPU上,變快兩倍都是合理的,但是當模型大到一個VRAM不夠用的時候就需要用到Pipeline parallelism。

  • 🏭 Pipeline parallelism

使用Pipeline Parallelism的話,可以設定--pipeline-parallel-size

之前看的時候還不支援Multiprocessing,當時要將預設會是mp的distributed-executor-backend,改成是ray,不過現在看起來是兩種都可以了。

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --port 8503 \
    --pipeline-parallel-size 2

🔀 或是使用Ray:

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --port 8503 \
    --pipeline-parallel-size 2
    --distributed-executor-backend ray

在推論中可以看到,這次兩張GPU不是都用好用滿了,其中一張維持在38-41,另一張則是在83-89左右,而速度上同樣跑筆者的QA資料集,執行時間是18分鐘,反而變慢了

https://ithelp.ithome.com.tw/upload/images/20240924/20168115M2RrjDEYXv.png

變慢的原因如下,也可以從 Day11 回顧 📅:

  1. 因為Pipeline Parallelism需要在所有的GPU之間傳輸資料 🔄,所以傳輸時間也變長了。 ⏳
  2. 如果模型每個階段的計算量不平衡 ⚖️,可能會導致有GPU閒置,在等其他GPU計算完畢,導致GPU使用率低下。 📉

🚀 Speculative decoding in vLLM

同樣先放官方文件,以及筆者的筆記Day18

現在vLLM有支援Speculative decoding,可以選擇兩種方法進行推理:一種是使用較小的draft model,另一種則是使用ngram進行推理,這兩種都必須要打開use-v2-block-manager。如果要精確一點的答案,num_speculative_token可以調小;如果速度比較重要,則是調大。

⚠️ Please note that speculative decoding in vLLM is not yet optimized and does not usually yield inter-token latency reductions for all prompt datasets or sampling parameters. The work to optimize it is ongoing and can be followed in this issue.

雖然官方有警告說Speculative decoding還沒有到最佳化,不過看到今年8月的進度已經幾乎完成了,延遲甚至減少了45%。

🔬 秉持著實驗精神,如果使用相同的draft model的話,因為要同時跑兩個的模型,也不是用小的模型當draft model,這些額外的計算讓筆者的QA資料集跑了大約12分鐘,並沒有比較划算。

這邊官方的範例是 model="facebook/opt-6.7b" 和 speculative_model="facebook/opt-125m"。

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --port 8503 \
    --tensor-parallel-size 2 \
    --speculative-model meta-llama/Meta-Llama-3-8B-Instruct \
    --num-speculative-tokens 5 \
    --use-v2-block-manager

如果要使用不同的draft model,需要確認兩個模型的詞彙表大小(vocab size)一致,可以先檢查兩個model的tokenizer大小,BY GPT-4o:

from transformers import AutoTokenizer

final_model_tokenizer = AutoTokenizer.from_pretrained("meta-llama/Meta-Llama-3-8B-Instruct")
final_model_vocab_size = final_model_tokenizer.vocab_size

draft_model_tokenizer = AutoTokenizer.from_pretrained("facebook/opt-125m")
draft_model_vocab_size = draft_model_tokenizer.vocab_size

print(f"Final model vocab size: {final_model_vocab_size}")
print(f"Draft model vocab size: {draft_model_vocab_size}")

📊 如果是用ngram的話,速度上筆者的QA資料集變成只要5分鐘!是目前最快的速度!

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-8B-Instruct \
    --port 8503 \
    --tensor-parallel-size 2 \
    --speculative-model [ngram] \
    --num-speculative-tokens 5 \
    --ngram-prompt-lookup-max 4 \
    --use-v2-block-manager

注意這邊如果是用vLLM開API的方法,在不同版本中要注意 - 和 _ 的寫法,像是use_v2_block_manager=True這一行會是 - 的寫法而不是 _ 的寫法。
因為在比較舊的版本中,有些沒有被統一到XD
請參考:https://docs.vllm.ai/en/latest/models/engine_args.html#engine-args


📜 更長的context length模型

假設筆者想要跑yentinglin/Llama-3-Taiwan-8B-Instruct-128k,但設備用的是只有32GB的電腦,而昨天提到預設的--gpu-memory-utilization是0.9,正是在 Day12 中提到的VRAM預留的一個記憶體大小,如果記憶體不夠的話就會出現下方的警告。

ValueError: The model's max seq len (131072) is larger than the maximum number of tokens that can be stored in KV cache (88528). Try increasing `gpu_memory_utilization` or decreasing `max_model_len` when initializing the engine.

這時有兩個選擇,一個是增加--gpu-memory-utilization,調到0.95用好用滿看裝不裝得下 💪;又或是減少--max-model-len,從原本131072減少到88528以下 📉,至少就可以執行大context length模型囉。

筆者調整了之後,雖然像是23910 tokens這種長度是可以跑的,但還是沒辦法跑88528那麼長的context length,原因推測還是KV cache的記憶體占用問題 💾,不過至少比原本8000 tokens還要多很多了XD?

  • 補充一下long context length model的使用心得:
    一定要記得設定max_tokens=512,不然很容易鬼打牆就一直卡著直到最大context length,API都timeout了還生成不完QQ

🛠️ 其他參數介紹

詳細請見官方文件

  • --host 0.0.0.0 如果可以將vLLM API對外被任何其他電腦訪問時可以設定。

  • --dtype auto 一般會是預設'auto',可以在API啟動後某一行看到他的選擇是什麼,也可自行設定 'float16'、'bfloat16'、'float32'。

  • --quantization awq 可以指定量化方法 🧮,目前支援'awq'、'gptq'、 'squeezellm'、'fp8' (experimental)。

  • --gpu-memory-utilization 0.75 可以設定一個0-1之間的浮點數,調整GPU的記憶體使用比例,增加的話可以預先提供更多的KV快取空間。

  • --max_seq_len 4096 可以控制模型的context length長度。

  • 如果想指定GPU,可以在指令最前面加上: CUDA_VISIBLE_DEVICES=0


章節總結

我們學會了如Tensor Parallelism與Pipeline Parallelism的差異,並且體驗了Speculative decoding更加速了local LLM的生成速度 📚。目前vLLM量化模型的使用沒有支援跑GGUF的量化模型,而同樣的官方文件表示目前AWQ支援還為最佳化,筆者跑起來AWQ跟vLLM (bfloat16) + Speculative decoding的速度差不多,因此可以看出vLLM真的很快!

明天來繼續在vLLM的文件中尋寶! 🧭🗺️✨

https://ithelp.ithome.com.tw/upload/images/20240924/20168115r5D6uf0WlW.png
(圖源: codecademy)


上一篇
Day22 - vLLM實作篇PART1:安裝到推理 (Linux version)
下一篇
Day24 - vLLM實作篇PART3:FastAPI與vLLM docs尋寶之旅
系列文
Local LLM infra & Inference 一部曲30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言