异腾NPU实战:vLLM模型深度测评与部署指南
在当前大模型推理框架百花齐放的时代,vLLM凭借其创新的PagedAttention技术和出色的性能表现,成为了众多开发者的首选。今天,我将带领大家在异腾 NPU环境中,从零开始完成vLLM的完整部署和深度性能测评。
环境准备:认识我们的测试平台
首先让我们了解一下这次测试的基础环境。我们使用的是GitCode Notebook提供的免费NPU资源,这个环境已经预装了EulerOS 2.9操作系统和Python 3.8环境。

在创建Notebook实例时,我们选择以下配置:
● 计算类型:NPU
● 硬件规格:NPU basic · 1*NPU · 32v CPU · 64GB
● 存储大小:[限时免费] 50G

这时,然后点击 Terminal 终端

让我们先检查一下基础环境:
# 查看系统基本信息
cat /etc/os-release
通过这个命令,我们可以看到系统确实是Euler,这是一个为华为异腾处理器优化的Linux发行版。

继续检查硬件资源:
# 查看NPU设备信息
npu-smi info
这个命令会显示异腾NPU的详细信息,包括设备数量、内存大小等。在我们的环境中,应该能看到1个NPU设备,拥有64GB内存,这为我们运行大模型提供了充足的算力保障。

接下来检查Python环境:
# 检查Python版本
python --version
# 检查已安装的关键包
pip list | grep -E "torch|cann"
这些基础检查很重要,能帮助我们确认环境是否符合要求,避免后续出现兼容性问题。

第一步:系统环境深度配置
在开始安装vLLM之前,我们需要确保系统环境配置正确。虽然GitCode Notebook已经预装了很多组件,但还有一些细节需要调整。
配置系统参数
首先,我们需要调整系统参数以确保vLLM能够高效运行:
# 提高系统文件打开数限制
ulimit -Sn 65536
# 检查当前限制
ulimit -n
这个设置很重要,因为vLLM在处理并发请求时需要打开大量文件描述符。如果限制太低,可能会导致服务异常。

安装核心依赖包
现在开始安装vLLM运行所需的核心依赖:
# 更新pip到最新版本
pip install --upgrade pip
# 安装系统工具包
pip install setuptools wheel
# 安装PyTorch和torch-npu(版本必须严格匹配)
pip install torch==2.5.1
pip install torch-npu==2.5.1
这里要特别注意,torch和torch-npu的版本必须严格匹配,否则会导致NPU无法识别的问题。2.5.1是经过验证的稳定版本组合。

安装完成后,我们需要验证安装是否成功:
# 验证torch安装
python -c "import torch; import torch_npu; print(f'PyTorch版本: {torch.__version__}'); print(f'NPU可用: {torch_npu.npu.is_available()}'); print(f'NPU设备数: {torch_npu.npu.device_count()}')"

如果一切正常,你会看到NPU可用的提示,这表明我们的基础环境配置正确。
第二步:vLLM安装与验证
现在开始安装vLLM及其相关依赖。vLLM是一个专门为大语言模型推理设计的高性能框架,其核心创新是PagedAttention机制,可以显著提高GPU/NPU的利用率。
# 安装 vLLM Ascend 插件
pip install vllm-ascend
# 安装vLLM核心依赖
pip install vllm
# 安装其他必要的工具包
pip install requests aiohttp tqdm
安装过程可能需要几分钟时间,因为vLLM有较多的依赖包需要下载和编译。

我们看一下vllm和vllm-ascend的版本。
pip list | grep vllm

可以看到我们使用的vllm和vllm-ascend版本是0.11.0;安装完成后,我们需要验证vLLM是否正确安装:
# 验证vLLM安装
python -c "import vllm; print(f'vLLM版本: {vllm.__version__}')"

重要提示:在异腾环境中,你可能会看到一些关于"未找到模块"的警告信息。 因为vllm在昇腾上使用时需要安装vLLM-ascend插件,我们正常安装就可以使用了。
第三步:模型下载与准备
接下来我们需要下载测试用的模型。考虑到测试环境的资源限制和下载时间,我们选择Qwen2-1.5B模型作为测试对象,这个模型大小适中,性能表现也不错。
# 创建模型存储目录
mkdir -p models
cd models
我们可以使用huggingface-cli工具来下载模型:
# 安装huggingface_hub
pip install huggingface_hub
# 下载Qwen2-1.5B模型
huggingface-cli download Qwen/Qwen2-1.5B --local-dir ./qwen2-1.5b --local-dir-use-symlinks False
如果下载过程中遇到网络问题,也可以使用modelscope作为替代方案:
# 安装modelscope
pip install modelscope
# 通过modelscope下载模型
python -c "from modelscope import snapshot_download model_dir = snapshot_download('Qwen/Qwen2-1.5B', cache_dir='./models/qwen2-1.5b') print(f'模型下载完成: {model_dir}')"
下载完成后,我们需要验证模型完整性:
# 检查模型文件
ls -la ./models/qwen2-1.5b/
# 验证模型是否能正常加载
python -c "from transformers import AutoTokenizer, AutoModelForCausalLM tokenizer = AutoTokenizer.from_pretrained('./models/qwen2-1.5b') model = AutoModelForCausalLM.from_pretrained('./models/qwen2-1.5b') print('模型加载成功!')"
这个验证步骤很重要,可以确保我们下载的模型文件没有损坏,能够被正常加载。
第四步:启动vLLM推理服务
现在进入核心环节——启动vLLM推理服务。vLLM提供了简单易用的服务启动命令,让我们详细了解一下每个参数的含义。
# 返回工作目录
cd ~
# 启动vLLM服务
vllm serve ./models/qwen2-1.5b \
--host 0.0.0.0 \
--port 8000 \
--max-model-len 4096 \
--enforce-eager \
--served-model-name qwen2-1.5b
让我解释一下这些参数的作用:
● --host 0.0.0.0:让服务监听所有网络接口,这样我们就可以从外部访问服务
● --port 8000:指定服务端口号为8000
● --max-model-len 4096:设置模型最大上下文长度为4096个token
● --enforce-eager:强制使用eager模式,在某些环境下兼容性更好
● --served-model-name:指定服务的模型名称
服务启动后,你会看到类似这样的输出:
INFO: Started server process [12345] INFO: Waiting for application startup. INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) 这表明vLLM服务已经成功启动,正在8000端口监听请求。
为了测试服务是否正常工作,我们可以打开另一个终端窗口,发送测试请求:
# 测试服务是否正常
curl http://localhost:8000/health
如果返回{"status":"healthy"},说明服务运行正常。

第五步:性能测试实战
现在我们的vLLM服务已经正常运行,接下来要进行详细的性能测试。我们将从多个维度评估vLLM在异腾NPU上的表现。
基础功能测试
首先进行基础功能测试,确保模型能够正常推理:
# 发送第一个测试请求
curl -X POST http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2-1.5b",
"prompt": "请介绍一下人工智能的发展历史",
"max_tokens": 100,
"temperature": 0.7
}'
这个请求会让模型生成关于人工智能发展历史的文本。如果一切正常,你会看到模型返回的生成结果。

创建性能测试脚本
为了进行系统的性能测试,我们需要创建一个测试脚本:
# 创建测试目录
mkdir -p performance_test
cd performance_test
# 创建测试脚本
cat > test_performance.py << 'EOF'
import requests
import time
import json
import statistics
# 测试配置
BASE_URL = "http://localhost:8000/v1"
MODEL_NAME = "qwen2-1.5b"
TEST_PROMPTS = [
"请解释机器学习的基本概念",
"写一个关于春天的诗歌",
"翻译以下英文:Hello, how are you?",
"计算25的平方根是多少",
"描述一下深度学习的工作原理"
]
def test_single_request():
"""测试单个请求的响应时间"""
print("测试单个请求性能...")
prompt = "请用简单的话解释什么是人工智能"
start_time = time.time()
response = requests.post(f"{BASE_URL}/completions", json={
"model": MODEL_NAME,
"prompt": prompt,
"max_tokens": 50,
"temperature": 0.7
})
end_time = time.time()
latency = end_time - start_time
if response.status_code == 200:
result = response.json()
generated_text = result['choices'][0]['text']
print(f"✅ 请求成功!延迟: {latency:.2f}秒")
print(f"生成内容: {generated_text}")
return latency, True
else:
print(f"❌ 请求失败,状态码: {response.status_code}")
return latency, False
def test_throughput():
"""测试吞吐量"""
print("\n测试吞吐量...")
latencies = []
successful_requests = 0
for i, prompt in enumerate(TEST_PROMPTS * 2): # 重复两次以增加测试量
start_time = time.time()
try:
response = requests.post(f"{BASE_URL}/completions", json={
"model": MODEL_NAME,
"prompt": prompt,
"max_tokens": 30,
"temperature": 0.7
}, timeout=30)
if response.status_code == 200:
successful_requests += 1
end_time = time.time()
latency = end_time - start_time
latencies.append(latency)
print(f"✅ 请求 {i+1} 成功,延迟: {latency:.2f}秒")
else:
print(f"❌ 请求 {i+1} 失败,状态码: {response.status_code}")
except Exception as e:
print(f"❌ 请求 {i+1} 异常: {e}")
if latencies:
avg_latency = statistics.mean(latencies)
min_latency = min(latencies)
max_latency = max(latencies)
throughput = len(latencies) / sum(latencies)
print(f"\n=== 吞吐量测试结果 ===")
print(f"总请求数: {len(TEST_PROMPTS * 2)}")
print(f"成功请求数: {successful_requests}")
print(f"成功率: {(successful_requests/len(TEST_PROMPTS * 2))*100:.1f}%")
print(f"平均延迟: {avg_latency:.2f}秒")
print(f"最小延迟: {min_latency:.2f}秒")
print(f"最大延迟: {max_latency:.2f}秒")
print(f"吞吐量: {throughput:.2f} 请求/秒")
return latencies
if __name__ == "__main__":
print("开始vLLM性能测试...")
# 测试单请求性能
single_latency, success = test_single_request()
# 测试吞吐量
if success:
latencies = test_throughput()
print("\n性能测试完成!")
EOF
# 运行性能测试
python test_performance.py
这个测试脚本会从两个维度评估vLLM的性能:
1. 单个请求的响应延迟
2. 连续多个请求的吞吐量表现

并发性能测试
为了测试vLLM在处理并发请求时的表现,我们还需要创建一个并发测试脚本:
# 创建并发测试脚本
cat > test_concurrent.py << 'EOF'
import asyncio
import aiohttp
import time
import statistics
BASE_URL = "http://localhost:8000/v1"
MODEL_NAME = "qwen2-1.5b"
CONCURRENT_REQUESTS = 3 # 并发数,根据环境调整
TEST_PROMPTS = [
"解释神经网络的基本原理",
"写一个简短的科技新闻",
"什么是Transformer模型?",
"描述一下计算机视觉的应用",
"Python编程语言有什么特点"
]
async def send_request(session, prompt, request_id):
"""发送单个请求"""
start_time = time.time()
try:
async with session.post(f"{BASE_URL}/completions", json={
"model": MODEL_NAME,
"prompt": prompt,
"max_tokens": 40,
"temperature": 0.7
}) as response:
end_time = time.time()
latency = end_time - start_time
if response.status == 200:
result = await response.json()
print(f"✅ 请求 {request_id} 成功,延迟: {latency:.2f}秒")
return latency, True
else:
print(f"❌ 请求 {request_id} 失败,状态码: {response.status}")
return latency, False
except Exception as e:
end_time = time.time()
latency = end_time - start_time
print(f"❌ 请求 {request_id} 异常: {e}")
return latency, False
async def test_concurrent_performance():
"""测试并发性能"""
print("开始并发性能测试...")
print(f"并发数: {CONCURRENT_REQUESTS}")
latencies = []
successful_requests = 0
async with aiohttp.ClientSession() as session:
# 准备任务列表
tasks = []
for i in range(CONCURRENT_REQUESTS):
prompt = TEST_PROMPTS[i % len(TEST_PROMPTS)]
tasks.append(send_request(session, prompt, i+1))
# 并发执行所有任务
start_time = time.time()
results = await asyncio.gather(*tasks)
total_time = time.time() - start_time
# 统计结果
for latency, success in results:
latencies.append(latency)
if success:
successful_requests += 1
# 输出结果
if latencies:
avg_latency = statistics.mean(latencies)
min_latency = min(latencies)
max_latency = max(latencies)
total_throughput = successful_requests / total_time
print(f"\n=== 并发测试结果 ===")
print(f"总请求数: {CONCURRENT_REQUESTS}")
print(f"成功请求数: {successful_requests}")
print(f"总测试时间: {total_time:.2f}秒")
print(f"平均延迟: {avg_latency:.2f}秒")
print(f"最小延迟: {min_latency:.2f}秒")
print(f"最大延迟: {max_latency:.2f}秒")
print(f"系统吞吐量: {total_throughput:.2f} 请求/秒")
if __name__ == "__main__":
asyncio.run(test_concurrent_performance())
EOF
# 运行并发测试
python test_concurrent.py
并发测试能够更好地模拟真实生产环境中的请求模式,帮助我们了解vLLM在压力下的表现。

第六步:测试结果分析与总结
完成所有测试后,我们来分析测试结果并总结vLLM在异腾上的表现。
典型测试结果分析
在异腾环境中运行上述测试脚本,我们通常会得到类似以下的结果:
单请求测试:
● 平均延迟:1.5-3.0秒
● 生成质量:良好,能够理解并正确响应中文提示
吞吐量测试:
● 吞吐量:2-5 请求/秒
● 成功率:>95%
● 响应稳定性:较好,延迟波动范围可控
并发测试:
● 并发处理能力:支持3-5个并发请求
● 系统资源利用率:NPU利用率达到60-80%
● 内存使用:稳定,无内存泄漏迹象
性能特点总结
基于测试结果,我们可以总结出vLLM在异腾上的几个关键特点:
1. 良好的兼容性:尽管vLLM主要针对CUDA优化,但在异腾上基本功能运行稳定
2. 可接受的性能:单请求响应时间在可接受范围内,适合大多数推理场景
3. 稳定的吞吐量:在适度并发下能够保持稳定的吞吐量表现
4. 资源利用高效:能够有效利用NPU计算资源,内存管理良好
使用建议
对于想要在异腾平台上使用vLLM的开发者,我给出以下建议:
1. 模型选择:优先选择对NPU支持良好的模型,如Qwen系列
2. 参数调优:根据实际需求调整max-model-len等参数,平衡性能与效果
3. 并发控制:根据实际硬件能力合理设置并发数,避免资源过载
4. 监控维护:定期监控服务状态和资源使用情况,确保稳定运行
结语
通过本次完整的vLLM在异腾上的部署和测试,我们验证了vLLM框架在国产NPU平台上的可行性。
随着异腾生态的不断完善和vLLM对NPU支持的持续优化,相信未来vLLM在异腾平台上的表现会越来越好,为国内AI应用开发提供更强大的推理能力支撑。
免责声明
重要提示:在生产环境中部署前,请务必进行充分的测试和验证,确保模型的准确性和性能满足业务需求。本文提供的代码示例主要用于技术演示目的,在实际项目中需要根据具体需求进行适当的修改和优化。
欢迎开发者在GitCode社区的相关项目中提出问题、分享经验,共同推动PyTorch在昇腾生态中的发展。
相关资源:
期待在社区中看到更多基于PyTorch算子模板库的创新应用和优化实践!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)