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}"),
            }
        }
    }
}