ノート:

Oracle Cloud Infrastructure ComputeでvLLMを使用した単純なLLM推論ベンチマーク・システムの設定

イントロダクション

システムのパフォーマンス特性を理解すると、そのコンポーネントとそのコンポーネントについて十分な情報に基づいて選択できます。このチュートリアルでは、AI大規模言語モデル(LLM)推論のための完全なベンチマークシステムを設定します。これを使用すると、LLMに対する特定のOracle Cloud Infrastructure (OCI)コンピュート・シェイプの適合性を評価することから、様々なLLMを相互に比較することに留意したパフォーマンス要件まで、様々な実験を実行できます。

このチュートリアルでは、一般的なオープン・ソース推論サーバーvLLMを使用します。これは、最先端のLLMの多くの状態をサポートし、これらのモデルを効率的に提供するために重要なパフォーマンス最適化を提供し、数千の同時リクエストを処理できます。さらに、ベンチマークの実行には Ray LLMPerfを使用します。

ノート:このチュートリアルでは、GPU割当て制限を持つOCIテナンシがあることを前提としています。割当ての詳細は、コンピュート割当てに関する項を参照してください。

目的

前提条件

タスク1: ネットワークの構成

このタスクでは、Virtual Cloud Network (VCN)を構成して、ベンチマークを実行するための機能的でセキュアな設定を提供します。この例では、1つのパブリック・サブネットと1つのプライベート・サブネットを持つVCNが必要です。VCN設定ウィザードを使用するか、すべてのコンポーネントを手動で設定して、セキュリティ・リストがSSHアクセスを許可し、NATゲートウェイがプライベート・サブネットに割り当てられていることを確認できます。

プライベート・サブネットとパブリック・サブネット、要塞ホスト、およびテスト中のGPU VMで構成されるソリューション・アーキテクチャの概要

OCI Computeインスタンスをプロビジョニングしてベンチマーク設定を進める前に、ネットワーク設定が適切に構成されていることを確認することが重要です。デフォルトでは、プロビジョニングされたネットワークはサブネット間の重要なトラフィックのみを許可します。ベンチマークに必要なネットワーク・トラフィックを許可するには、パブリック・サブネットとプライベート・サブネット間のHTTPトラフィックを許可するようにこれらの設定を調整する必要があります。具体的には、VCN CIDRブロックから宛先ポート8000へのトラフィックを許可するプライベート・サブネットのセキュリティ・リストにイングレス・ルールを追加します。

タスク2: OCIコンピュート・インスタンスのプロビジョニング

このタスクでは、ベンチマーク設定用に2つのOCI Computeインスタンスをプロビジョニングします。1つは、要塞およびベンチマーク・クライアント・マシンとして機能するCPU専用仮想マシン(VM)インスタンスで、もう1つはテスト中のGPU装備インスタンスです。

  1. 8つのOCPUとOracle Linux 8を含むVM.Flex.E5インスタンスをプロビジョニングします。要塞/ベンチマーク・クライアントは、別のマシンでホストされているモデルにのみリクエストを送信するため、CPUシェイプの選択を行うため、GPUは必要ありません。ネットワーク・パラメータでパブリック・サブネットを選択し、SSH公開キーをアップロードすることを忘れないでください(または、必要に応じて指定された秘密キーをダウンロードしてください)。

  2. VM.GPU.A10.1インスタンスをプロビジョニングします。設定を合理化するには、NVIDIAドライバおよびCUDAフレームワークを含むOracle Linux 8イメージを使用してインスタンスをプロビジョニングします。まず目的のシェイプを選択し、イメージ選択メニューに戻り、GPUが組み込まれたOracle Linux 8バリアントを選択します。このインスタンスはプライベート・サブネットにプロビジョニングする必要があります。つまり、要塞ホストを使用してのみアクセスできます。SSHキーも必ず設定してください。

組込みGPUサポートを含むOracle Linux 8イメージを選択するスクリーンショット

タスク3: ベンチマーク・クライアントの設定

このタスクでは、パフォーマンス・ベンチマークに必要なすべてのコンポーネントをインストールし、GPUホストを構成します。

  1. SSHキーで要塞にログインし、次のコマンドを使用してLLMPerfのすべての要件を設定します。

    sudo dnf install epel-release -y
    sudo yum-config-manager --enable ol8_baseos_latest ol8_appstream ol8_addons ol8_developer_EPEL
    sudo dnf install git python3.11 python3.11-devel python3.11-pip -y
    
  2. Ray LLMPerfリポジトリをクローニングし、Python venvを設定し、次のコマンドを使用してLLMPerfをインストールします。

    git clone https://github.com/ray-project/llmperf.git
    cd llmperf
    mkdir venv && python3.11 -mvenv venv && source venv/bin/activate
    
  3. LLMPerf (およびそのPython依存関係)をインストールする前に、pyproject.tomlファイルを編集し、Python要件句を削除します。この句によって、Pythonのバージョンが不必要に制限され、3.11未満になります。

    diff --git a/pyproject.toml b/pyproject.toml
    index 7687fb2..521a2a7 100644
    --- a/pyproject.toml
    +++ b/pyproject.toml
    @@ -8,7 +8,6 @@ version = "0.1.0"
     description = "A framework for load testing LLM APIs"
     authors = [{name="Avnish Narayan", email="avnish@anyscale.com"}]
     license = {text= "Apache-2.0"}
    -requires-python = ">=3.8, <3.11"
     dependencies = ["pydantic<2.5",
                     "ray",
                     "pytest>=6.0",
    
  4. pip install -e コマンドを実行して、設定を確定します。

タスク4: ベンチマーク・ターゲットの設定

このタスクでは、ベンチマーク・ターゲット自体を設定します。必要なドライバとCompute Unified Device Architecture(CUDA)フレームワークでノードをすでにプロビジョニングしているため、vLLMとそのpython依存関係をインストールし、ベンチマークするモデルをデプロイする必要があります。

ノート:プロビジョニングしたGPUコンピュート・インスタンスはプライベート・サブネットに存在します。そのため、アクセスするには、まず要塞ホストにログインし、ベンチマーク・ターゲットに選択した秘密SSHキーを設定する必要があります。その場合のみ、プライベートIPアドレスを使用してベンチマーク・ターゲットにログインできます。

  1. 要塞ホストでの初期設定など、必要なパッケージをインストールします。また、次のコマンドを使用して、ポート8000で受信トラフィックを許可するようにホストのファイアウォールを更新します。

    sudo dnf install epel-release -y
    sudo yum-config-manager --enable ol8_baseos_latest ol8_appstream ol8_addons ol8_developer_EPEL
    sudo dnf install git python3.11 python3.11-devel python3.11-pip -y
    sudo firewall-cmd --permanent --zone=public --add-port=8000/tcp
    sudo firewall-cmd --reload
    
  2. 次のコマンドを実行して、vLLMとその要件をインストールします。

    mkdir venv
    python3.11 -mvenv venv && source venv/bin/activate
    pip install -U pip "bitsandbytes>=0.44.0" vllm gpustat mistral_common
    
  3. テストするモデルでvLLMを開始する準備ができています。

    export HF_TOKEN=<your huggingface token>
    export MODEL="meta-llama/Llama-3.2-3B-Instruct"
    ulimit -Sn 65536 # increase limits to avoid running out of files that can be opened
    vllm serve $MODEL --tokenizer-mode auto --config-format hf --load-format auto \
                      --enforce-eager --max-model-len 65536
    

    ノート:モデル・コンテキストの長さをA10 GPUメモリーに収まるように減らす必要があります。コンテキストの長さを128kトークンのデフォルト・サイズから64kトークンに減らします。ロード後、モデルvLLMは推論統計の出力を一定の間隔で開始する必要があります。

    INFO 12-09 15:46:36 metrics.py:449] Avg prompt throughput: 0.0 tokens/s, Avg generation throughput: 0.0 tokens/s, Running: 0 reqs, Swapped: 0 reqs, Pending: 0 reqs, GPU KV cache usage: 0.0%, CPU KV cache usage: 0.0%.
    
  4. バックグラウンドでサーバーの実行を続行し、別の端末に切り替えて設定をテストおよびベンチマークします。単純なテストは、次のようにcurlを使用して実行できます。

    export HOST="<the ip address of the benchmark machine"
    export MODEL="meta-llama/Llama-3.2-3B-Instruct"
    curl --location "http://${HOST}:8000/v1/chat/completions"     --header 'Content-Type: application/json'     --header 'Authorization: Bearer token'     --data '{
            "model": "'"$MODEL"'",
            "messages": [
              {
                "role": "user",
                "content": "What is the question to the answer to the ultimate question of life, the universe, and everything. You may give a humorous response."
              }
            ]
        }' -s | jq
    

    出力は次のようになります。

    {
      "id": "chatcmpl-f11306f943604d41bad84be1dadd9da6",
      "object": "chat.completion",
      "created": 1733997638,
      "model": "meta-llama/Llama-3.2-3B-Instruct",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "You want to know the ultimate question to the answer of 42?\n\nWell, after years of intense research and contemplation, I've discovered that the answer is actually a giant, cosmic joke. The question is: \"What's for lunch?\"",
            "tool_calls": []
          },
          "logprobs": null,
          "finish_reason": "stop",
          "stop_reason": null
        }
      ],
      "usage": {
        "prompt_tokens": 62,
        "total_tokens": 112,
        "completion_tokens": 50,
        "prompt_tokens_details": null
      },
      "prompt_logprobs": null
    }
    

タスク5: ベンチマークの実行

これで、ベンチマークを実行する準備ができました。大規模な言語モデルを選択した特定のアプリケーション・シナリオを考えて、同時推論リクエストの実行のパフォーマンス特性について、ターゲット・システムで理解します。

次のシナリオをベンチマークします。

PARAMETER VALUE
モデル Meta LLaMa 3.2 3Bのインストラクション
ユースケース チャット
入力トークン N(200, 40
出力トークン N(100, 10)
同カレント要求 1 - 32
  1. ホーム・ディレクトリ内のベンチマーク・クライアント(要塞ホスト)に、llm_benchmark.shという名前の次のスクリプトを作成します。

    #!/usr/bin/env bash
    
    set -xe
    
    # Use vLLM OpenAPI endpoint
    export OPENAI_API_BASE="http://<benchmark host>:8000/v1"
    # API key is not in use, but needs to be set for llmbench
    export OPENAI_API_KEY="none"
    
    model="meta-llama/Llama-3.2-3B-Instruct"
    
    modelname="${model##*/}"
    mkdir "$modelname"
    
    concurrent_requests=(1 2 4 8 16 32)
    
    pushd llmperf
    
    source venv/bin/activate
    
    for cr in "${concurrent_requests[@]}"
    do
        python3 token_benchmark_ray.py --model $model \
            --mean-input-tokens 200 --stddev-input-tokens 40 \
            --mean-output-tokens 100 --stddev-output-tokens 10 \
            --max-num-completed-requests $((cr * 100)) --num-concurrent-requests $cr \
            --metadata "use_case=chatbot" \
            --timeout 1800 --results-dir "../$modelname/result_outputs_chat_creq_$cr" --llm-api openai
    done
    popd
    

    このスクリプトを使用すると、同時リクエストの数が増える(1から開始して32まで連続して倍増する) llmperfを使用して、一連のベンチマークを自動的に実行できます。token_benchmark_ray.pyスクリプトに渡された引数からわかるように、前述の表に定義されているトークン入力および出力を設定します。

  2. 次のコマンドを使用してベンチマーク・スクリプトを実行します。

    bash -x llm_benchmark.sh
    

完了すると、ホーム・ディレクトリにLlama-3.2-3B-Instructという新しいディレクトリが見つかります。このディレクトリには、すべての実験結果がJSON形式で格納され、お気に入りのデータ分析ツールを使用してダウンロードして後処理できます。

ノート:ベンチマークをプロットに変換する簡単な方法の1つは、少しのシェル・スクリプトおよびjqを使用して最も関心のある数字を.csv形式に抽出することです。これにより、Excelに簡単にコピー・ペーストできます。

echo "concurrent_requests,token_throughput"
for i in *; do
    cat $i/*_summary.json | jq -r '[.num_concurrent_requests, .results_request_output_throughput_token_per_s_mean] | join(",")'
done;

承認

その他の学習リソース

docs.oracle.com/learnの他のラボを確認するか、Oracle Learning YouTubeチャネルで無料のラーニング・コンテンツにアクセスしてください。また、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerになります。

製品ドキュメントについては、Oracle Help Centerを参照してください。