-
Notifications
You must be signed in to change notification settings - Fork 37
[draft]support sglang native disagg and profiling. #55
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |||||||||||||
| #SBATCH --job-name={{ job_name }} | ||||||||||||||
| #SBATCH --nodes={{ total_nodes }} | ||||||||||||||
| #SBATCH --ntasks={{ total_nodes }} | ||||||||||||||
| #SBATCH --segment={{ total_nodes }} | ||||||||||||||
| #SBATCH --ntasks-per-node=1 | ||||||||||||||
| {% if use_gpus_per_node_directive %} | ||||||||||||||
| #SBATCH --gpus-per-node={{ gpus_per_node }} | ||||||||||||||
|
|
@@ -57,7 +58,7 @@ for i in "${!nodes[@]}"; do | |||||||||||||
| done | ||||||||||||||
|
|
||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if enable_multiple_frontends %} | ||||||||||||||
| {% if enable_multiple_frontends and not use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| # Multiple frontend architecture | ||||||||||||||
| # Node 0: nginx only + prefill shard | ||||||||||||||
|
|
@@ -142,7 +143,7 @@ echo "Master IP address: $MASTER_IP" | |||||||||||||
|
|
||||||||||||||
| # Compute leader nodes for each worker | ||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if enable_multiple_frontends %} | ||||||||||||||
| {% if enable_multiple_frontends and not use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| # With multiple frontends: keep offset 0; nginx coexists on node 0 | ||||||||||||||
| WORKER_NODE_OFFSET=0 | ||||||||||||||
|
|
@@ -183,7 +184,12 @@ ENROOT_ARGS="\ | |||||||||||||
| {% raw %} | ||||||||||||||
| WORKER_ARGS="--gpu_type ${GPU_TYPE} --gpus_per_node ${GPUS_PER_NODE} --master_ip ${MASTER_IP}" | ||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if enable_multiple_frontends %} | ||||||||||||||
| {% if use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| WORKER_ARGS="$WORKER_ARGS --use-sglang-router" | ||||||||||||||
| {% endraw %} | ||||||||||||||
| {% endif %} | ||||||||||||||
| {% if enable_multiple_frontends and not use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| # Add multiple frontends flag for worker setup | ||||||||||||||
| WORKER_ARGS="$WORKER_ARGS --multiple-frontends-enabled" | ||||||||||||||
|
|
@@ -204,7 +210,7 @@ WORKER_ARGS="$WORKER_ARGS --setup-script {{ setup_script }}" | |||||||||||||
| {% raw %} | ||||||||||||||
|
|
||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if enable_multiple_frontends %} | ||||||||||||||
| {% if enable_multiple_frontends and not use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if total_nodes > 1 %} | ||||||||||||||
|
|
@@ -314,7 +320,7 @@ done | |||||||||||||
|
|
||||||||||||||
| echo "" | ||||||||||||||
| {% endraw %} | ||||||||||||||
| {% if enable_multiple_frontends %} | ||||||||||||||
| {% if enable_multiple_frontends and not use_sglang_router %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| echo "Frontend available at: http://${NGINX_NODE}:8000" | ||||||||||||||
| echo "To connect to the nginx node:" | ||||||||||||||
|
|
@@ -330,6 +336,38 @@ echo "srun $ENROOT_ARGS --jobid $SLURM_JOB_ID -w ${nodes[0]} --overlap --pty bas | |||||||||||||
| {% endif %} | ||||||||||||||
| {% raw %} | ||||||||||||||
|
|
||||||||||||||
| # Launch sglang router when enabled | ||||||||||||||
| {% endraw %}{% if use_sglang_router %}{% raw %} | ||||||||||||||
| echo "Launching sglang router on ${nodes[0]}" | ||||||||||||||
| # Collect leader IPs for prefill and decode | ||||||||||||||
| PREFILL_LEADER_IPS=() | ||||||||||||||
| for idx in "${prefill_leaders[@]}"; do | ||||||||||||||
| node_name=${nodes[$idx]} | ||||||||||||||
| ip=$(get_node_ip "$node_name" "$SLURM_JOB_ID" "$NETWORK_INTERFACE") | ||||||||||||||
| PREFILL_LEADER_IPS+=("$ip") | ||||||||||||||
| done | ||||||||||||||
| DECODE_LEADER_IPS=() | ||||||||||||||
| for idx in "${decode_leaders[@]}"; do | ||||||||||||||
| node_name=${nodes[$idx]} | ||||||||||||||
| ip=$(get_node_ip "$node_name" "$SLURM_JOB_ID" "$NETWORK_INTERFACE") | ||||||||||||||
| DECODE_LEADER_IPS+=("$ip") | ||||||||||||||
| done | ||||||||||||||
|
|
||||||||||||||
| ROUTER_ARGS="--pd-disaggregation" | ||||||||||||||
| for ip in "${PREFILL_LEADER_IPS[@]}"; do | ||||||||||||||
| ROUTER_ARGS="$ROUTER_ARGS --prefill http://${ip}:30000" | ||||||||||||||
| done | ||||||||||||||
| for ip in "${DECODE_LEADER_IPS[@]}"; do | ||||||||||||||
| ROUTER_ARGS="$ROUTER_ARGS --decode http://${ip}:30000" | ||||||||||||||
| done | ||||||||||||||
|
|
||||||||||||||
| ROUTER_NODE=${nodes[0]} | ||||||||||||||
| cmd="srun --overlap $ENROOT_ARGS --nodes=1 --ntasks=1 --nodelist=$ROUTER_NODE --output=${LOG_DIR}/${ROUTER_NODE}_router.out python -m sglang_router.launch_router $ROUTER_ARGS --host 0.0.0.0 --port 8000" | ||||||||||||||
| echo "$cmd" | ||||||||||||||
| $cmd & | ||||||||||||||
| {% endraw %}{% endif %} | ||||||||||||||
| {% raw %} | ||||||||||||||
|
|
||||||||||||||
| echo "" | ||||||||||||||
| echo "Make sure to cancel the job at the end:" | ||||||||||||||
| echo "scancel $SLURM_JOB_ID" | ||||||||||||||
|
|
@@ -349,25 +387,35 @@ srun --nodes=1 --ntasks=1 $ENROOT_ARGS --jobid $SLURM_JOB_ID -w ${nodes[0]} --ou | |||||||||||||
|
|
||||||||||||||
| {% if profiler != 'none' %} | ||||||||||||||
| {% raw %} | ||||||||||||||
| # Torch profiling mode: run profiling on prefill and decode workers separately | ||||||||||||||
| echo "Starting profiler..." | ||||||||||||||
| # Torch/NSYS profiling mode: run a single orchestrator that profiles all prefill and decode workers. | ||||||||||||||
| echo "Starting unified profiler..." | ||||||||||||||
|
|
||||||||||||||
| # Collect leader IPs for prefill and decode workers | ||||||||||||||
| PREFILL_LEADER_IPS=() | ||||||||||||||
| for idx in "${prefill_leaders[@]}"; do | ||||||||||||||
| node_name=${nodes[$idx]} | ||||||||||||||
| ip=$(get_node_ip "$node_name" "$SLURM_JOB_ID" "$NETWORK_INTERFACE") | ||||||||||||||
| PREFILL_LEADER_IPS+=("$ip") | ||||||||||||||
| done | ||||||||||||||
|
|
||||||||||||||
| # Get leader nodes for first prefill and decode workers | ||||||||||||||
| PREFILL_LEADER_NODE=${nodes[${prefill_leaders[0]}]} | ||||||||||||||
| DECODE_LEADER_NODE=${nodes[${decode_leaders[0]}]} | ||||||||||||||
| DECODE_LEADER_IPS=() | ||||||||||||||
| for idx in "${decode_leaders[@]}"; do | ||||||||||||||
| node_name=${nodes[$idx]} | ||||||||||||||
| ip=$(get_node_ip "$node_name" "$SLURM_JOB_ID" "$NETWORK_INTERFACE") | ||||||||||||||
| DECODE_LEADER_IPS+=("$ip") | ||||||||||||||
| done | ||||||||||||||
|
|
||||||||||||||
| echo "Prefill profiling will run on: $PREFILL_LEADER_NODE" | ||||||||||||||
| echo "Decode profiling will run on: $DECODE_LEADER_NODE" | ||||||||||||||
| PREFILL_LEADER_IPS_STR=$(IFS=,; echo "${PREFILL_LEADER_IPS[*]}") | ||||||||||||||
| DECODE_LEADER_IPS_STR=$(IFS=,; echo "${DECODE_LEADER_IPS[*]}") | ||||||||||||||
|
|
||||||||||||||
| # Run prefill profiling on first prefill worker's leader node | ||||||||||||||
| srun --nodes=1 --ntasks=1 $ENROOT_ARGS --jobid $SLURM_JOB_ID -w $PREFILL_LEADER_NODE \ | ||||||||||||||
| --output=${LOG_DIR}/profile_prefill.out --overlap \ | ||||||||||||||
| bash -c "PROFILING_MODE=prefill {% endraw %}{% if profiler == 'torch' %}SGLANG_TORCH_PROFILER_DIR=/logs/profiles/prefill {% endif %}{{ prefill_profile_env }}{% raw %} /scripts/profiling/profile.sh $PREFILL_WORKERS $DECODE_WORKERS $PREFILL_GPUS $DECODE_GPUS $TOTAL_GPUS" & | ||||||||||||||
| # Use the first prefill leader as the orchestrator node | ||||||||||||||
| PROFILE_ORCHESTRATOR_NODE=${nodes[${prefill_leaders[0]}]} | ||||||||||||||
| echo "Unified profiling will run on orchestrator node: $PROFILE_ORCHESTRATOR_NODE" | ||||||||||||||
|
|
||||||||||||||
| # Run decode profiling on first decode worker's leader node | ||||||||||||||
| srun --nodes=1 --ntasks=1 $ENROOT_ARGS --jobid $SLURM_JOB_ID -w $DECODE_LEADER_NODE \ | ||||||||||||||
| --output=${LOG_DIR}/profile_decode.out --overlap \ | ||||||||||||||
| bash -c "PROFILING_MODE=decode {% endraw %}{% if profiler == 'torch' %}SGLANG_TORCH_PROFILER_DIR=/logs/profiles/decode {% endif %}{{ decode_profile_env }}{% raw %} /scripts/profiling/profile.sh $PREFILL_WORKERS $DECODE_WORKERS $PREFILL_GPUS $DECODE_GPUS $TOTAL_GPUS" & | ||||||||||||||
| # Run a single profiling orchestrator that coordinates profiling across all leaders | ||||||||||||||
| srun --nodes=1 --ntasks=1 $ENROOT_ARGS --jobid $SLURM_JOB_ID -w $PROFILE_ORCHESTRATOR_NODE \ | ||||||||||||||
| --output=${LOG_DIR}/profile_all.out --overlap \ | ||||||||||||||
| bash -c "PROFILING_MODE=prefill PROFILE_PREFILL_IPS=${PREFILL_LEADER_IPS_STR} PROFILE_DECODE_IPS=${DECODE_LEADER_IPS_STR} {% endraw %}{% if profiler == 'torch' %}SGLANG_TORCH_PROFILER_DIR=/logs/profiles {% endif %}{{ prefill_profile_env }}{% raw %} /scripts/profiling/profile.sh $PREFILL_WORKERS $DECODE_WORKERS $PREFILL_GPUS $DECODE_GPUS $TOTAL_GPUS" & | ||||||||||||||
|
Comment on lines
+416
to
+418
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing The - bash -c "PROFILING_MODE=prefill PROFILE_PREFILL_IPS=${PREFILL_LEADER_IPS_STR} PROFILE_DECODE_IPS=${DECODE_LEADER_IPS_STR} {% endraw %}{% if profiler == 'torch' %}SGLANG_TORCH_PROFILER_DIR=/logs/profiles {% endif %}{{ prefill_profile_env }}{% raw %} /scripts/profiling/profile.sh $PREFILL_WORKERS $DECODE_WORKERS $PREFILL_GPUS $DECODE_GPUS $TOTAL_GPUS" &
+ bash -c "PROFILING_MODE=prefill HEAD_NODE=${nodes[0]} HEAD_PORT=8000 PROFILE_PREFILL_IPS=${PREFILL_LEADER_IPS_STR} PROFILE_DECODE_IPS=${DECODE_LEADER_IPS_STR} {% endraw %}{% if profiler == 'torch' %}SGLANG_TORCH_PROFILER_DIR=/logs/profiles {% endif %}{{ prefill_profile_env }}{% raw %} /scripts/profiling/profile.sh $PREFILL_WORKERS $DECODE_WORKERS $PREFILL_GPUS $DECODE_GPUS $TOTAL_GPUS" &Note: 📝 Committable suggestion
Suggested change
|
||||||||||||||
| {% endraw %} | ||||||||||||||
| {% endif %} | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential issue:
start_stepis passed as a string whilenum_stepsis an integer.In the JSON payload at line 118,
start_stepis quoted as a string (\"$PROFILE_START_STEP\") whilenum_stepsis computed as an integer. This inconsistency may cause issues if the server expects consistent types.Also update line 131 for consistency:
🤖 Prompt for AI Agents