bert-base-chinese部署监控方案:Prometheus+Grafana跟踪GPU显存与推理延迟
·
bert-base-chinese部署监控方案:Prometheus+Grafana跟踪GPU显存与推理延迟
1. 监控方案概述
在实际的AI模型部署中,仅仅能够运行模型是远远不够的。我们需要实时了解模型的运行状态,特别是GPU资源使用情况和推理性能指标。本文将介绍如何为bert-base-chinese模型搭建完整的监控系统,让你能够:
- 实时监控GPU显存使用情况
- 跟踪每次推理的延迟时间
- 设置告警阈值,及时发现异常
- 通过可视化仪表盘直观查看各项指标
这个监控方案基于Prometheus和Grafana两大开源工具,无需额外付费,部署简单,效果专业。
2. 环境准备与组件安装
2.1 安装必要的监控组件
首先,我们需要安装几个关键的监控组件:
# 安装Prometheus客户端库
pip install prometheus-client
# 安装GPU监控工具
pip install nvidia-ml-py
# 安装Grafana(可选,也可以使用docker方式)
# 这里我们使用docker-compose方式部署整个监控栈
2.2 创建监控脚本
在bert-base-chinese模型目录下创建监控脚本:
# monitor_metrics.py
import time
import psutil
from prometheus_client import start_http_server, Gauge, Histogram
try:
import pynvml
pynvml.nvmlInit()
HAS_GPU = True
except:
HAS_GPU = False
# 定义监控指标
GPU_MEMORY_USAGE = Gauge('gpu_memory_usage', 'GPU memory usage in MB')
INFERENCE_LATENCY = Histogram('inference_latency', 'Inference latency in seconds')
CPU_USAGE = Gauge('cpu_usage', 'CPU usage percentage')
MEMORY_USAGE = Gauge('memory_usage', 'System memory usage percentage')
def collect_metrics():
"""收集系统指标"""
# CPU使用率
CPU_USAGE.set(psutil.cpu_percent())
# 内存使用率
memory = psutil.virtual_memory()
MEMORY_USAGE.set(memory.percent)
# GPU显存使用(如果有GPU)
if HAS_GPU:
try:
handle = pynvml.nvmlDeviceGetHandleByIndex(0)
info = pynvml.nvmlDeviceGetMemoryInfo(handle)
GPU_MEMORY_USAGE.set(info.used / 1024 / 1024) # 转换为MB
except:
pass
def monitor_inference(func):
"""监控推理延迟的装饰器"""
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
latency = time.time() - start_time
INFERENCE_LATENCY.observe(latency)
return result
return wrapper
if __name__ == '__main__':
# 启动指标服务器(端口8000)
start_http_server(8000)
print("监控指标服务器已启动,访问 http://localhost:8000/metrics")
# 持续收集指标
while True:
collect_metrics()
time.sleep(5)
3. 集成监控到模型推理
3.1 修改原有测试脚本
现在我们需要修改原有的test.py脚本,集成监控功能:
# test_with_monitor.py
from transformers import BertTokenizer, BertForMaskedLM, BertModel
import torch
from monitor_metrics import monitor_inference, collect_metrics
import threading
import time
# 初始化模型和分词器
tokenizer = BertTokenizer.from_pretrained('/root/bert-base-chinese')
model = BertForMaskedLM.from_pretrained('/root/bert-base-chinese')
feature_model = BertModel.from_pretrained('/root/bert-base-chinese')
# 将模型移动到GPU(如果可用)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
feature_model.to(device)
@monitor_inference
def cloze_test(text):
"""完型填空任务"""
inputs = tokenizer(text, return_tensors='pt')
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
outputs = model(**inputs)
return outputs
@monitor_inference
def similarity_test(text1, text2):
"""语义相似度计算"""
# 编码两个句子
inputs1 = tokenizer(text1, return_tensors='pt', padding=True, truncation=True)
inputs2 = tokenizer(text2, return_tensors='pt', padding=True, truncation=True)
inputs1 = {k: v.to(device) for k, v in inputs1.items()}
inputs2 = {k: v.to(device) for k, v in inputs2.items()}
with torch.no_grad():
outputs1 = feature_model(**inputs1)
outputs2 = feature_model(**inputs2)
# 计算余弦相似度
similarity = torch.cosine_similarity(
outputs1.last_hidden_state.mean(dim=1),
outputs2.last_hidden_state.mean(dim=1)
)
return similarity.item()
@monitor_inference
def feature_extraction(text):
"""特征提取"""
inputs = tokenizer(text, return_tensors='pt')
inputs = {k: v.to(device) for k, v in inputs.items()}
with torch.no_grad():
outputs = feature_model(**inputs)
return outputs.last_hidden_state.cpu().numpy()
def run_demo():
"""运行演示任务"""
print("开始运行BERT演示任务...")
# 完型填空示例
print("\n1. 完型填空演示:")
text = "中国的首都是[MASK]京。"
result = cloze_test(text)
print(f"输入: {text}")
# 语义相似度示例
print("\n2. 语义相似度演示:")
similarity = similarity_test("今天天气真好", "今天的天气很不错")
print(f"相似度得分: {similarity:.4f}")
# 特征提取示例
print("\n3. 特征提取演示:")
features = feature_extraction("自然语言处理")
print(f"特征向量形状: {features.shape}")
def metrics_collector():
"""指标收集线程"""
while True:
collect_metrics()
time.sleep(5)
if __name__ == '__main__':
# 启动指标收集线程
metrics_thread = threading.Thread(target=metrics_collector, daemon=True)
metrics_thread.start()
# 运行演示任务
run_demo()
print("\n监控指标已启动,请访问 http://localhost:8000/metrics")
print("按Ctrl+C停止程序")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("程序已停止")
4. 部署Prometheus和Grafana
4.1 使用Docker Compose部署监控栈
创建docker-compose.yml文件:
version: '3'
services:
prometheus:
image: prom/prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/console_templates'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
grafana:
image: grafana/grafana
ports:
- "3000:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
depends_on:
- prometheus
volumes:
prometheus_data:
grafana_data:
4.2 配置Prometheus
创建prometheus.yml配置文件:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'bert-model'
static_configs:
- targets: ['host.docker.internal:8000']
metrics_path: '/metrics'
scrape_interval: 5s
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
5. 配置Grafana监控仪表盘
5.1 创建GPU监控面板
启动所有服务后,访问Grafana(http://localhost:3000),使用admin/admin登录,然后:
- 添加Prometheus数据源(URL: http://prometheus:9090)
- 创建新的仪表盘
- 添加以下监控面板:
GPU显存使用面板:
- Query:
gpu_memory_usage - Visualization: Stat
- Unit: megabytes
推理延迟分布面板:
- Query:
histogram_quantile(0.95, rate(inference_latency_bucket[5m])) - Visualization: Graph
- Unit: seconds
CPU和内存使用面板:
- Queries:
cpu_usage和memory_usage - Visualization: Gauge
5.2 设置告警规则
在Grafana中设置重要的告警规则:
- GPU显存告警:当显存使用超过90%时发送告警
- 推理延迟告警:当95%分位延迟超过1秒时发送告警
- 服务宕机告警:当指标停止上报时发送告警
6. 实际运行与效果验证
6.1 启动监控系统
# 1. 启动监控组件
docker-compose up -d
# 2. 运行带监控的模型脚本
cd /root/bert-base-chinese
python test_with_monitor.py
# 3. 在另一个终端中运行指标收集器
python monitor_metrics.py
6.2 查看监控效果
访问以下地址查看监控效果:
- Grafana仪表盘: http://localhost:3000
- Prometheus界面: http://localhost:9090
- 原始指标: http://localhost:8000/metrics
6.3 压力测试与监控验证
为了验证监控系统的有效性,可以运行压力测试脚本:
# stress_test.py
from test_with_monitor import cloze_test, similarity_test, feature_extraction
import threading
import time
def run_stress_test():
"""运行压力测试"""
test_texts = [
"人工智能是[MASK]来发展的重要方向。",
"机器学习需要大量的[MASK]据。",
"深度学习在图像识别领域取得了重大[MASK]破。"
]
# 模拟并发请求
def worker():
for i in range(20):
for text in test_texts:
cloze_test(text)
similarity_test("测试句子A", "测试句子B")
time.sleep(0.1)
# 启动多个工作线程
threads = []
for i in range(4):
t = threading.Thread(target=worker)
threads.append(t)
t.start()
for t in threads:
t.join()
if __name__ == '__main__':
print("开始压力测试...")
run_stress_test()
print("压力测试完成")
7. 方案总结
通过本文介绍的Prometheus+Grafana监控方案,我们为bert-base-chinese模型搭建了完整的性能监控体系。这个方案具有以下优点:
核心价值:
- 实时监控GPU资源使用,避免显存溢出
- 跟踪推理延迟,及时发现性能瓶颈
- 历史数据记录,便于性能分析和优化
- 灵活的告警机制,及时发现问题
实践建议:
- 在生产环境中,建议将监控数据持久化到外部存储
- 根据实际业务需求调整监控指标和告警阈值
- 定期检查监控系统的运行状态,确保监控不中断
- 结合业务指标(如QPS、错误率等)进行综合监控
扩展可能性:
- 添加业务指标监控(请求量、成功率等)
- 集成日志监控和追踪系统
- 添加自动扩缩容机制基于监控指标
- 建立性能基线和健康检查机制
这个监控方案不仅适用于bert-base-chinese模型,也可以轻松适配其他AI模型的部署监控需求,为你提供全面的模型运行可视化管理能力。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐




所有评论(0)