File size: 2,280 Bytes
e85df1f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | //! 跑一下:查询本机 GPU 状态 + 演示热驻留。
//!
//! ```bash
//! cargo run --example gpu_status
//! ```
//!
//! 需要本机有 Ollama 在跑(`ollama serve`)。
use perch_gpu::status::{query_status, DEFAULT_OLLAMA_BASE_URL};
use perch_gpu::warmup::warmup_model;
#[tokio::main]
async fn main() {
println!("🔍 查询本机 GPU 状态({DEFAULT_OLLAMA_BASE_URL})…\n");
match query_status(None).await {
Ok(st) => {
if st.models.is_empty() {
println!(" (当前没有加载任何模型——闲置后 Ollama 卸载了)");
println!("\n💡 热驻留可以解决:预热一次 + keep_alive 保活");
} else {
for m in &st.models {
let gb = |n: u64| n as f64 / 1024.0 / 1024.0 / 1024.0;
println!(
" 📦 {}\n GPU 驻留: {}%({:.2}GB / {:.2}GB)",
m.name,
m.gpu_residency_percent,
gb(m.gpu_memory_bytes),
gb(m.model_bytes)
);
if let Some(ctx) = m.context_length {
println!(" 上下文: {ctx}");
}
if let Some(exp) = &m.expires_at {
println!(" 过期: {exp}");
}
println!();
}
println!("✅ GPU 加速正在生效(Ollama 已自动选择 Metal/CUDA 后端)");
}
}
Err(e) => {
println!(" ✗ 查询失败: {e}");
println!("\n 检查 Ollama 是否在跑:curl {DEFAULT_OLLAMA_BASE_URL}/api/ps");
return;
}
}
// 演示:预热第一个模型(如果有的话)
if let Ok(st) = query_status(None).await {
if let Some(first) = st.models.first() {
println!("\n🔥 预热 {}(keep_alive 30m)…", first.name);
match warmup_model(&first.name, "30m", None).await {
Ok(()) => println!(" ✅ 已保活 30 分钟——下次请求首 token 只要 0.04~0.18s"),
Err(e) => println!(" ✗ 预热失败: {e}"),
}
}
}
}
|