🗨️

FlexGen で opt-66b を動かすメモ

2023/02/28に公開

https://github.com/FMInference/FlexGen

動作環境(256 GB 推奨(X670 などで 48GB x 4 で 192 GB もいけるかもはしれません). 128 GB でも動くけど二倍くらい遅くなる)があれば特に問題なく動くのですが, 一部 huggingface transformers(ややこしい名前であるが, transformer 系 model をぺろっとダウンロードしたり読むためのライブラリ) での(?)weight のダウンロードに不都合あるようです.

とりま試す

とりま chatbot 試します!

  • x299 256 GB CPU mem
  • 3090 x 2(実際は一個だけ使われる)
$ python chatbot.py --model facebook/opt-66b --percent 50 10 100 0 100 0 --compress-weight

(ちなみに最新 FlexGen だと chatbot.py サンプルが消されてます)

GPU は 20 GB, CPU は 25 GB くらいのメモリ消費量でした.

A chat between a curious human and a knowledgeable artificial intelligence assistant.                                                 
Human: Hello! What can you do?
Assistant: As an AI assistant, I can answer questions and chat with you.
Human: What is the name of the tallest mountain in the world?
Assistant: Everest.

ここで東京と NY どれくらい遠いか聞いてみます!

Human: How far from Tokyo to New York?
Assistant: About 10,000 kilometers.

正解は 10,850 km くらいですが, About ~ で答えているのでヨシ!
きちんと SI 単位系で答えておりエライ!

Human: ずんだもんはかわいいですか?
Assistant: うん! ずんだもんはかわいいですか?  

日本語はだめだめでした...

返答には 1 分くらいかかりました. FlexGen には opt-66b の benchmark 設定はないのですが, opt-175b の benchmark 結果から想定するにだいたい 1~2 token/sec くらいな感じでしょうか.
opt-66b は chatbot として使うのは現状難しいカナ.

メモリある場合の改善

--percent 0 100 100 0 100 0 --compress-weight

で, CPU メモリ 64 GB, GPU 4 GB くらいで返答時間は 20 秒くらいになりました! GPU あんまり使わんほうが性能でる...
(--compress-weight なしはメモリ不足でした(正確には頑張って動かそうと kernel がメモリ圧縮とかしていつまでも初期化が終わらない. 384 GB とかなら動きそうです)

でも

Human: How far from Tokyo to New York?                                                Assistant: About 12,000 miles.

とマイル換算で答えてメッ!(しかも距離間違っている), となりました.

ただ返答 20 秒も chatbot 用途ではちょっときびしいカナ.
opt-30b (benchmark 7 token/sec) だと 5~10 秒くらいで, なんとか許容できる感じ.
opt-6.7b は 2~3 秒で返ってきてチャット感ありました.

opt-6b or opt-30b でまずはチャットして, それでもユーザーが満足しなかったら, 責任者として opt-66b 出して問い合わせしてもらう感じで運用がいいでしょうか...

あとは, LLaMa あたりや GPT-neox 系に期待ですかね.

ちなみに opt-30b もマイルで返答し, また距離間違っていた..

https://twitter.com/syoyo/status/1629917508005400576?s=20

opt-66b benchmark

FlexGen repo には opt-66b の benchmark は無いのですが, opt-30b と opt-175b の設定を参考にやってみました. 1x1(1 node, single GPU)での結果です. compress 有効にしています.

python -m flexgen.flex_opt --model facebook/opt-66b --path _DUMMY_ --percent 0 100 0 100 0 100 --gpu-batch-size 32 --num-gpu-batches 3
 --debug fewer_batch --compress-cache
model size: 122.375 GB, cache size: 114.750 GB, hidden size (prefill): 0.896 GB
init weight...
warmup - generate
benchmark - generate
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 20/20 [0
2:19<00:00,  6.96s/it]
/home/syoyo/miniconda3/envs/flexgen/lib/python3.8/site-packages/torch/distributed/distributed_c10d.py:262: UserWarning: torch.distribu
ted.reduce_op is deprecated, please use torch.distributed.ReduceOp instead
  warnings.warn(
TorchDevice: cuda:0
  cur_mem: 1.2672 GB,  peak_mem: 6.1617 GB
TorchDevice: cpu
  cur_mem: 123.2760 GB,  peak_mem: 0.0000 GB
model size: 122.375 GB  cache size: 114.750 GB  hidden size (p): 0.896 GB
peak gpu mem: 6.162 GB  projected: True
prefill latency: 136.627 s      prefill throughput: 359.753 token/s
decode latency: 511.038 s       decode throughput: 5.823 token/s
total latency: 647.665 s        total throughput: 4.743 token/s
python -m flexgen.flex_opt --model facebook/opt-66b --path _DUMMY_ --percent 0 100 0 100 0 100 --gpu-batch-size 12 --num-gpu-batches 4 --debug fewer_batch --compress-cache --prompt-len 1024
model size: 122.375 GB, cache size: 111.375 GB, hidden size (prefill): 0.870 GB
init weight...
warmup - generate
benchmark - generate
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 20/20 [02:21<00:00,  7.09s/it]
/home/syoyo/miniconda3/envs/flexgen/lib/python3.8/site-packages/torch/distributed/distributed_c10d.py:262: UserWarning: torch.distributed.reduce_op is deprecated, please use torch.distributed.ReduceOp instead
  warnings.warn(
TorchDevice: cuda:0
  cur_mem: 1.2663 GB,  peak_mem: 6.7893 GB
TorchDevice: cpu
  cur_mem: 123.2759 GB,  peak_mem: 0.0000 GB
model size: 122.375 GB  cache size: 111.375 GB  hidden size (p): 0.870 GB
peak gpu mem: 6.789 GB  projected: True
prefill latency: 139.272 s      prefill throughput: 352.921 token/s
decode latency: 501.070 s       decode throughput: 2.970 token/s
total latency: 640.342 s        total throughput: 2.399 token/s

CPU 123 GB くらい使い, 4.7 tokens/s でした. opt-30b が 7~8 tokens/sec, opt-175b が 1 tokens/sec ですから意外といいかんじでしょうか.

ただバッチサイズ等増やしてスループット上げての結果だと思いますので, いろいろ設定いじってレイテンシ重視にしても chatbot 用途向けにレイテンシ短縮はむりっぽそうな気もします.

モデルダウンロードの不都合

FlexGen では, huggingface で落としたモデルデータに変換をかけます.
したがって, 元となる huggingface の cache(~/.cache/huggingface/hub/)が壊れているとうまくいきません.

(あと, opt-66b だと 14 個ある weight ファイルのうち, 最後の 1 個が FlexGen 経由のダウンロードでは欠けるっぽい?)

huggingface のライブラリでは SHA ハッシュなどでファイルが壊れていないかなどのチェックはしてくれないようです...

また, ファイル自体は何らかのハッシュを取って blob に保存なので, ファイル名みただけではわかりません.

元ファイル名は

~/.cache/huggingface/hub/models--facebook--opt-66b/snapshots/7259969061237fe940036d22bea0fd349e4485e9

のように snapshots にあります(さらに一段何かしらのハッシュを取ってフォルダ作っておりややこしい)

ここから blob へのシンボリックリンクの形でファイルがありますので, ダウンロード失敗したのはこの symlink と blob の両方のファイルを消して再度ダウンロードします.
(ダウンロードしたファイル名はなにか別途 DB で管理しているようではないので, 単に不都合のあるファイルを消せば OK だった)

モデルのダウンロード自体は, transformers 使った簡単なスクリプトかいて,

from transformers import AutoModelForCausalLM, AutoTokenizer
model = AutoModelForCausalLM.from_pretrained("facebook/opt-66b", torch_dtype=torch.float16).cuda()

あたりな感じで.

opt-175b は?

一応 CPU mem 256 GB あれば動きそうですが, opt-175b は落とすのにリクエストが必要です.
運よく許可されれば試してみたいところ.

Discussion