main
sh 220 lines 6.88 KB
Raw
1 #!/bin/bash
2 set -euo pipefail
3
4 declare -a PIDS=()
5
6 ###############################################################################
7 # Configuration -- override via env before running
8 ###############################################################################
9 MODEL="${MODEL:-Qwen/Qwen2.5-VL-3B-Instruct}"
10 LOG_PATH="${LOG_PATH:-./logs}"
11 mkdir -p "$LOG_PATH"
12
13 ENCODE_PORT="${ENCODE_PORT:-19534}"
14 PREFILL_DECODE_PORT="${PREFILL_DECODE_PORT:-19535}"
15 PROXY_PORT="${PROXY_PORT:-10001}"
16
17 GPU_E="${GPU_E:-0}"
18 GPU_PD="${GPU_PD:-1}"
19
20 # Device platform and affinity env name.
21 # DEVICE_PLATFORM supports: cuda, xpu
22 DEVICE_PLATFORM="${DEVICE_PLATFORM:-cuda}"
23 if [[ -z "${DEVICE_AFFINITY_ENV:-}" ]]; then
24 if [[ "${DEVICE_PLATFORM,,}" == "xpu" ]]; then
25 DEVICE_AFFINITY_ENV="ZE_AFFINITY_MASK"
26 else
27 DEVICE_AFFINITY_ENV="CUDA_VISIBLE_DEVICES"
28 fi
29 fi
30
31 EC_SHARED_STORAGE_PATH="${EC_SHARED_STORAGE_PATH:-/tmp/ec_cache}"
32 TIMEOUT_SECONDS="${TIMEOUT_SECONDS:-300}" # wait_for_server timeout
33
34 NUM_PROMPTS="${NUM_PROMPTS:-100}" # number of prompts to send in benchmark
35
36 # Serve args
37 GPU_MEMORY_UTILIZATION_E="${GPU_MEMORY_UTILIZATION_E:-0.01}"
38 GPU_MEMORY_UTILIZATION_PD="${GPU_MEMORY_UTILIZATION_PD:-0.7}"
39 MAX_NUM_SEQS="${MAX_NUM_SEQS:-128}"
40 MAX_MODEL_LEN="${MAX_MODEL_LEN:-32768}"
41
42 ###############################################################################
43 # Helpers
44 ###############################################################################
45 # Find the git repository root directory
46 GIT_ROOT=$(git rev-parse --show-toplevel)
47
48 START_TIME=$(date +"%Y%m%d_%H%M%S")
49 ENC_LOG=$LOG_PATH/encoder_${START_TIME}.log
50 PD_LOG=$LOG_PATH/pd_${START_TIME}.log
51 PROXY_LOG=$LOG_PATH/proxy_${START_TIME}.log
52
53 wait_for_server() {
54 local port=$1
55 timeout "$TIMEOUT_SECONDS" bash -c "
56 until curl -s localhost:$port/v1/chat/completions > /dev/null; do
57 sleep 1
58 done" && return 0 || return 1
59 }
60
61 # Cleanup function
62 cleanup() {
63 echo "Stopping everything…"
64 trap - INT TERM USR1 # prevent re-entrancy
65
66 # Kill all tracked PIDs
67 for pid in "${PIDS[@]}"; do
68 if kill -0 "$pid" 2>/dev/null; then
69 echo "Killing process $pid"
70 kill "$pid" 2>/dev/null
71 fi
72 done
73
74 # Wait a moment for graceful shutdown
75 sleep 2
76
77 # Force kill any remaining processes
78 for pid in "${PIDS[@]}"; do
79 if kill -0 "$pid" 2>/dev/null; then
80 echo "Force killing process $pid"
81 kill -9 "$pid" 2>/dev/null
82 fi
83 done
84
85 # Kill the entire process group as backup
86 kill -- -$$ 2>/dev/null
87
88 echo "All processes stopped."
89 exit 0
90 }
91
92 trap cleanup INT
93 trap cleanup USR1
94 trap cleanup TERM
95
96 # clear previous cache
97 echo "remove previous ec cache folder"
98 rm -rf "$EC_SHARED_STORAGE_PATH"
99
100 echo "make ec cache folder"
101 mkdir -p "$EC_SHARED_STORAGE_PATH"
102
103 ###############################################################################
104 # Encoder worker
105 ###############################################################################
106 env "$DEVICE_AFFINITY_ENV=$GPU_E" vllm serve "$MODEL" \
107 --gpu-memory-utilization "$GPU_MEMORY_UTILIZATION_E" \
108 --port "$ENCODE_PORT" \
109 --enforce-eager \
110 --enable-request-id-headers \
111 --no-enable-prefix-caching \
112 --max-num-batched-tokens 114688 \
113 --max-num-seqs "$MAX_NUM_SEQS" \
114 --allowed-local-media-path "${GIT_ROOT}"/tests/v1/ec_connector/integration \
115 --ec-transfer-config '{
116 "ec_connector": "ECExampleConnector",
117 "ec_role": "ec_producer",
118 "ec_connector_extra_config": {
119 "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'"
120 }
121 }' \
122 >"${ENC_LOG}" 2>&1 &
123
124 PIDS+=($!)
125
126 ###############################################################################
127 # Prefill+Decode worker
128 ###############################################################################
129 env "$DEVICE_AFFINITY_ENV=$GPU_PD" vllm serve "$MODEL" \
130 --gpu-memory-utilization "$GPU_MEMORY_UTILIZATION_PD" \
131 --port "$PREFILL_DECODE_PORT" \
132 --enforce-eager \
133 --enable-request-id-headers \
134 --max-num-seqs "$MAX_NUM_SEQS" \
135 --max-model-len "$MAX_MODEL_LEN" \
136 --allowed-local-media-path "${GIT_ROOT}"/tests/v1/ec_connector/integration \
137 --ec-transfer-config '{
138 "ec_connector": "ECExampleConnector",
139 "ec_role": "ec_consumer",
140 "ec_connector_extra_config": {
141 "shared_storage_path": "'"$EC_SHARED_STORAGE_PATH"'"
142 }
143 }' \
144 >"${PD_LOG}" 2>&1 &
145
146 PIDS+=($!)
147
148 # Wait for workers
149 wait_for_server "$ENCODE_PORT"
150 wait_for_server "$PREFILL_DECODE_PORT"
151
152 ###############################################################################
153 # Proxy
154 ###############################################################################
155 PROXY_ARGS=()
156 if [[ "${DYNAMIC_REGISTRATION:-0}" == "1" ]]; then
157 : "${ADMIN_API_KEY:?Set ADMIN_API_KEY for dynamic registration}"
158 export ADMIN_API_KEY
159 PROXY_ARGS=(--dynamic-registration)
160 else
161 PROXY_ARGS=(
162 --encode-servers-urls "http://localhost:$ENCODE_PORT"
163 --decode-servers-urls "http://localhost:$PREFILL_DECODE_PORT"
164 )
165 fi
166 python disagg_epd_proxy.py \
167 --host "0.0.0.0" \
168 --port "$PROXY_PORT" \
169 "${PROXY_ARGS[@]}" \
170 >"${PROXY_LOG}" 2>&1 &
171
172 PIDS+=($!)
173
174 wait_for_server "$PROXY_PORT"
175 if [[ "${DYNAMIC_REGISTRATION:-0}" == "1" ]]; then
176 for endpoint in "encode:$ENCODE_PORT" "prefill_decode:$PREFILL_DECODE_PORT"; do
177 curl --fail-with-body "http://127.0.0.1:$PROXY_PORT/instances" \
178 -H "X-API-Key: $ADMIN_API_KEY" -H 'Content-Type: application/json' \
179 -d "{\"role\":\"${endpoint%%:*}\",\"url\":\"http://127.0.0.1:${endpoint#*:}\"}"
180 done
181 fi
182 echo "All services are up!"
183
184 ###############################################################################
185 # Benchmark
186 ###############################################################################
187 echo "Running benchmark (stream)..."
188 vllm bench serve \
189 --model "$MODEL" \
190 --backend openai-chat \
191 --endpoint /v1/chat/completions \
192 --dataset-name hf \
193 --dataset-path lmarena-ai/VisionArena-Chat \
194 --seed 0 \
195 --num-prompts "$NUM_PROMPTS" \
196 --port "$PROXY_PORT"
197
198 PIDS+=($!)
199
200 ###############################################################################
201 # Single request with local image
202 ###############################################################################
203 echo "Running single request with local image (non-stream)..."
204 curl http://127.0.0.1:"${PROXY_PORT}"/v1/chat/completions \
205 -H "Content-Type: application/json" \
206 -d '{
207 "model": "'"${MODEL}"'",
208 "messages": [
209 {"role": "system", "content": "You are a helpful assistant."},
210 {"role": "user", "content": [
211 {"type": "image_url", "image_url": {"url": "file://'"${GIT_ROOT}"'/tests/v1/ec_connector/integration/hato.jpg"}},
212 {"type": "text", "text": "What is in this image?"}
213 ]}
214 ]
215 }'
216
217
218 # cleanup
219 echo "cleanup..."
220 cleanup