26S30m

QK·3일 전
#!/usr/bin/env bash
# ==========================================================================
# STAGE 3a-8 (신규): Prefix Caching 진짜 A/B 비교
# 기존 stage3a 시나리오3은 "on일 때 이 정도"만 봤음 — 여기서는 정확히 동일한
# 32k 고정 프리픽스 반복 워크로드를 on/off 두 번 돌려서 순수 캐싱 효과만 분리.
# ==========================================================================
set -euo pipefail

export HF_HUB_OFFLINE=1
export TRANSFORMERS_OFFLINE=1
export HF_DATASETS_OFFLINE=1

LOCAL_MODEL_ROOT="${LOCAL_MODEL_ROOT:-/mnt/local-nvme-cache/models}"
MODEL_70B="${MODEL_70B:-${LOCAL_MODEL_ROOT}/Meta-Llama-3.1-70B-Instruct}"
[ -d "${MODEL_70B}" ] || { echo "모델 없음: ${MODEL_70B}"; exit 1; }

TP_SIZE=8
VLLM_PORT=8000
SERVER_HOST="127.0.0.1"
LOG_DIR="/var/log/b300_validation/stage3a8_prefixab_$(date +%Y%m%d_%H%M%S)"
mkdir -p "${LOG_DIR}"
log() { echo -e "\n\033[1;32m[$(date '+%Y-%m-%d %H:%M:%S')] $1\033[0m"; }
source ~/vllm-bench-env/bin/activate

run_case() {
    local tag=$1 cache_flag=$2
    log "서버 기동: ${tag} (${cache_flag})"
    python3 -m vllm.entrypoints.openai.api_server \
        --model "${MODEL_70B}" --served-model-name "llama-3.1-70b" \
        --tensor-parallel-size "${TP_SIZE}" --gpu-memory-utilization 0.90 --max-model-len 65536 \
        ${cache_flag} \
        --port "${VLLM_PORT}" > "${LOG_DIR}/server_${tag}.log" 2>&1 &
    SERVER_PID=$!
    until curl -s "http://${SERVER_HOST}:${VLLM_PORT}/v1/models" > /dev/null 2>&1; do
        kill -0 "${SERVER_PID}" 2>/dev/null || { echo "기동 실패: ${LOG_DIR}/server_${tag}.log"; exit 1; }
        sleep 5
    done

    # 동일한 32k 고정 프리픽스를 8동시성으로 30개 반복 — stage3a 시나리오3과 동일 조건
    vllm bench serve \
        --backend openai-chat --endpoint /v1/chat/completions \
        --host "${SERVER_HOST}" --port "${VLLM_PORT}" \
        --model "llama-3.1-70b" --tokenizer "${MODEL_70B}" \
        --dataset-name random --random-input-len 32768 --random-output-len 256 \
        --random-prefix-len 32000 \
        --num-prompts 30 --max-concurrency 8 --request-rate inf \
        --save-result --result-dir "${LOG_DIR}" --result-filename "${tag}.json" || true

    kill -TERM "${SERVER_PID}" 2>/dev/null || true
    wait "${SERVER_PID}" 2>/dev/null || true
    sleep 3
}

run_case "prefix_cache_on"  "--enable-prefix-caching"
run_case "prefix_cache_off" "--no-enable-prefix-caching"

log "=== 결과 비교 ==="
python3 - << PYEOF
import json, os
log_dir = "${LOG_DIR}"

def load(tag):
    fp = os.path.join(log_dir, f"{tag}.json")
    if not os.path.exists(fp): return {}
    try: return json.load(open(fp))
    except Exception: return {}

on = load("prefix_cache_on")
off = load("prefix_cache_off")

ttft_on = on.get("median_ttft_ms", 0)
ttft_off = off.get("median_ttft_ms", 0)
speedup = (ttft_off / ttft_on) if ttft_on else 0

report = f"""# Stage3a-8 Prefix Caching A/B 결과 (동일 32k 고정 프리픽스, concurrency=8)

| 조건 | Median TTFT |
|---|---|
| Cache OFF (기준) | {ttft_off:.1f}ms |
| Cache ON | {ttft_on:.1f}ms |

**단축 배율: {speedup:.1f}x**

## 판정 기준
- 5~10배 이상 단축되면 정상적으로 캐싱이 동작하는 것 (이전 3단계 설계 문서의 Pass Criteria와 동일 기준)
- 단축 배율이 2배 미만이면 캐시가 제대로 히트하지 않고 있다는 신호 — 캐시 블록 크기,
  KV 캐시 메모리 여유(--gpu-memory-utilization), 요청 간 프리픽스가 정말 동일한지 재확인 필요
"""
with open(f"{log_dir}/prefix_cache_ab_report.md", "w") as f:
    f.write(report)
print(report)
PYEOF
log "Prefix Caching A/B 완료! 리포트: ${LOG_DIR}/prefix_cache_ab_report.md"
profile
engineer

0개의 댓글