发布时间:2026/8/26 18:40:40
Vllm LINUX部署Qwen3.8-27B多模态支持视频图片模型全流程(8张L20卡) 一.环境准备1.安装python虚拟环境,安装VLLMsudo dnf install -y gcc openssl-devel bzip2-devel libffi-devel xz-devel sqlite-devel sudo dnf install python3-devel libxml2-devel libxslt-devel zlib-devel pcre-devel openssl-devel sudo wget https://www.python.org/ftp/python/3.11.6/Python-3.11.6.tgz tar xvf Python-3.11.6.tgz cd Python-3.11.6 ./configure --enable-optimizations make -j$(nproc) sudo make install #验证 /usr/local/bin/python3.11 --version #创建虚拟环境 python3 -m venv vllm_env #激活虚拟环境 source vllm_env/bin/activate # #安装 vllm pip3 install vllm0.25.02.安装英伟达显卡驱动wget https://mirrors.tencentyun.com/install/GPU/NVIDIA-Linux-x86_64-580.82.07.run chmod x NVIDIA-Linux-x86_64-580.82.07.run ./NVIDIA-Linux-x86_64-580.82.07.run -x cd NVIDIA-Linux-x86_64-580.82.07 ./nvidia-installer #查看显卡 lspci | grep -i nvidia #查看驱动英伟达显卡 nvidia-smi #实时监控 watch -n 1 nvidia-smi #toolkit ✅ 安装到 /data 目录 步骤 1创建目标目录 bash sudo mkdir -p /data/cuda-root 步骤 2使用 --installroot 安装到 /data bash sudo yum install -y --installroot/data/cuda-root cuda-toolkit-12-5 步骤 3安装完成后CUDA 文件在 /data/cuda-root/usr/local/cuda-12.5 bash ls -la /data/cuda-root/usr/local/ 步骤 4创建软链接 bash sudo ln -sf /data/cuda-root/usr/local/cuda-12.5 /data/cuda-12.5 步骤 5设置环境变量 bash echo export CUDA_HOME/data/cuda-12.5 ~/.bashrc echo export PATH$CUDA_HOME/bin:$PATH ~/.bashrc source ~/.bashrc 步骤 6验证 bash /data/cuda-12.5/bin/nvcc --version3.模型下载#魔塔社区下载模型 pip3 install modelscope modelscope download --model Qwen/Qwen3.8-27B --local_dir /data/app/model/Qwen3.8-27B #huggingface下载模型 # 设置环境变量使用 HF 镜像 pip install -U huggingface_hub export HF_TOKENhf_your_token_here export HF_ENDPOINThttps://hf-mirror.com hf download tencent/Qwen3.8-27B \ --local-dir /data/app/model/Hy/Qwen3.8-27B4.启动脚本编写启动脚本(3卡实例不支持改模型)#!/bin/bash # # vLLM 生产级部署脚本 - v0.25.0 # 模型: Qwen3.8-27B # 使用: ./deploy.sh [single|dual|3card|4card|auto] # set -uo pipefail # 信号处理 trap log_info 收到退出信号正在清理...; kill $(jobs -p) 2/dev/null; exit SIGTERM SIGINT # 缓存目录设置 export VLLM_CACHE_ROOT/run/vllm_cache export TMPDIR/run/tmp mkdir -p /run/vllm_cache /run/tmp chmod 1777 /run/tmp SCRIPT_DIR$(cd $(dirname ${BASH_SOURCE[0]}) pwd) # CUDA 环境变量 export CUDA_HOME/data/cuda-12.5 export PATH$CUDA_HOME/bin:$PATH # 核心配置 MODEL_PATH/data/app/model/Qwen/Qwen3.8-27B SERVED_NAMEQwen3.8-27B VENV_PATH/data/app/vllm_env # 性能调优参数 MAX_MODEL_LEN102400 MAX_NUM_SEQS24 GPU_MEMORY_UTIL0.85 KV_CACHE_DTYPEfp8 ENABLE_CHUNKED_PREFILLfalse # MTP 配置 ENABLE_MTPtrue MTP_NUM_SPECULATIVE_TOKENS3 # 路径配置 LOG_DIR${SCRIPT_DIR}/vllm_logs PID_DIR${SCRIPT_DIR}/vllm_pids mkdir -p $LOG_DIR $PID_DIR # 颜色输出 GREEN\033[0;32m RED\033[0;31m YELLOW\033[1;33m BLUE\033[0;34m NC\033[0m log_info() { echo -e ${GREEN}[INFO]${NC} $1; } log_error() { echo -e ${RED}[ERROR]${NC} $1; } log_warn() { echo -e ${YELLOW}[WARN]${NC} $1; } log_model() { echo -e ${BLUE}[MODEL]${NC} $1; } # 获取部署模式名称 get_deploy_mode_name() { local tp$1 case $tp in 1) echo 单卡 ;; 2) echo 双卡 ;; 3) echo 三卡 ;; 4) echo 四卡 ;; *) echo ${tp}卡 ;; esac } # 解析部署模式 parse_deploy_mode() { local mode${1:-auto} case $mode in single) NUM_INSTANCES8 TENSOR_PARALLEL_SIZE1 BASE_PORT8000 log_info 部署模式: 单卡 (8实例 × 1卡, 端口8000-8007) ;; dual) NUM_INSTANCES4 TENSOR_PARALLEL_SIZE2 BASE_PORT8000 log_info 部署模式: 双卡 (4实例 × 2卡, 端口8000-8003) ;; 3card) NUM_INSTANCES2 TENSOR_PARALLEL_SIZE3 BASE_PORT8000 log_info 部署模式: 三卡 (2实例 × 3卡, 端口8000-8001) ;; 4card) NUM_INSTANCES2 TENSOR_PARALLEL_SIZE4 BASE_PORT8000 log_info 部署模式: 四卡 (2实例 × 4卡, 端口8000-8001) ;; auto|*) # 自动检测根据 GPU 数量决定 local gpu_count$(nvidia-smi --query-gpuname --formatcsv,noheader 2/dev/null | wc -l) if [ $gpu_count -ge 8 ]; then NUM_INSTANCES8 TENSOR_PARALLEL_SIZE1 log_info 自动检测: 8 GPU使用单卡模式 elif [ $gpu_count -ge 4 ]; then NUM_INSTANCES4 TENSOR_PARALLEL_SIZE2 log_info 自动检测: 4-7 GPU使用双卡模式 else log_error GPU 数量不足 (需要至少4张): $gpu_count exit 1 fi BASE_PORT8000 ;; esac local total_gpus$((NUM_INSTANCES * TENSOR_PARALLEL_SIZE)) log_info 实例数: $NUM_INSTANCES log_info TP大小: $TENSOR_PARALLEL_SIZE log_info 总GPU: $total_gpus } # 激活虚拟环境 activate_venv() { if [ ! -d $VENV_PATH ]; then log_error 虚拟环境不存在: $VENV_PATH exit 1 fi source $VENV_PATH/bin/activate log_info 已激活虚拟环境: $VENV_PATH if ! command -v nvcc /dev/null; then log_error nvcc 未找到请检查 CUDA 安装 exit 1 fi log_info CUDA 版本: $(nvcc --version | grep release | awk {print $6} | sed s/,//) } # 等待服务启动 wait_for_service() { local port$1 local instance_name$2 local max_wait600 local wait_time0 local interval5 log_info 等待 $instance_name (端口 $port) 服务启动... while [ $wait_time -lt $max_wait ]; do if netstat -tln 2/dev/null | grep -q :$port; then local http_code$(curl -s -o /dev/null -w %{http_code} http://127.0.0.1:$port/v1/models 2/dev/null) if [ $http_code 200 ]; then log_info ✅ $instance_name 已就绪 (耗时 ${wait_time}s) return 0 fi fi sleep $interval wait_time$((wait_time interval)) [ $((wait_time % 30)) -eq 0 ] log_info 等待 $instance_name ... (已等待 ${wait_time}s) done log_error $instance_name 等待超时 (${max_wait}s) return 1 } # 启动单个实例 start_instance() { local instance_id$1 local port$((BASE_PORT instance_id)) # 计算 GPU 分配 local gpu_start$((instance_id * TENSOR_PARALLEL_SIZE)) local gpu_end$((gpu_start TENSOR_PARALLEL_SIZE - 1)) local gpu_list$(seq -s , $gpu_start $gpu_end) local LOG_FILE$LOG_DIR/instance_${instance_id}.log local PID_FILE$PID_DIR/instance_${instance_id}.pid log_model 启动实例 $instance_id: GPU$gpu_list, 端口$port log_info 日志: $LOG_FILE # MTP 参数 local MTP_ARG if [ $ENABLE_MTP true ]; then MTP_ARG--speculative-config {\method\:\mtp\,\num_speculative_tokens\:$MTP_NUM_SPECULATIVE_TOKENS} log_info MTP 已启用: num_speculative_tokens$MTP_NUM_SPECULATIVE_TOKENS fi # 启动进程 CUDA_VISIBLE_DEVICES$gpu_list \ vllm serve \ --model $MODEL_PATH \ --served-model-name $SERVED_NAME \ --tensor-parallel-size $TENSOR_PARALLEL_SIZE \ --max-model-len $MAX_MODEL_LEN \ --max-num-seqs $MAX_NUM_SEQS \ --enable-auto-tool-choice \ --tool-call-parser hermes \ --gpu-memory-utilization $GPU_MEMORY_UTIL \ ${KV_CACHE_DTYPE:--kv-cache-dtype $KV_CACHE_DTYPE} \ $( [ $ENABLE_CHUNKED_PREFILL true ] echo --enable-chunked-prefill ) \ --port $port \ --host 0.0.0.0 \ --enable-log-requests \ ${MTP_ARG} \ $LOG_FILE 21 local pid$! echo $pid $PID_FILE log_info PID: $pid sleep 2 } # 启动所有实例 start_instances() { log_info log_info 启动 $NUM_INSTANCES 个 vLLM 实例... log_info 模型: $SERVED_NAME log_info for ((i0; iNUM_INSTANCES; i)); do start_instance $i done log_info sleep 2 } # 验证所有实例 verify_instances() { log_info log_info 等待所有实例启动完成... log_info 注意: 首次启动可能需要 5-10 分钟进行 torch.compile log_info local all_readytrue for ((i0; iNUM_INSTANCES; i)); do local port$((BASE_PORT i)) if ! wait_for_service $port 实例$((i1)); then all_readyfalse log_error 实例 $((i1)) (端口 $port) 启动失败 log_info 查看日志: tail -100 $LOG_DIR/instance_${i}.log fi done echo if [ $all_ready true ]; then log_info log_info ✅ 所有实例已成功启动 log_info log_info log_model $SERVED_NAME log_info 部署模式: $(get_deploy_mode_name $TENSOR_PARALLEL_SIZE) log_info 实例数: $NUM_INSTANCES log_info TP 大小: $TENSOR_PARALLEL_SIZE log_info 总 GPU: $((NUM_INSTANCES * TENSOR_PARALLEL_SIZE)) 张 log_info for ((i0; iNUM_INSTANCES; i)); do local port$((BASE_PORT i)) local gpu_start$((i * TENSOR_PARALLEL_SIZE)) local gpu_end$((gpu_start TENSOR_PARALLEL_SIZE - 1)) log_info 端口 $port: GPU $gpu_start-$gpu_end done log_info log_info 测试命令: for ((i0; iNUM_INSTANCES; i)); do log_info curl http://127.0.0.1:$((BASE_PORT i))/v1/models done log_info return 0 else log_error log_error ❌ 部分实例启动失败请检查日志 log_error return 1 fi } # 主流程 main() { # 解析部署模式从命令行参数 parse_deploy_mode ${1:-auto} log_info log_info vLLM 0.25.0 单模型多实例部署 log_info 模型: $SERVED_NAME log_info 模式: $(get_deploy_mode_name $TENSOR_PARALLEL_SIZE) log_info 实例: $NUM_INSTANCES 个 (TP$TENSOR_PARALLEL_SIZE) log_info 端口: $BASE_PORT-$((BASE_PORT NUM_INSTANCES - 1)) log_info activate_venv start_instances verify_instances } # # 主进程保持运行等待所有子进程 # main $ JOBS$(jobs -p) if [ -n $JOBS ]; then log_info 脚本进入守护模式等待 $NUM_INSTANCES 个 vLLM 进程... log_info 子进程 PIDs: $JOBS wait log_warn 所有 vLLM 子进程已退出脚本结束 else log_error 没有后台子进程脚本退出 exit 1 fi停止脚本#!/bin/bash # # vLLM 生产级停止脚本彻底版 # set -e SCRIPT_DIR$(cd $(dirname ${BASH_SOURCE[0]}) pwd) PID_DIR${SCRIPT_DIR}/vllm_pids log_info() { echo -e \033[0;32m[INFO]\033[0m $1; } log_warn() { echo -e \033[1;33m[WARN]\033[0m $1; } log_error() { echo -e \033[0;31m[ERROR]\033[0m $1; } stop_instances() { log_info 正在停止所有 vLLM 实例... # 1. 通过 PID 文件停止主进程 if [ -d $PID_DIR ]; then for pid_file in $PID_DIR/*.pid; do if [ -f $pid_file ]; then PID$(cat $pid_file) if kill -0 $PID 2/dev/null; then log_info 停止主进程 PID: $PID # 先发 SIGTERM 让进程自己清理 kill -TERM $PID 2/dev/null || kill -9 $PID 2/dev/null else log_warn 进程 $PID 已不存在 fi rm -f $pid_file fi done fi # 2. 等待主进程退出 sleep 2 # 3. 清理所有 vLLM 相关进程关键 log_info 清理所有 vLLM 相关进程... # vLLM Worker 进程最常见残留 local worker_count$(ps aux | grep -c VLLM::Worker 2/dev/null || echo 0) if [ $worker_count -gt 0 ]; then pkill -9 -f VLLM::Worker 2/dev/null log_info ✅ 已杀死 Worker 进程 || true fi # EngineCore 进程 pkill -9 -f EngineCore 2/dev/null log_info ✅ 已杀死 EngineCore 进程 || true # multiprocessing resource_tracker pkill -9 -f resource_tracker 2/dev/null log_info ✅ 已杀死 resource_tracker || true # vLLM 主进程二次清理 pkill -9 -f vllm serve 2/dev/null log_info ✅ 已杀死 vLLM 主进程 || true # 其他 vLLM Python 进程 pkill -9 -f vllm_env.*vllm 2/dev/null log_info ✅ 已杀死其他 vLLM Python 进程 || true # 4. 等待进程退出 sleep 2 # 5. 检查残留 local remaining$(ps aux | grep -E vllm|VLLM::Worker|EngineCore|resource_tracker | grep -v grep | wc -l) if [ $remaining -eq 0 ]; then log_info ✅ 所有进程已清理干净 else log_warn ⚠️ 还有 $remaining 个残留进程: ps aux | grep -E vllm|VLLM::Worker|EngineCore|resource_tracker | grep -v grep fi log_info 所有实例已停止。 } # 强制停止模式 force_stop() { log_warn 执行强制停止... # 杀死所有相关进程 pkill -9 -f vllm serve 2/dev/null || true pkill -9 -f VLLM::Worker 2/dev/null || true pkill -9 -f EngineCore 2/dev/null || true pkill -9 -f resource_tracker 2/dev/null || true pkill -9 -f vllm_env.*vllm 2/dev/null || true rm -rf $PID_DIR 2/dev/null || true sleep 2 log_info ✅ 强制停止完成 # 检查残留 local remaining$(ps aux | grep -E vllm|VLLM::Worker|EngineCore | grep -v grep | wc -l) if [ $remaining -eq 0 ]; then log_info ✅ 所有进程已清理干净 else log_warn ⚠️ 还有 $remaining 个残留进程: ps aux | grep -E vllm|VLLM::Worker|EngineCore | grep -v grep fi } # 主逻辑 case $1 in -f|--force) force_stop ;; *) stop_instances ;; esac

相关新闻

2026/8/26 18:35:39

Linux 性能排查实战

在日常运维中,"机器很卡"是最常见也最模糊的问题描述。卡顿可能来自 CPU、内存、磁盘 IO、网络中的任何一个环节,也可能是特定场景下的局部问题。本文从系统整体卡顿、打字延迟、内存泄漏三个层面,给出一套可执行的排查方法论。 目…

2026/8/26 18:35:39

Codex auth.json 是什么:位置、风险与安全排错

引言:被误解的 auth.json 在 OpenAI Codex 的日常使用中,auth.json 文件常常被开发者从网上搜索、复制粘贴,当作一个普通的“配置文件模板”来使用。这是一个极其危险且普遍存在的误解。本文将深入解析 auth.json 的本质、正确的管理方式以及…

2026/8/26 18:35:39

嵌入式串口调试神器 JCom 详解|自定义协议组包+实时曲线解析

1. 前言 在嵌入式、单片机日常开发中,串口调试是最基础也是最高频的操作。 目前开发者常用的 SSCOM、串口调试助手等工具,仅支持基础的 HEX/ASCII 收发、定时发送功能。 一旦遇到自定义二进制协议、自动CRC校验、传感器ADC数据可视化、丢包检测等场景&am…

2026/8/26 19:35:47

#CSP202503C. 模板展开

模板展开 - 题目详情 - 曙梦 OJ 题目一共就三种操作 操作一是直接赋值 这个很好理解 操作二是间接赋值 此时相当于保存了一个字符串拼接公式 里面的字符串可能会随着后续赋值而改变 操作三是输出长度 这题根据子任务 很容易拿到40%的分数 若想将分数拿满,就需…

2026/8/26 19:35:47

基于SpringBoot个性化课程推荐系统设计和实现(源码+LW+调试文档)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/26 19:35:47

台球桌从树上掉下来砸死人的概率分析

一、引言 1.1 研究背景与问题提出 在日常生活中,我们很少会将台球桌与树木联系在一起——前者是室内运动器材,后者是户外自然元素。然而,正是这种看似荒诞的假设情境,为我们提供了一个绝佳的风险分析案例。这种分析并非无聊的思维…

2026/8/26 19:35:47

AI 时代营销正在变天,很多企业还在沿用搜索时代的旧思路

当大模型深度渗透商业决策,不少企业的获客逻辑却还停留在网页搜索时代。竞价广告、信息流投放、传统 SEO,这些过去十几年行之有效的营销手段,正在面临一个客观现实:用户获取信息的入口已经发生迁移。现在大量 B 端采购、产品选型、…

2026/8/26 19:30:47

Codex调试记录怎么看,codex-devtools上手实测

用 Codex 做开发,最让开发者心里没底的不是代码写不出来,而是不知道它到底怎么写出来的。你丢过去一句需求,它返回一段实现,中间经历了什么、读了哪些文件、调了哪些工具、为什么上下文突然飙高,全是黑箱。Codex-DevTo…

2026/8/26 9:13:28

[光学原理与应用-521]:对光的错误理解与纠偏

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

2026/8/25 11:48:27

SIP通话转接原理与REFER方法实战解析

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

2026/8/25 16:56:43

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

2026/8/26 0:04:32

Python random 模块常用函数详解:从入门到实战

目录 1. 引言2. 准备工作3. 基础随机函数4. 序列相关函数5. 随机种子与复现6. 实战案例7. 注意事项8. 常见问题与排查9. 总结 1. 引言 摘要: 本文系统介绍 Python 标准库 random 模块中最常用的随机数生成函数。内容涵盖基础随机函数(random()、unifor…

2026/8/26 1:19:35

JSON总结

JSON概念 JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,主要用于跟服务器进行交换数据。它基于ECMAScript的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C、C、C#、Java、JavaScr…

2026/8/26 1:19:35

保存连接sse 是什么原理,为什么不会一直请求

“保持连接”用的是 SSE(Server-Sent Events),本质是一个没有马上结束的 HTTP 请求。 过程是: 拷贝机发送一次请求: GET /api/code-sync/events服务器返回: Content-Type: text/event-stream但不关闭响应&…

2026/8/26 19:34:06

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/26 19:17:08

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/26 19:34:05

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…