### DeepSeek-R1 HLE 提出用ランブック(更新版 / vLLM 2ノード16GPU 実績反映)
本書は、HLE評価に向けて提出物(モデル+sbatch+config)を実運用で通った最新構成に更新した手順書です。以下はログインノードでの準備から、2ノード×8GPU(計16GPU)でのvLLM起動、推論・採点までを一気通貫でカバーします。
---
## 1. 事前準備
```bash
# 評価スクリプトを取得(既存なら最新化のみ)
git clone https://github.com/matsuolab/llm_bridge_prod.git || true
cd ~/llm_bridge_prod
git fetch --all --prune
git checkout master 2>/dev/null || git checkout main
git pull --ff-only
# 個人ログ出力先(書き込み権限制約回避のためホーム配下推奨)
mkdir -p "$HOME/logs"
# ~/llm_bridge_prod/eval_hle/conf/config.yaml
dataset: cais/hle
provider: vllm
base_url: http://127.0.0.1:8000/v1
model: deepseek-r1
max_completion_tokens: 6500 # 上限: 8192 - (入力トークン) を超えないように注意
reasoning: true
temperature: 0.0
num_workers: 2500
max_samples: 2500
judge: o3-mini-2025-01-31
注意: 400 Bad Request(8192超過)が多発する場合は、max_completion_tokens を一時的に下げるか、呼び出し側で動的に上限を調整してください。
以下の内容で ~/run_deepseek.sbatch を作成します。今回の成功構成を反映し、環境混在防止・Ray/vLLMの安定化・APIキーの分離・レディネス確認などを取り込み済みです。
cat > ~/run_deepseek.sbatch <<'SBATCH'
#!/bin/bash
#SBATCH --job-name=deepseek_r1_hle
#SBATCH --partition=P10
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=1
#SBATCH --gpus-per-node=8
#SBATCH --cpus-per-task=240
#SBATCH --mem=0
#SBATCH --time=12:00:00
# 出力はホーム配下の個人ログに(権限問題を回避)
# 必要に応じて変更可: LOG_DIR=/home/Competition2025/P10/P10U017/logs など
#SBATCH --output=%x-%j.out
#SBATCH --error=%x-%j.err
#SBATCH --export=ALL
set -euo pipefail
#=============== ユーザ設定(必要なら書き換え) ===============
LOG_DIR="${LOG_DIR:-$HOME/logs}"
MODEL_PATH="${MODEL_PATH:-/home/Competition2025/P10/shareP10/llm_project/models/deepseek/deepseek-r1-0528-merged/20250814_run1/fp8}"
DEEPSEEK_ENV="${DEEPSEEK_ENV:-$HOME/conda_env_llm}"
VLLM_API_KEY="${VLLM_API_KEY:-p10-deepseek-key}"
#=============== モード切替(--skip-env対応) ===============
MODE_ARG="${1:-}"
case "$MODE_ARG" in
--skip-env) SKIP_ENV_SETUP=1 ;;
--setup-env) SKIP_ENV_SETUP=0 ;;
*) : ;;
esac
: "${SKIP_ENV_SETUP:=0}"
mkdir -p "$LOG_DIR"
#=============== 前処理 / 片付け ===============
cleanup () {
[[ -n "${pid_vllm:-}" ]] && kill "${pid_vllm}" 2>/dev/null || true
[[ -n "${pid_vllm_pretty:-}" ]] && kill "${pid_vllm_pretty}" 2>/dev/null || true
[[ -n "${pid_nvsmi:-}" ]] && kill "${pid_nvsmi}" 2>/dev/null || true
srun -N ${SLURM_NNODES:-1} -n ${SLURM_NNODES:-1} /bin/bash -lc '
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
conda activate '"""$DEEPSEEK_ENV"""' || true
timeout 10s ray stop --force || true
pkill -9 ray || true
pkill -9 gcs_server || true
find /tmp/ray -maxdepth 1 -type d -name "session_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
find /tmp -maxdepth 1 -type d -name "ray_tmp_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
rm -rf /dev/shm/ray* 2>/dev/null || true
' >/dev/null 2>&1 || true
}
export PYTHONNOUSERSITE=1
unset PYTHONPATH
export PIP_USER=no
export TORCH_COMPILE_DISABLE=1
export TORCHDYNAMO_DISABLE=1
trap cleanup EXIT ERR SIGINT SIGTERM SIGQUIT
#=============== Hugging Face 認証とキャッシュ ===============
export HF_TOKEN="${HF_TOKEN:-<your_hf_token>}"
export HF_HOME=${SLURM_TMPDIR:-$HOME}/.hf_cache
export TRANSFORMERS_CACHE=$HF_HOME
export HUGGINGFACE_HUB_TOKEN=$HF_TOKEN
mkdir -p "$HF_HOME"
#=============== GPU 監視 ======================
nvidia-smi -i 0,1,2,3,4,5,6,7 -l 3 > "$LOG_DIR/nvidia-smi.$SLURM_JOB_ID.log" &
pid_nvsmi=$!
#=============== モジュールと Conda 環境(条件付き) ===============
module reset
module load nccl/2.24.3
module load hpcx/2.18.1-gcc-cuda12/hpcx-mt
module load cudnn/9.4.0
module load miniconda/24.7.1-py311
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
if [[ "$SKIP_ENV_SETUP" -eq 1 ]]; then
conda activate "$DEEPSEEK_ENV" || true
export PATH="$DEEPSEEK_ENV/bin:$PATH"
else
[ -d "$DEEPSEEK_ENV" ] && conda env remove --prefix "$DEEPSEEK_ENV" -y && rm -rf "$DEEPSEEK_ENV"
conda create --prefix "$DEEPSEEK_ENV" python=3.11 -y
conda activate "$DEEPSEEK_ENV"
export PATH="$DEEPSEEK_ENV/bin:$PATH"
conda install cuda-toolkit=12.6 -c conda-forge -y
conda install gcc_linux-64 gxx_linux-64 -y
pip install --upgrade pip wheel cmake ninja
pip install huggingface-hub hydra-core openai
pip cache purge && rm -rf ~/.cache/pip/*
pip install vllm==0.9.2
pip install --index-url https://download.pytorch.org/whl/cu126 torch==2.7.0 torchvision==0.22.0+cu126 torchaudio==2.7.0
pip install "ray[cgraph,data,train,tune,serve]==2.43.0"
pip install transformers==4.53.2 accelerate==1.2.1 sentencepiece==0.2.0 \
protobuf==4.25.5 pydantic==2.10.3 aiohttp==3.11.10 \
numpy==2.2.6 scipy==1.14.1 datasets requests tqdm psutil gputil
pip install https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.2/flash_attn-2.8.2+cu12torch2.7cxx11abiTRUE-cp311-cp311-linux_x86_64.whl
pip install flashinfer-python
fi
#=============== Ray 前処理(自分の所有物のみ掃除) ===============
srun -N ${SLURM_NNODES:-1} -n ${SLURM_NNODES:-1} /bin/bash -lc '
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
conda activate '"""$DEEPSEEK_ENV"""' || true
export PYTHONNOUSERSITE=1; unset PYTHONPATH; export PATH="'""$DEEPSEEK_ENV"""/bin:$PATH"
timeout 10s ray stop --force || true
pkill -9 ray || true
pkill -9 gcs_server || true
find /tmp/ray -maxdepth 1 -type d -name "session_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
find /tmp -maxdepth 1 -type d -name "ray_tmp_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
rm -rf /dev/shm/ray* 2>/dev/null || true
'
#=============== ノード情報・Ray起動 ===============
HOSTS=($(scontrol show hostnames "$SLURM_JOB_NODELIST"))
HEAD_NODE=${HOSTS[0]}
HEAD_IF=enp25s0np0
HEAD_IP=$(ip -o -4 addr show dev "$HEAD_IF" | awk '{print $4}' | cut -d/ -f1)
[[ -z "$HEAD_IP" ]] && HEAD_IP=$(hostname -i | awk '{print $1}')
export RAY_TMPDIR="${SLURM_TMPDIR:-/tmp}/ray-${SLURM_JOB_ID:-manual}"
mkdir -p "$RAY_TMPDIR"
export VLLM_HOST_IP=$HEAD_IP # Rayのnodeラベル用に実IPを使う
export NCCL_SOCKET_IFNAME=enp25s0np0
export NCCL_IB_DISABLE=0
ray start --head --node-ip-address="$HEAD_IP" --port=6379 \
--dashboard-host=0.0.0.0 --dashboard-port=8265 \
--temp-dir "$RAY_TMPDIR"
export RAY_ADDRESS=$HEAD_IP:6379
if [[ ${#HOSTS[@]} -gt 1 ]]; then
for node in "${HOSTS[@]:1}"; do
srun -N1 -n1 -w "$node" /bin/bash -lc '
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
conda activate '"""$DEEPSEEK_ENV"""' || true
export PYTHONNOUSERSITE=1; unset PYTHONPATH; export PATH="'""$DEEPSEEK_ENV"""/bin:$PATH"
export NCCL_SOCKET_IFNAME=enp25s0np0; export NCCL_IB_DISABLE=0
export RAY_TMPDIR="${SLURM_TMPDIR:-/tmp}/ray-${SLURM_JOB_ID:-manual}"
mkdir -p "$RAY_TMPDIR"
IF=enp25s0np0
WORKER_IP=$(ip -o -4 addr show dev "$IF" | awk "{print \$4}" | cut -d/ -f1)
[[ -z "$WORKER_IP" ]] && WORKER_IP=$(hostname -i | awk "{print \$1}")
export VLLM_HOST_IP=$WORKER_IP
ray start --address="'""$RAY_ADDRESS""'" --node-ip-address="$WORKER_IP" \
--temp-dir "$RAY_TMPDIR" --block
' &
done
for i in {1..60}; do
ok=$(srun -N1 -n1 -w "$HEAD_NODE" /bin/bash -lc '
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
conda activate '"""$DEEPSEEK_ENV"""' || true
python - <<PY
import os, ray
ray.init(address=os.environ.get("RAY_ADDRESS","auto"), log_to_driver=False)
print(len(ray.nodes()))
PY
' 2>/dev/null | tail -n1)
[[ "$ok" == "${SLURM_NNODES}" ]] && echo "all workers joined" && break
sleep 2
done
fi
#=============== vLLM サーバ起動(バックグラウンド) ===============
cat > deepseek_server.sh << 'EOF'
#!/bin/bash
export MODEL_PATH="'""$MODEL_PATH""'"
export CUDA_VISIBLE_DEVICES=0,1,2,3,4,5,6,7
export NCCL_SOCKET_IFNAME=enp25s0np0
export NCCL_IB_DISABLE=0
export NCCL_DEBUG=WARN
export RAY_ADDRESS=${RAY_ADDRESS:-"auto"}
export PYTORCH_CUDA_ALLOC_CONF=max_split_size_mb:128
export CUDA_LAUNCH_BLOCKING=1
"'""$DEEPSEEK_ENV""'"/bin/python -m vllm.entrypoints.openai.api_server --model "$MODEL_PATH" \
--served-model-name deepseek-r1 \
--tensor-parallel-size 16 \
--enable-expert-parallel \
--distributed-executor-backend ray \
--trust-remote-code \
--dtype auto \
--gpu-memory-utilization 0.90 \
--max-model-len 8192 \
--max-num-seqs 80 \
--max-num-batched-tokens 32768 \
--host 0.0.0.0 --port 8000 \
--api-key "'""$VLLM_API_KEY""'" \
--enforce-eager --disable-log-requests \
--swap-space 16
EOF
chmod +x deepseek_server.sh
./deepseek_server.sh > "$LOG_DIR/vllm_server.$SLURM_JOB_ID.log" 2>&1 & pid_vllm=$!
stdbuf -oL -eL tail -n +1 -F "$LOG_DIR/vllm_server.$SLURM_JOB_ID.log" \
| awk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), "[vllm]", $0; fflush(); }' \
> "$LOG_DIR/vllm_server.$SLURM_JOB_ID.pretty.log" & pid_vllm_pretty=$!
#=============== レディネス確認 ===============
OPENAI_BASE_URL="http://127.0.0.1:8000/v1"
for i in $(seq 1 180); do
resp=$(curl -fsS --max-time 2 -H "Authorization: Bearer ${VLLM_API_KEY}" \
"${OPENAI_BASE_URL}/models" 2>/dev/null || true)
echo "$resp" | grep -q '"id"[[:space:]]*:[[:space:]]*"deepseek-r1"' && echo "vLLM HTTP API is ready." && break
sleep 2
done
#=============== 推論・評価 ===============
cd ~/llm_bridge_prod/eval_hle/ || exit 0
mkdir -p predictions judged
"$DEEPSEEK_ENV/bin/python" predict.py > predict.log 2>&1
"$DEEPSEEK_ENV/bin/python" judge.py > judge.log 2>&1
#=============== 後片付け ===============
kill "${pid_vllm}" 2>/dev/null || true
kill "${pid_vllm_pretty}" 2>/dev/null || true
kill "${pid_nvsmi}" 2>/dev/null || true
srun -N ${SLURM_NNODES:-1} -n ${SLURM_NNODES:-1} /bin/bash -lc '
source /home/appli/miniconda3/24.7.1-py311/etc/profile.d/conda.sh
conda activate '"""$DEEPSEEK_ENV"""' || true
timeout 10s ray stop --force || true
pkill -9 ray || true
pkill -9 gcs_server || true
find /tmp/ray -maxdepth 1 -type d -name "session_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
find /tmp -maxdepth 1 -type d -name "ray_tmp_*" -user "$USER" -print0 2>/dev/null | xargs -0r rm -rf
rm -rf /dev/shm/ray* 2>/dev/null || true
' || true
echo "Done. Logs: $LOG_DIR"
SBATCH
投入例(Judge用 OpenAI キーは投入時に渡す):
sbatch -p P10 --export=ALL,OPENAI_API_KEY=sk-xxxxxxxx ~/run_deepseek.sbatch
# 既存環境で推論のみ
sbatch -p P10 --export=ALL,OPENAI_API_KEY=sk-xxxxxxxx ~/run_deepseek.sbatch --skip-env
MODEL_PATH は環境に合わせて変更してください(例・実績):
export MODEL_PATH=/home/Competition2025/P10/shareP10/llm_project/models/deepseek/deepseek-r1-0528-merged/20250814_run1/fp8
JOBID=$(squeue -u $USER -h -o %A | tail -1)
WORKDIR=$(scontrol show job "$JOBID" | tr ' ' '\n' | awk -F= '$1=="WorkDir"{print $2; exit}')
tail -n 200 -F -v "$LOG_DIR/vllm_server.$JOBID.pretty.log"
export PYTHONNOUSERSITE=1, unset PYTHONPATH, export PATH="$DEEPSEEK_ENV/bin:$PATH" をヘッド/ワーカー両方で適用。"$DEEPSEEK_ENV/bin/python" -m vllm.entrypoints.openai.api_server に固定。--enforce-eager を付与。精度影響なし(性能面のみ)。TORCH_COMPILE_DISABLE=1, TORCHDYNAMO_DISABLE=1 を設定。VLLM_API_KEY(本手順では p10-deepseek-key を既定)。sbatch --export で投入時に受け渡し。http://127.0.0.1:8000/v1/models に Bearer VLLM_API_KEY で確認。--node-ip-address=$HEAD_IP, --port=6379 明示、ワーカーは --address=$RAY_ADDRESS。--host 0.0.0.0 でHTTP待受。VLLM_HOST_IP はRayリソース判定用に各ノード実IPを使用。LOG_DIR=$HOME/logs を既定に。必要に応じて共有領域へ変更可。cd ~/llm_bridge_prod/eval_hle/ など絶対パス/環境依存を低減。max_completion_tokens + 入力トークン > 8192 で発生します。頻発時は次のいずれかで緩和してください。
conf/config.yaml の max_completion_tokens を一時的に小さくする。max_completion_tokens を 8192 - 入力 - マージン に丸める(推奨)。以上で、提出用の sbatch / config による HLE 推論~採点が再現可能です。