Hinweis:

Einfaches LLM-Inferenzbenchmarking-System mit vLLM auf Oracle Cloud Infrastructure Compute einrichten

Einführung

Wenn Sie die Leistungsmerkmale eines Systems verstehen, können Sie fundierte Entscheidungen über seine Komponenten und deren Erwartungen treffen. In diesem Tutorial wird ein komplettes Benchmarking-System für die Inferenzierung von AI Large Language Model (LLM) eingerichtet. Auf diese Weise können Sie verschiedene Experimente ausführen, um die Eignung einer bestimmten Oracle Cloud Infrastructure (OCI) Compute-Ausprägung für die LLM- und Performanceanforderungen zu bewerten und verschiedene LLMs miteinander zu vergleichen.

In diesem Tutorial verwenden wir den beliebten Open-Source-Inferenzserver vLLM, der viele hochmoderne LLMs unterstützt und Leistungsoptimierungen bietet, die für die effiziente Bereitstellung dieser Modelle entscheidend sind und Tausende gleichzeitiger Anforderungen verarbeiten können. Darüber hinaus verwenden wir Ray LLMPerf zur Ausführung der Benchmarks.

Hinweis: In diesem Tutorial wird davon ausgegangen, dass Sie über einen OCI-Mandanten mit einer GPU-Quota verfügen. Weitere Informationen zu Quotas finden Sie unter Compute-Quotas.

Ziele

Voraussetzungen

Aufgabe 1: Netzwerk konfigurieren

Konfigurieren Sie in dieser Aufgabe das virtuelle Cloud-Netzwerk (VCN), um ein funktionales und sicheres Setup für die Ausführung Ihrer Benchmarks bereitzustellen. In diesem Beispiel benötigen wir ein VCN mit einem öffentlichen und einem privaten Subnetz. Sie können den VCN-Setupassistenten verwenden oder alle Komponenten manuell einrichten. Stellen Sie sicher, dass Sicherheitslisten SSH-Zugriff zulassen und ein NAT-Gateway dem privaten Subnetz zugewiesen ist.

Überblick über die Lösungsarchitektur, bestehend aus einem privaten und öffentlichen Subnetz, einem Bastionhost und der zu testenden GPU-VM

Bevor Sie OCI Compute-Instanzen bereitstellen und mit dem Benchmarksetup fortfahren, müssen Sie sicherstellen, dass Ihre Netzwerkeinstellungen ordnungsgemäß konfiguriert sind. Standardmäßig lässt das bereitgestellte Netzwerk nur wesentlichen Traffic zwischen Subnetzen zu. Um den für das Benchmarking erforderlichen Netzwerktraffic zuzulassen, müssen Sie diese Einstellungen anpassen, um HTTP-Traffic zwischen den öffentlichen und privaten Subnetzen zuzulassen. Fügen Sie insbesondere eine Ingress-Regel zur Sicherheitsliste des privaten Subnetzes hinzu, die Traffic vom VCN-CIDR-Block zum Zielport 8000 zulässt.

Aufgabe 2: OCI Compute-Instanzen bereitstellen

Stellen Sie in dieser Aufgabe zwei OCI Compute-Instanzen für unser Benchmarksetup bereit. Eine Instanz ist eine VM-Instanz (nur CPU), die als Bastion und Benchmark-Clientrechner fungiert, die andere ist die Instanz mit GPU-Ausrüstung, die getestet wird.

  1. Stellen Sie eine VM.Flex.E5-Instanz mit acht OCPUs und Oracle Linux 8 bereit. Der Bastion/Benchmark-Client benötigt keine GPU, da er nur Anforderungen an das Modell sendet, das auf einem separaten Rechner gehostet wird, also die Auswahl einer CPU-Ausprägung. Stellen Sie sicher, dass Sie das öffentliche Subnetz in den Netzwerkparametern auswählen, und vergessen Sie nicht, den SSH-Public Key hochzuladen (oder den angegebenen Private Key bei Bedarf herunterzuladen).

  2. Stellen Sie eine VM.GPU.A10.1-Instanz bereit. Um das Setup zu optimieren, stellen Sie die Instanz mit einem Oracle Linux 8-Image bereit, das NVIDIA-Treiber und das CUDA-Framework enthält. Wählen Sie zunächst die gewünschte Ausprägung aus, navigieren Sie dann zurück zum Bildauswahlmenü, und wählen Sie die Oracle Linux 8-Variante mit integrierter GPU-Unterstützung aus. Diese Instanz muss im privaten Subnetz bereitgestellt werden, sodass nur mit dem Bastionhost darauf zugegriffen werden kann. Richten Sie auch den SSH-Schlüssel ein.

Screenshot der Auswahl eines Oracle Linux 8-Images mit integrierter GPU-Unterstützung

Aufgabe 3: Benchmarkclient einrichten

In dieser Aufgabe werden wir alle erforderlichen Komponenten für unsere Leistungsbenchmarks installieren und den GPU-Host konfigurieren.

  1. Melden Sie sich mit dem SSH-Schlüssel bei Ihrer Bastion an, und richten Sie mit dem folgenden Befehl alle Anforderungen für LLMPerf ein.

    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. Klonen Sie das Ray-Repository LLMPerf, richten Sie ein Python-venv ein, und installieren Sie LLMPerf mit dem folgenden Befehl.

    git clone https://github.com/ray-project/llmperf.git
    cd llmperf
    mkdir venv && python3.11 -mvenv venv && source venv/bin/activate
    
  3. Bearbeiten Sie vor der Installation von LLMPerf (und den zugehörigen Python-Abhängigkeiten) die Datei pyproject.toml, und entfernen Sie die Python-Anforderungsklausel. Die Klausel begrenzt die Python-Version unnötigerweise auf weniger als 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. Führen Sie den Befehl pip install -e aus, um das Setup abzuschließen.

Aufgabe 4: Benchmarkziel einrichten

In dieser Aufgabe richten wir das Benchmark-Ziel selbst ein. Da wir den Knoten bereits mit den erforderlichen Treibern und dem Compute Unified Device Architecture-(CUDA-)Framework bereitgestellt haben, müssen wir einfach vLLM und seine python-Abhängigkeiten installieren und das Modell bereitstellen, das wir als Benchmark verwenden möchten.

Hinweis: Die von Ihnen bereitgestellte GPU-Compute-Instanz befindet sich in einem privaten Subnetz. Um ihn zu erreichen, müssen Sie sich zunächst beim Bastionhost anmelden und den privaten SSH-Schlüssel einrichten, den Sie für das Benchmarkziel ausgewählt haben. Erst dann können Sie sich mit der privaten IP-Adresse beim Benchmarkziel anmelden.

  1. Installieren Sie die erforderlichen Packages, wie das anfängliche Setup auf dem Bastionhost. Aktualisieren Sie außerdem die Firewall des Hosts, um eingehenden Traffic auf Port 8000 mit dem folgenden Befehl zuzulassen.

    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. Führen Sie den folgenden Befehl aus, um vLLM und die zugehörigen Anforderungen zu installieren.

    mkdir venv
    python3.11 -mvenv venv && source venv/bin/activate
    pip install -U pip "bitsandbytes>=0.44.0" vllm gpustat mistral_common
    
  3. Wir sind bereit, vLLM mit dem Modell zu starten, das wir testen möchten.

    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
    

    Hinweis: Die Modellkontextlänge muss reduziert werden, damit sie in den GPU-Speicher A10 passt. Die Kontextlänge wird von der Standardgröße der 128k-Token auf 64k-Token reduziert. Nach dem Laden sollte das Modell vLLM mit der Ausgabe seiner Inferenzstatistiken in regelmäßigen Abständen beginnen.

    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. Wir lassen den Server im Hintergrund weiterlaufen, während wir zu einem anderen Terminal wechseln, wo wir nun unser Setup testen und Benchmarking durchführen. Ein einfacher Test kann wie folgt mit curl ausgeführt werden.

    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
    

    Ausgabe:

    {
      "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
    }
    

Aufgabe 5: Benchmark ausführen

Jetzt sind wir bereit, unseren Benchmark zu betreiben. In Anbetracht eines bestimmten Anwendungsszenarios mit einem ausgewählten großen Sprachmodell möchten wir im Zielsystem verstehen, welche Performanceeigenschaften gleichzeitige Inferenzanforderungen aufweisen.

Lassen Sie uns das folgende Szenario vergleichen:

PARAMETER WERT
MODELL Meta LLaMa 3.2 3B Instruct
ANWENDUNGSFALL Chat
EINGABETOKEN N(200, 40
AUSGABETOKEN N(100, 10)
GLEICHZEITIGE ANFORDERUNGEN 1 - 32
  1. Erstellen Sie das folgende Skript namens llm_benchmark.sh auf dem Benchmarkclient (Bastionhost) im Home-Verzeichnis.

    #!/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
    

    Mit diesem Skript können Sie automatisch eine Reihe von Benchmarks mit llmperf mit zunehmender Anzahl gleichzeitiger Anforderungen (beginnend bei 1 und sukzessive Verdoppelung bis zu 32) durchlaufen. Wie Sie anhand der Argumente sehen können, die an das Skript token_benchmark_ray.py übergeben wurden, legen wir Tokenein- und -ausgaben wie in der obigen Tabelle definiert fest.

  2. Führen Sie das Benchmark-Skript mit dem folgenden Befehl aus.

    bash -x llm_benchmark.sh
    

Sobald Sie fertig sind, finden Sie ein neues Verzeichnis namens Llama-3.2-3B-Instruct in Ihrem Home-Verzeichnis, in dem alle Experimentergebnisse im JSON-Format gespeichert werden, das Sie mit Ihrem bevorzugten Datenanalysetool herunterladen und nachverarbeiten können.

Hinweis: Eine einfache Möglichkeit, Ihre Benchmarks in einen Plot umzuwandeln, besteht darin, die Zahlen, die Sie am meisten interessieren, mit einem kleinen Shellskript und jq in das .csv-Format zu extrahieren, das einfach in Excel kopiert werden kann.

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;

Danksagungen

Weitere Lernressourcen

Sehen Sie sich andere Übungen zu docs.oracle.com/learn an, oder greifen Sie im Oracle Learning YouTube-Channel auf weitere kostenlose Lerninhalte zu. Besuchen Sie außerdem education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.

Die Produktdokumentation finden Sie im Oracle Help Center.