259 lines
8.9 KiB
Bash
Executable File
259 lines
8.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# FlashAttention hardware-counter profile for MiniMax-H3 on 8x RTX 6000D.
|
|
# Four isolated TP2 services run concurrently:
|
|
# GPU 0-1: F3, cold-cache NCU replay
|
|
# GPU 2-3: F3, warm-cache NCU replay
|
|
# GPU 4-5: RVA, cold-cache NCU replay
|
|
# GPU 6-7: RVA, warm-cache NCU replay
|
|
set -Eeuo pipefail
|
|
|
|
ROOT=${ROOT:-/data/wxy}
|
|
RUN_ID=${RUN_ID:-h3-flashattention-ncu-$(date +%Y%m%d-%H%M%S)}
|
|
RESULT_ROOT=${RESULT_ROOT:-$ROOT/profile_results/$RUN_ID}
|
|
MODEL=${MODEL:-/data/hf_models/MiniMax-H3}
|
|
PYTHON=${PYTHON:-/root/.miniconda3/envs/sglang/bin/python}
|
|
SGLANG=${SGLANG:-/root/.miniconda3/envs/sglang/bin/sglang}
|
|
CLIENT=${CLIENT:-$ROOT/h3_profile/h3_profile_client.py}
|
|
NCU=${NCU:-/usr/local/cuda-13.2/bin/ncu}
|
|
MEDIA_BIN_DIR=${MEDIA_BIN_DIR:-/root/.miniconda3/envs/deploy/bin}
|
|
|
|
STEPS=${STEPS:-20}
|
|
DURATION=${DURATION:-5}
|
|
WARMUP_STEPS=${WARMUP_STEPS:-5}
|
|
BASE_PORT=${BASE_PORT:-30010}
|
|
PORT_STRIDE=${PORT_STRIDE:-10}
|
|
MASTER_PORT_BASE=${MASTER_PORT_BASE:-33000}
|
|
SCHEDULER_PORT_BASE=${SCHEDULER_PORT_BASE:-34000}
|
|
SERVER_START_TIMEOUT=${SERVER_START_TIMEOUT:-1800}
|
|
|
|
REFERENCE_IMAGE=${REFERENCE_IMAGE:-$ROOT/sskj-MiniMax-H3/assets/reference_images/landscape_mountain_lake.jpg}
|
|
REFERENCE_IMAGES_DIR=${REFERENCE_IMAGES_DIR:-$ROOT/h3_profile/assets/reference_images_5}
|
|
REFERENCE_VIDEO_1S=${REFERENCE_VIDEO_1S:-$MODEL/assets/r2va.mp4}
|
|
REFERENCE_VIDEO_5S=${REFERENCE_VIDEO_5S:-$MODEL/assets/ref2va.mp4}
|
|
REFERENCE_VIDEO_10S=${REFERENCE_VIDEO_10S:-$MODEL/assets/h3_direct_768p.mp4}
|
|
|
|
FLASH_REGEX=${FLASH_REGEX:-pytorch_flash::flash_fwd_kernel}
|
|
F3_LAUNCH_SKIP=${F3_LAUNCH_SKIP:-3734}
|
|
RVA_LAUNCH_SKIP=${RVA_LAUNCH_SKIP:-3921}
|
|
LAUNCH_COUNT=${LAUNCH_COUNT:-1}
|
|
|
|
declare -a SERVER_PIDS=() CLIENT_PIDS=()
|
|
|
|
log(){ printf '[%s] %s\n' "$(date '+%F %T')" "$*" | tee -a "$RESULT_ROOT/run.log"; }
|
|
die(){ log "ERROR: $*"; exit 1; }
|
|
|
|
port_open(){
|
|
"$PYTHON" - "$1" <<'PY'
|
|
import socket, sys
|
|
s = socket.socket()
|
|
s.settimeout(0.3)
|
|
try:
|
|
s.connect(("127.0.0.1", int(sys.argv[1])))
|
|
except OSError:
|
|
raise SystemExit(1)
|
|
raise SystemExit(0)
|
|
PY
|
|
}
|
|
|
|
wait_healthy(){
|
|
local port=$1 pid=$2 logfile=$3 deadline=$((SECONDS+SERVER_START_TIMEOUT))
|
|
while ((SECONDS < deadline)); do
|
|
if curl -fsS --max-time 2 "http://127.0.0.1:${port}/health" >/dev/null 2>&1; then return 0; fi
|
|
if ! kill -0 "$pid" 2>/dev/null; then tail -120 "$logfile"; return 1; fi
|
|
sleep 5
|
|
done
|
|
tail -120 "$logfile"
|
|
return 1
|
|
}
|
|
|
|
stop_servers(){
|
|
local p deadline alive
|
|
for p in "${SERVER_PIDS[@]:-}"; do
|
|
kill -INT -- "-$p" 2>/dev/null || kill -INT "$p" 2>/dev/null || true
|
|
done
|
|
deadline=$((SECONDS+180))
|
|
while ((SECONDS < deadline)); do
|
|
alive=0
|
|
for p in "${SERVER_PIDS[@]:-}"; do kill -0 "$p" 2>/dev/null && alive=1; done
|
|
((alive == 0)) && break
|
|
sleep 2
|
|
done
|
|
for p in "${SERVER_PIDS[@]:-}"; do
|
|
if kill -0 "$p" 2>/dev/null; then kill -TERM -- "-$p" 2>/dev/null || true; sleep 3; fi
|
|
if kill -0 "$p" 2>/dev/null; then kill -KILL -- "-$p" 2>/dev/null || true; fi
|
|
wait "$p" 2>/dev/null || true
|
|
done
|
|
SERVER_PIDS=()
|
|
}
|
|
|
|
cleanup(){
|
|
local rc=$? p
|
|
trap - EXIT INT TERM
|
|
for p in "${CLIENT_PIDS[@]:-}"; do kill -TERM "$p" 2>/dev/null || true; done
|
|
stop_servers
|
|
exit "$rc"
|
|
}
|
|
trap cleanup EXIT INT TERM
|
|
|
|
start_server(){
|
|
local replica=$1 variant=$2 gpus=$3 scenario=$4 cache_control=$5 launch_skip=$6
|
|
local port=$((BASE_PORT+replica*PORT_STRIDE))
|
|
local master=$((MASTER_PORT_BASE+replica*PORT_STRIDE))
|
|
local scheduler=$((SCHEDULER_PORT_BASE+replica*PORT_STRIDE))
|
|
local dir="$RESULT_ROOT/instances/replica_${replica}_${scenario}_${cache_control}"
|
|
local logfile="$dir/server.log"
|
|
mkdir -p "$dir/outputs" "$dir/ncu" "$dir/perf"
|
|
|
|
for p in "$port" "$((port+1))" "$master" "$scheduler"; do
|
|
port_open "$p" && die "port occupied: $p"
|
|
done
|
|
|
|
local -a sections=(
|
|
--set detailed
|
|
--section SchedulerStats
|
|
--section WarpStateStats
|
|
--section InstructionStats
|
|
)
|
|
local -a ncu_cmd=(
|
|
"$NCU"
|
|
--force-overwrite
|
|
--target-processes all
|
|
--kernel-name-base demangled
|
|
--kernel-name "regex:${FLASH_REGEX}"
|
|
--launch-skip "$launch_skip"
|
|
--launch-count "$LAUNCH_COUNT"
|
|
--replay-mode kernel
|
|
--cache-control "$cache_control"
|
|
--clock-control boost
|
|
"${sections[@]}"
|
|
--export "$dir/ncu/server"
|
|
)
|
|
local -a serve_cmd=(
|
|
"$SGLANG" serve
|
|
--model-path "$MODEL"
|
|
--model-variant "$variant"
|
|
--backend sglang
|
|
--performance-mode speed
|
|
--num-gpus 2
|
|
--tp-size 2
|
|
--ulysses-degree 1
|
|
--use-fsdp-inference false
|
|
--enable-torch-compile false
|
|
--batching-max-size 1
|
|
--batching-delay-ms 0
|
|
--enable-layerwise-nvtx-marker
|
|
--host 0.0.0.0
|
|
--port "$port"
|
|
--master-port "$master"
|
|
--scheduler-port "$scheduler"
|
|
--output-path "$dir/outputs"
|
|
--log-requests
|
|
--log-requests-level 2
|
|
)
|
|
|
|
printf '%q ' env CUDA_VISIBLE_DEVICES="$gpus" "${ncu_cmd[@]}" "${serve_cmd[@]}" > "$dir/command.txt"
|
|
printf '\n' >> "$dir/command.txt"
|
|
log "start replica=$replica scenario=$scenario GPUs=$gpus cache=$cache_control skip=$launch_skip port=$port"
|
|
CUDA_VISIBLE_DEVICES="$gpus" PATH="$MEDIA_BIN_DIR:$PATH" PYTHONUNBUFFERED=1 \
|
|
TOKENIZERS_PARALLELISM=false SGLANG_USE_RUNAI_MODEL_STREAMER=false \
|
|
SGLANG_DIFFUSION_STAGE_LOGGING=1 SGLANG_DIFFUSION_SYNC_STAGE_PROFILING=0 \
|
|
NCCL_DEBUG=WARN setsid "${ncu_cmd[@]}" "${serve_cmd[@]}" > "$logfile" 2>&1 &
|
|
SERVER_PIDS+=("$!")
|
|
}
|
|
|
|
run_client(){
|
|
local replica=$1 scenario=$2
|
|
local port=$((BASE_PORT+replica*PORT_STRIDE))
|
|
local cache_control=all
|
|
((replica % 2 == 1)) && cache_control=none
|
|
local dir="$RESULT_ROOT/instances/replica_${replica}_${scenario}_${cache_control}"
|
|
"$PYTHON" "$CLIENT" \
|
|
--deployment "FLASH_NCU_TP2_${cache_control}" \
|
|
--scenario "$scenario" \
|
|
--host 127.0.0.1 \
|
|
--port "$port" \
|
|
--replica-index "$replica" \
|
|
--model "$MODEL" \
|
|
--reference-image "$REFERENCE_IMAGE" \
|
|
--reference-images-dir "$REFERENCE_IMAGES_DIR" \
|
|
--reference-video-1s "$REFERENCE_VIDEO_1S" \
|
|
--reference-video-5s "$REFERENCE_VIDEO_5S" \
|
|
--reference-video-10s "$REFERENCE_VIDEO_10S" \
|
|
--steps "$STEPS" \
|
|
--duration "$DURATION" \
|
|
--short-edge 768 \
|
|
--aspect-ratio 16:9 \
|
|
--seed 1101 \
|
|
--repeats 1 \
|
|
--warmup 1 \
|
|
--warmup-steps "$WARMUP_STEPS" \
|
|
--perf-dir "$dir/perf" \
|
|
--output "$dir/results.jsonl" > "$dir/client.log" 2>&1
|
|
}
|
|
|
|
validate_report(){
|
|
local replica=$1 scenario=$2 expected_grid=$3
|
|
local cache_control=all
|
|
((replica % 2 == 1)) && cache_control=none
|
|
local dir="$RESULT_ROOT/instances/replica_${replica}_${scenario}_${cache_control}"
|
|
local report
|
|
report=$(find "$dir/ncu" -maxdepth 1 -name '*.ncu-rep' -print -quit)
|
|
[[ -n "$report" ]] || return 1
|
|
"$NCU" --import "$report" --page details --print-details all --csv > "$dir/ncu/details.csv" 2> "$dir/ncu/export.log"
|
|
grep -q "${expected_grid}, 1, 28" "$dir/ncu/details.csv" || grep -q "(${expected_grid}, 1, 28)" "$dir/ncu/details.csv"
|
|
}
|
|
|
|
mkdir -p "$RESULT_ROOT"/{metadata,instances,system}
|
|
cp "$0" "$RESULT_ROOT/metadata/$(basename "$0")"
|
|
date -Ins > "$RESULT_ROOT/metadata/date.txt"
|
|
nvidia-smi --query-gpu=index,name,uuid,memory.total,pci.bus_id,driver_version --format=csv > "$RESULT_ROOT/metadata/gpus.csv"
|
|
nvidia-smi topo -m > "$RESULT_ROOT/metadata/topology.txt"
|
|
"$NCU" --version > "$RESULT_ROOT/metadata/ncu-version.txt"
|
|
"$PYTHON" -m pip freeze > "$RESULT_ROOT/metadata/pip-freeze.txt"
|
|
|
|
log "launching four TP2 NCU services"
|
|
start_server 0 FL2VA 0,1 F3 all "$F3_LAUNCH_SKIP"
|
|
start_server 1 FL2VA 2,3 F3 none "$F3_LAUNCH_SKIP"
|
|
start_server 2 Ref2VA 4,5 RVA_EMBEDDED all "$RVA_LAUNCH_SKIP"
|
|
start_server 3 Ref2VA 6,7 RVA_EMBEDDED none "$RVA_LAUNCH_SKIP"
|
|
|
|
for replica in 0 1 2 3; do
|
|
port=$((BASE_PORT+replica*PORT_STRIDE))
|
|
scenario=F3
|
|
((replica >= 2)) && scenario=RVA_EMBEDDED
|
|
cache_control=all
|
|
((replica % 2 == 1)) && cache_control=none
|
|
logfile="$RESULT_ROOT/instances/replica_${replica}_${scenario}_${cache_control}/server.log"
|
|
wait_healthy "$port" "${SERVER_PIDS[$replica]}" "$logfile" || die "server failed: $logfile"
|
|
log "replica=$replica healthy port=$port"
|
|
done
|
|
|
|
nvidia-smi dmon -s pucvmet -d 2 -o DT > "$RESULT_ROOT/system/nvidia-dmon.log" 2>&1 &
|
|
DMON_PID=$!
|
|
|
|
log "starting F3/F3/RVA/RVA clients concurrently"
|
|
run_client 0 F3 & CLIENT_PIDS+=("$!")
|
|
run_client 1 F3 & CLIENT_PIDS+=("$!")
|
|
run_client 2 RVA_EMBEDDED & CLIENT_PIDS+=("$!")
|
|
run_client 3 RVA_EMBEDDED & CLIENT_PIDS+=("$!")
|
|
|
|
failed=0
|
|
for p in "${CLIENT_PIDS[@]}"; do wait "$p" || failed=1; done
|
|
CLIENT_PIDS=()
|
|
kill -TERM "$DMON_PID" 2>/dev/null || true
|
|
wait "$DMON_PID" 2>/dev/null || true
|
|
((failed == 0)) || die "one or more clients failed"
|
|
|
|
log "clients completed; stopping services so NCU can finalize reports"
|
|
stop_servers
|
|
|
|
validation_failed=0
|
|
validate_report 0 F3 327 || validation_failed=1
|
|
validate_report 1 F3 327 || validation_failed=1
|
|
validate_report 2 RVA_EMBEDDED 638 || validation_failed=1
|
|
validate_report 3 RVA_EMBEDDED 638 || validation_failed=1
|
|
((validation_failed == 0)) || die "NCU report missing or captured the wrong FlashAttention grid"
|
|
|
|
touch "$RESULT_ROOT/DONE"
|
|
log "DONE: $RESULT_ROOT"
|