0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

WSL2 + RTX 4090 x 4 で OCR モデル 3 種類を vLLM Docker に分散デプロイする

0
Posted at

はじめに

ローカル環境で OCR / Document Parsing 系モデルをいくつか試したかったので、WSL2 + Docker + RTX 4090 x 4 の環境に、OCR モデルを 3 種類まとめてデプロイしました。

今回起動したのは以下の 3 モデルです。

モデル 用途 GPU Host Port
baidu/Unlimited-OCR 長文書 OCR / Markdown 化 GPU 0 8884
rednote-hilab/dots.mocr 文書・図表・レイアウト解析 GPU 1 8883
zai-org/GLM-OCR 軽量・高速 OCR GPU 2 8888

全部 vLLM の OpenAI compatible API として立てています。

ポイントは、WSL2 + Docker Desktop 環境では --gpus device=... だけでは GPU 指定が期待通り効かないことがあったため、最終的に CUDA_VISIBLE_DEVICES でモデルごとに GPU を固定したことです。

環境

今回の環境です。

項目 内容
Host Windows + WSL2
WSL distro Ubuntu 22.04
GPU NVIDIA GeForce RTX 4090 x 4
VRAM 24GB x 4
Docker Docker Desktop + WSL Integration
API server vLLM OpenAI compatible server

nvidia-smi では以下のように 4 枚見えています。

nvidia-smi
GPU 0  NVIDIA GeForce RTX 4090
GPU 1  NVIDIA GeForce RTX 4090
GPU 2  NVIDIA GeForce RTX 4090
GPU 3  NVIDIA GeForce RTX 4090

モデル配置

モデルは Hugging Face から事前にローカルへダウンロード済みです。

/root/HuggingFaceCache/Unlimited-OCR
/root/HuggingFaceCache/DotsMOCR
/root/HuggingFaceCache/GLM-OCR

Docker コンテナには read-only でマウントします。

-v /root/HuggingFaceCache/Unlimited-OCR:/models/Unlimited-OCR:ro

のような形です。

最終構成

今回の構成は以下です。

Container Model GPU Host Port Container Port
unlimited-ocr-gpu0 baidu/Unlimited-OCR 0 8884 8000
dots-mocr-gpu1 rednote-hilab/dots.mocr 1 8883 8000
glm-ocr-gpu2 zai-org/GLM-OCR 2 8888 8000

それぞれコンテナ内では 8000 で起動し、ホスト側のポートだけ分けています。

GPU 指定について

最初は Docker の GPU 指定で、以下のようにしていました。

--gpus '"device=2"'

また GPU UUID 指定も試しました。

--gpus '"device=GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"'

ただし、今回の WSL2 + Docker Desktop 環境では、コンテナ内の nvidia-smi で 4 枚すべて見えてしまいました。

そのため最終的には、以下の形にしています。

--gpus all
-e CUDA_VISIBLE_DEVICES=2

つまり、Docker 側では GPU capability を全部渡し、CUDA アプリケーション側で使う GPU を絞ります。

今回の割り当ては以下です。

モデル CUDA_VISIBLE_DEVICES
Unlimited-OCR 0
dots.mocr 1
GLM-OCR 2

1. Unlimited-OCR を GPU 0 / Port 8884 で起動

docker run -d \
  --name unlimited-ocr-gpu0 \
  --gpus all \
  -e CUDA_VISIBLE_DEVICES=0 \
  --ipc=host \
  -p 8884:8000 \
  -v /root/HuggingFaceCache/Unlimited-OCR:/models/Unlimited-OCR:ro \
  -e HF_HOME=/root/.cache/huggingface \
  -e HF_TOKEN="${HF_TOKEN:-}" \
  docker.1ms.run/vllm/vllm-openai:unlimited-ocr \
  /models/Unlimited-OCR \
  --trust-remote-code \
  --host 0.0.0.0 \
  --port 8000 \
  --logits_processors vllm.model_executor.models.unlimited_ocr:NGramPerReqLogitsProcessor \
  --no-enable-prefix-caching \
  --mm-processor-cache-gb 0 \
  --gpu-memory-utilization 0.80 \
  --max-model-len 32768

アクセス先は以下です。

http://127.0.0.1:8884/v1

2. dots.mocr を GPU 1 / Port 8883 で起動

docker run -d \
  --name dots-mocr-gpu1 \
  --gpus all \
  -e CUDA_VISIBLE_DEVICES=1 \
  --shm-size 32g \
  --ipc=host \
  -p 8883:8000 \
  -v /root/HuggingFaceCache/DotsMOCR:/models/DotsMOCR:ro \
  docker.1ms.run/vllm/vllm-openai:v0.17.1 \
  --model /models/DotsMOCR \
  --served-model-name rednote-hilab/dots.mocr \
  --tensor-parallel-size 1 \
  --gpu-memory-utilization 0.9 \
  --chat-template-content-format string \
  --trust-remote-code \
  --host 0.0.0.0 \
  --port 8000

アクセス先は以下です。

http://127.0.0.1:8883/v1

3. GLM-OCR を GPU 2 / Port 8888 で起動

docker run -d \
  --name glm-ocr-gpu2 \
  --gpus all \
  -e CUDA_VISIBLE_DEVICES=2 \
  --shm-size 32g \
  --ipc=host \
  -p 8888:8000 \
  -v /root/HuggingFaceCache/GLM-OCR:/models/GLM-OCR:ro \
  docker.1ms.run/vllm/vllm-openai \
  --model /models/GLM-OCR \
  --served-model-name glm-ocr \
  --trust-remote-code \
  --host 0.0.0.0 \
  --port 8000 \
  --gpu-memory-utilization 0.90 \
  --max-model-len 32768 \
  --speculative-config '{"method": "mtp", "num_speculative_tokens": 3}'

アクセス先は以下です。

http://127.0.0.1:8888/v1

起動確認

まずコンテナを確認します。

docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}"

期待値はこんな感じです。

NAMES                 PORTS
unlimited-ocr-gpu0    0.0.0.0:8884->8000/tcp
dots-mocr-gpu1        0.0.0.0:8883->8000/tcp
glm-ocr-gpu2          0.0.0.0:8888->8000/tcp

ログを見る場合は以下です。

docker logs -f unlimited-ocr-gpu0
docker logs -f dots-mocr-gpu1
docker logs -f glm-ocr-gpu2

/v1/models の確認

Unlimited-OCR

curl -s http://127.0.0.1:8884/v1/models | jq

dots.mocr

curl -s http://127.0.0.1:8883/v1/models | jq

GLM-OCR

curl -s http://127.0.0.1:8888/v1/models | jq

jq がない場合はインストールします。

apt update
apt install -y jq

GPU 使用状況の確認

ホスト側で確認します。

nvidia-smi

想定は以下です。

GPU モデル
GPU 0 Unlimited-OCR
GPU 1 dots.mocr
GPU 2 GLM-OCR
GPU 3 空き

WSL2 + Docker Desktop 環境では、nvidia-smi の Processes 表示が少し分かりづらいことがあります。
そのため、基本的には各 GPU の Memory-Usage を見て、意図した GPU に載っているか確認します。

よく使う確認コマンド

コンテナ一覧

docker ps

ポート確認

ss -lntp | grep -E '8883|8884|8888'

ログ確認

docker logs --tail 100 unlimited-ocr-gpu0
docker logs --tail 100 dots-mocr-gpu1
docker logs --tail 100 glm-ocr-gpu2

GPU 使用状況

nvidia-smi

各モデル API の疎通確認

curl -s http://127.0.0.1:8884/v1/models | jq
curl -s http://127.0.0.1:8883/v1/models | jq
curl -s http://127.0.0.1:8888/v1/models | jq

停止・削除

docker rm -f unlimited-ocr-gpu0 dots-mocr-gpu1 glm-ocr-gpu2

ハマったところ

--gpus device=N が効かなかった

今回の環境では、以下の指定をしてもコンテナ内の nvidia-smi で 4 枚すべて見えていました。

--gpus '"device=2"'

UUID 指定でも同じでした。

--gpus '"device=GPU-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"'

最終的には以下で回避しました。

--gpus all
-e CUDA_VISIBLE_DEVICES=2

この方法なら、vLLM / PyTorch 側では指定した GPU のみを使えます。

コンテナ内の cuda:0 はホストの GPU 0 とは限らない

CUDA_VISIBLE_DEVICES=2 とすると、コンテナ内ではホストの GPU 2 が cuda:0 として見えることがあります。

つまり、対応関係はこうなります。

Host GPU 2 -> Container cuda:0

これは正常です。

モデル名は /v1/models で確認したほうがよい

--served-model-name を指定しているモデルは分かりやすいです。

rednote-hilab/dots.mocr
glm-ocr

一方、Unlimited-OCR は起動方法によって model id が /models/Unlimited-OCR のようになる場合があります。
そのため、実際に呼び出す前に必ず以下で確認しておくと安全です。

curl -s http://127.0.0.1:8884/v1/models | jq

まとめ

WSL2 + RTX 4090 x 4 の環境で、OCR モデルを 3 種類同時に vLLM Docker として起動しました。

最終的な構成は以下です。

モデル GPU Port
Unlimited-OCR 0 8884
dots.mocr 1 8883
GLM-OCR 2 8888

一番重要だったのは、GPU の分散方法です。

--gpus all
-e CUDA_VISIBLE_DEVICES=N

この形にすることで、WSL2 + Docker Desktop 環境でも、モデルごとに使用 GPU を分けることができました。

ローカル OCR 環境としては、以下のように使い分けると便利です。

モデル 使いどころ
Unlimited-OCR 長い PDF / Markdown 化
dots.mocr レイアウト・表・図表を含む文書解析
GLM-OCR 軽量・高速な OCR API

クラウド OCR に出しづらい文書でも、ローカル GPU 上で処理できるのはかなり便利です。
複数 GPU がある場合は、1 モデル 1 GPU で API サーバーを分けておくと、検証も運用もしやすくなります。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?