vLLM is an open-source library designed to optimize the inference and serving. Originally developed at UC Berkeley's Sky Computing Lab, it has evolved into a community-driven project. The library is built around the innovative PagedAttention algorithm, which significantly improves memory management by reducing waste in Key-Value (KV) cache memory.
To ensure your workflows utilize the preloaded model weights and datasets, update the following environment variables in your session. Some models hosted on Hugging Face may be gated, requiring additional authentication. To access these gated models, you will need a Hugging Face authentication token.
For small models that fit within the memory of a single A100 GPU (40 GB), no additional configuration is required to serve the model. Simply use the default tensor parallelism size (TP) of 1 when serving the model. This ensures the model is run on a single GPU without the need for distributed setup. Models with fewer than 15 billion parameters typically fit within a single GPU when using half precision (e.g., bfloat16).
For example, the following command serves meta-llama/Llama-3.1-8B-Instruct on a single GPU of a single node.
After the server output says Application startup complete., it is ready to accept prompt requests, for example with the following simple Python code (can background the server process)
fromopenaiimportOpenAIopenai_api_base=f"http://localhost:8000/v1"client=OpenAI(api_key="EMPTY",base_url=openai_api_base,)prompt="Hi, can you introduce yourself?"response=client.chat.completions.create(model="meta-llama/Llama-3.1-8B-Instruct",messages=[{"role":"user","content":prompt}],temperature=0.0,max_tokens=1024,stream=False)print(f"\n{response.choices[0].message.content}\n")
Serving Medium Models on Multiple GPUs (Single Node)¶
To serve larger models which require multiple GPUs (TP>1) but still only a single node, a more advanced setup is necessary. This involves setting the VLLM_HOST_IP and the TP size. Models with about 70 billion parameters can usually fit within a single node utilizing half precition.
The following commands demonstrate how to serve the meta-llama/Llama-3.1-70B-Instruct on 4 GPUs on a single node.
To serve models across multiple nodes, we suggest users take advantage of the provided setup_ray_cluster.sh script to setup a Ray cluster across nodes before running vllm serve.
# This script is intended to be sourced, not executed directly.# On the head node, run:# source ./setup_ray_cluster.sh# main######################################################################### FUNCTIONS######################################################################### Setup environment and variables needed to setup ray and vllmsetup_environment(){echo"[$(hostname)] Setting up the environment..."# Set proxy configurationsexportHTTP_PROXY="http://proxy.alcf.anl.gov:3128"exportHTTPS_PROXY="http://proxy.alcf.anl.gov:3128"exporthttp_proxy="http://proxy.alcf.anl.gov:3128"exporthttps_proxy="http://proxy.alcf.anl.gov:3128"exportftp_proxy="http://proxy.alcf.anl.gov:3128"# Define the common setup script path (make sure this file is accessible on all nodes)SCRIPT_DIR=$(cd--"$(dirname--"${BASH_SOURCE[0]}")"&>/dev/null&&pwd)SCRIPT_PATH="${SCRIPT_DIR}/$(basename"${BASH_SOURCE[0]}")"exportCOMMON_SETUP_SCRIPT=$SCRIPT_PATH# Load modules and activate your conda environmentmoduleuse/soft/modulefiles
moduleloadconda
condaactivate
exportCUDA_VISIBLE_DEVICES=0,1,2,3
exportRAY_EXPERIMENTAL_NOSET_CUDA_VISIBLE_DEVICES=1exportOMP_NUM_THREADS=8exportTORCH_LLM_ALLREDUCE=1exportHF_HOME="/eagle/datasets/model-weights"exportHF_DATASETS_CACHE="/flare/datasets/model-weights"exportTMPDIR="/tmp"exportRAY_TMPDIR="/tmp"exportVLLM_IMAGE_FETCH_TIMEOUT=60ulimit-cunlimited
# Derive the node's HSN IP address (modify the getent command as needed)exportHSN_IP_ADDRESS=$(getenthosts"$(hostname).hsn.cm.polaris.alcf.anl.gov"|awk'{ print $1 }'|sort|head-n1)exportVLLM_HOST_IP="$HSN_IP_ADDRESS"echo"[$(hostname)] Environment setup complete. HSN_IP_ADDRESS is $HSN_IP_ADDRESS"}# Stop any running Ray processesstop_ray(){echo"[$(hostname)] Stopping Ray (if running)..."raystop-f
}# Start Ray head nodestart_ray_head(){echo"[$(hostname)] Starting Ray head..."raystart--num-gpus=4--num-cpus=32--head--node-ip-address="$HSN_IP_ADDRESS"--temp-dir=/tmp
# Wait until Ray reports that the head node is upecho"[$(hostname)] Waiting for Ray head to be up..."untilraystatus&>/dev/null;dosleep5echo"[$(hostname)] Waiting for Ray head..."doneecho"[$(hostname)] ray status: $(raystatus)"echo"[$(hostname)] Ray head node is up."}# Start Ray worker nodestart_ray_worker(){echo"[$(hostname)] Starting Ray worker, connecting to head at $RAY_HEAD_IP..."echo"HSN IP Address : $HSN_IP_ADDRESS"raystart--num-gpus=4--num-cpus=32--address="$RAY_HEAD_IP:6379"--node-ip-address="$HSN_IP_ADDRESS"--temp-dir=/tmp
echo"[$(hostname)] Waiting for Ray worker to be up..."untilraystatus&>/dev/null;dosleep5echo"[$(hostname)] Waiting for Ray worker..."doneecho"[$(hostname)] ray status: $(raystatus)"echo"[$(hostname)] Ray worker node is up."}######################################################################### MAIN SCRIPT LOGIC########################################################################main(){# Require HF_TOKEN env variableif[[-z"${HF_TOKEN}"]];thenecho"Error: HF_TOKEN is not set!">&2return1fi# Ensure that the script is being run within a PBS jobif[-z"$PBS_NODEFILE"];thenecho"Error: PBS_NODEFILE not set. This script must be run within a PBS job allocation."return1fi# Read all nodes from the PBS_NODEFILE into an array.mapfile-tnodes_full<"$PBS_NODEFILE"num_nodes=${#nodes_full[@]}echo"Allocated nodes ($num_nodes):"printf" - %s\n""${nodes_full[@]}"# Require at least 2 nodes (one head + one worker)if["$num_nodes"-lt2];thenecho"Error: Need at least 2 nodes to launch the Ray cluster."return1fi# The first node will be our Ray head.head_node_full="${nodes_full[0]}"# All remaining nodes will be the workers.worker_nodes_full=("${nodes_full[@]:1}")# It is a good idea to run this master script on the designated head node.current_node=$(hostname-f)echo"[$(hostname)] Running on head node."# --- Setup and start the head node ---setup_environment
stop_ray
start_ray_head
# Export the head node's IP so that workers can join.exportRAY_HEAD_IP="$HSN_IP_ADDRESS"exportRAY_ADDRESS="$RAY_HEAD_IP:6379"echo"[$(hostname)] RAY_HEAD_IP exported as $RAY_HEAD_IP"echo"[$(hostname)] RAY_ADDRESS exported as $RAY_ADDRESS"# --- Launch Ray workers on each of the other nodes via SSH ---forworkerin"${worker_nodes_full[@]}";doecho"[$(hostname)] Launching Ray worker on $worker..."ssh"$worker""bash -l -c 'set -x; export RAY_HEAD_IP=${RAY_HEAD_IP}; export COMMON_SETUP_SCRIPT=${COMMON_SETUP_SCRIPT} ;source \$COMMON_SETUP_SCRIPT; setup_environment; stop_ray; start_ray_worker'"&done# Wait for all background SSH jobs to finish.waitecho"[$(hostname)] Ray cluster is up and running with $num_nodes nodes."}
The following example serves meta-llama/Llama-3.1-70B-Instruct model using 2 nodes. It sets tensor parallelism TP=4 for intra-node communications and pipeline parallelism PP=2 for inter-node communication, for a total of 16 shards.
source/path/to/setup_ray_cluster.sh
main
raystatus# should show 2 active nodes and 8 GPUs totalvllmservemeta-llama/Llama-3.1-70B-Instruct--port8000--tensor-parallel-size4--pipeline-parallel-size2--dtypebfloat16--trust-remote-code--max-model-len8192
General guidelines to keep in mind when serving models across nodes:
Guidelines for vLLM Model Serving
Setting --max-model-len can be important in order to fit the model on the GPUs.
Tensor parallelism size must evenly divide the number of attention heads of the model. For example, the Llama-3.1-70B-Instruct model has 64 attention heads, so valid TP values are 1, 2, 4, 8. However, setting TP size equal to the number of GPUs on the node (4 for Polaris) is preferred to utilize intra-node communications for this parallism dimension.
Pipeline parallelism size must evenly divide the number of hidden layers in the model. For example, the Llama-3.1-70B-Instruct model has 80 layers, so PP values of 1, 2, 4, 5, etc. are valid. In this case PP is set to the number of nodes used.
The product TP x PP indicates the total number of GPUs used to serve the model, which is usually defined by the number of parameters in the model and the memory of the individual GPUs. As a back of the envelope calculation, when using half precision such as bfloat16, (num. billion paramemers x 2) / GPU GB mem gives the number of GPUs needed.
To scale vLLM workflows on ALCF system there are a few recommended approaches depending on the user's needs and setup. These approaches are described in detail in the GettingStarted repository along with example scripts for each.