File size: 4,803 Bytes
e85df1f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3b0a4b4
 
 
 
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
---
language:
  - zh
  - en
tags:
  - gpu
  - ollama
  - metal
  - local-inference
  - llm
  - rust
license: mit
pretty_name: perch-gpu — Local GPU Acceleration Toolkit
---

> ⭐ **这是栖木 Perch 的开源组件之一。**
> 核心应用(macOS 本地优先 AI 工作台 · 0.08s 首字)在这里 →
> [**🪵 栖木 Perch**](https://huggingface.co/datasets/hongcoding/perch)

# 🖥️ perch-gpu

### 让本机大模型真的用上 GPU——而且用得对。

> 你装了个 7B 模型,满心期待地点发送。
> 然后**等了 5 秒**才出第一个字。
>
> 你查了半天,以为是模型太大、显卡太弱。
> 其实——**是 Ollama 把它从显存里卸载了**。

**perch-gpu** 是一个 Rust 工具箱,解决本机大模型 GPU 加速的三个坑。

从 [栖木 Perch](https://huggingface.co/datasets/hongcoding/perch) 生产环境提取 · MIT · `cargo test` 全绿

---

## 🕳️ 三个坑(大多数人都踩了)

### 坑 1 · 强行指定 GPU 层数

```json
{ "num_gpu": 40 }   // ❌ 错
```

很多人以为这样能"控制 GPU 加速"。实际后果:
**Ollama 触发 runner 重载 → 反而更慢。**

**正确做法**:让 Ollama 自己按模型结构和显存选择后端与层数。
你只需要**如实报告**它分配了多少——这就是本库的 `status` 模块。

### 坑 2 · 模型被悄悄卸载

Ollama 默认在空闲后释放显存。下次请求**冷加载 3~5 秒**——
比云端还慢,你的"本机秒回"名存实亡。

**正确做法**:预热一次 + `keep_alive` 保活。
本库的 `warmup` 模块,首 token 从 3s 降到 **0.04~0.18s**。

### 坑 3 · 本机并发抢显存

同时跑两个模型?一块 GPU 会互相拖慢,甚至 OOM。

**正确做法**:本机并发压到 1(排队比抢显存快),云端可控并发。
本库的 `scheduler` 模块。

---

## 🚀 快速开始

```toml
[dependencies]
perch-gpu = { git = "https://huggingface.co/hongcoding/perch-gpu" }
```

```rust
use perch_gpu::{status, warmup, scheduler};

// 1) 预热 + 保活 30 分钟(首 token 从 3s 降到 0.08s)
warmup::warmup_model("qwen3-06b:latest", "30m", None).await?;

// 2) 查真实 GPU 驻留(读 Ollama /api/ps,不是猜)
let st = status::query_status(None).await?;
for m in &st.models {
    println!("{} → GPU 驻留 {}%", m.name, m.gpu_residency_percent);
}

// 3) 本机推理排队(并发 1,防止抢显存)
let _permit = scheduler::acquire(false).await?;
// ... 跑推理 ...
```

跑 demo 看效果:

```bash
cargo run --example gpu_status
```

真实输出:

```
🔍 查询本机 GPU 状态(http://127.0.0.1:11434)…

  📦 qwen3-06b:latest
     GPU 驻留: 100%(0.37GB / 0.37GB)
     上下文: 4096
     过期: 2026-11-05T22:30:00+08:00

✅ GPU 加速正在生效(Ollama 已自动选择 Metal/CUDA 后端)
```

---

## 🧩 三个模块

| 模块 | 作用 | 关键点 |
|---|---|---|
| **`status`** | 读 Ollama `/api/ps` 真实 VRAM 分配 | 驻留百分比来自真实字节,不是估算 |
| **`warmup`** | 预热 + `keep_alive` 保活 | **绝不传 `num_gpu`**(会触发重载)|
| **`scheduler`** | 本机/云端资源调度 + 元数据缓存 | 只控并发度,不改语义 |

## 📊 实测效果(栖木 Perch,Apple Silicon + Metal)

| 状态 | 首 token 延迟 |
|---|---|
| 冷加载(模型被卸载) | **3 ~ 5 秒** |
| 热驻留(预热 + 保活) | **0.04 ~ 0.18 秒** |

**快 20~70 倍**,代价只是让 0.6B 模型占着 ~0.4GB 显存。

---

## 🛡️ 设计红线

| 红线 | 原因 |
|---|---|
| **绝不传 `num_gpu`** | 让 Ollama 自己选,强行指定会重载 |
| **诊断不猜** | 驻留百分比 = 真实 `/api/ps` 字节数 |
| **调度不改语义** | 只控并发,不碰模型/prompt/思考档/回复长度 |
| **预热不出本机** | 预热提示只发 loopback,不进对话历史 |

## 🔬 验证

```bash
cargo test   # 7 个单元测试 + 1 个文档测试
```

覆盖:真实驻留计算 / CPU 回退 / 无模型 / 预热体不含 num_gpu / 并发序列化 / 缓存失效。

---

## 🔗 相关项目

| 项目 | 说明 | 链接 |
|---|---|---|
| **栖木 Perch**(应用) | macOS 本地优先 AI 工作台 | https://huggingface.co/datasets/hongcoding/perch |
| **perch-ultrafast**(框架) | 混合流 + Ultrafast 推理框架:首字 1s → 80ms | https://huggingface.co/hongcoding/perch-ultrafast |
| **perch-gpu**(本库) | 本机 GPU 加速工具箱 | https://huggingface.co/hongcoding/perch-gpu |
| **HF Collection** | 全部归在一起 | https://huggingface.co/collections/hongcoding/perch-ai-workbench-and-ultrafast-framework |

## 📜 许可

MIT —— 随便用,注明出处即可。

---

**🖥️ 别让你的 GPU 闲着。也别让 Ollama 偷偷把它卸载。**