Metadata-Version: 2.1
Name: gpumem
Version: 0.1.4
Summary: 显存/带宽独立测量小工具：任意 OpenAI 兼容推理服务（vLLM/sglang/...）的显存曲线 + AMD rocprofv3 带宽实测 + 可选 evalscope 压测
Author: gpumonitor
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: requests
Provides-Extra: perf
Requires-Dist: evalscope; extra == "perf"

# gpumem — 显存/带宽测量小工具

开箱即用的 GPU 显存 + 显存带宽测量工具，**框架无关**（vLLM / sglang / 任意 OpenAI 兼容服务）、不依赖 Docker。从 gpumonitor 项目的显存监控 + rocprofv3 带宽分析能力剥离而来，不含插件/门禁/评测等重逻辑。

## 安装（pip wheel，推荐）

拿到 `gpumem-<版本>-py3-none-any.whl` 后，装到**被测推理服务同一环境**（直接复用服务自带的 torch，无需另装）：

```bash
# 服务的 python 环境里（vLLM/sglang 所在 venv/conda）
pip install gpumem-0.1.4-py3-none-any.whl

# 可选：evalscope 并发档压测（--evalscope 时才需要）
pip install "gpumem[perf] @ file:./gpumem-0.1.4-py3-none-any.whl"   # 或 pip install evalscope
```

装完在**任意目录**直接敲 `gpumem`（结果默认落当前目录 `./data/`）。

> **torch 说明**：gpumem 的 wheel 依赖只有 requests；torch 必须匹配机器 CUDA/ROCm 版本，所以不自动安装——装进被测服务同环境即可复用。若在空环境使用，AMD 装 ROCm 版：`pip install torch --index-url https://download.pytorch.org/whl/rocm6.x`（NVIDIA 装默认 CUDA 版）。缺 torch 时 gpumem 会给出同样的指引。

### 重新构建 wheel（维护者）

```bash
python -m pip wheel . -w dist --no-deps     # 产物 dist/gpumem-<版本>-py3-none-any.whl
```

改过 `gpumonitor/` 包内代码（含 BWTOOL.md）必须：同步 `BWTOOL.md` 到 `gpumonitor/`（package-data 从包内取）→ 升 `pyproject.toml` 版本号 → 重构建，避免 wheel 版本漂移。

## 快速开始

```bash
# 方式一（推荐）：一条命令，启动服务 + 全套测量
gpumem --cmd 'python3 -m vllm.entrypoints.openai.api_server \
    --model /path/to/model --served-model-name my-model --port 8000'

gpumem --cmd 'python3 -m sglang.launch_server \
    --model-path /path/to/model --port 8000'

# 方式二：附加到已运行的服务（只测显存，带宽重放不可用）
gpumem --api-url http://127.0.0.1:8000/v1 --no-bandwidth

# 加 evalscope 并发档压测（可选依赖：pip install evalscope；TTFT/TPOT/吞吐分布）
gpumem --cmd '<同上启动命令>' --evalscope
```

> 命令里**显式带 `--port`**。不带时 API 地址按 `http://127.0.0.1:8000/v1` 推导（sglang 默认端口是 30000，务必注意）。

## 它会做什么

1. **启动前就开始采样**全局显存（`used / free / GPU 利用率`，`--interval` 秒一次）——部署阶段（权重加载）的显存增长也能采到
2. 启动服务（经 wrapper，独立进程组，结束自动整组停掉），就绪探活 `/health` → `/v1/models`
3. 自动 `GET /v1/models` 取模型名（也可 `--model` 显式指定）
4. 先发 1 个**不计分 warmup 预热请求**（剔除服务冷启动首请求的一次性开销：量化 kernel autotune / 投机解码 draft 首跑；不进统计，失败仅告警），再发 `--num-requests` 个流式请求（默认 5），记录每请求 Prefill/Decode 时间窗
5. （`--evalscope` 开启时）跑 evalscope perf 并发档压测（默认 parallel 1 8 16 32 64 × number 20 60 80 100 256，请求数 ≥2-3×并发保证波次可信），输出各档 TTFT/TPOT/吞吐结构化表；tokenizer 默认自动从启动命令的 `--model`/`--model-path` 推导（附加模式跑 random 数据集需显式传 `--evalscope-tokenizer-path`）
6. （AMD 且未 `--no-bandwidth`）设置 perf level → 在 rocprofv3 下**重启服务重放同一请求序列**（fast 模式 1 轮；`--amd-bandwidth-full` 校准 3 轮）→ 输出 部署/Prefill/Decode 阶段 DRAM 读/写带宽表
7. 产物落 `data/run_<时间戳>/`：`vram_global_*.csv`（显存曲线）、`phase_windows_main.json`（含 `tasks.evalscope` 压测时间窗）、`evalscope/`（压测日志与结果）、`rocprof_*/`（各重放轮）、`amd_bandwidth_*.csv`、`bw_summary.json`

## 常用参数

| 参数 | 默认 | 说明 |
|---|---|---|
| `--cmd` | - | 服务启动命令（vLLM/sglang/任意命令，引号整体传入） |
| `--api-url` | - | 附加到已运行服务（与 `--cmd` 二选一） |
| `--model` | 自动 | 模型名；不传自动取 `/v1/models` 第一个 |
| `--num-requests` / `--gap-seconds` | 5 / 1.0 | 请求序列（监控跑与带宽重放同序列） |
| `--prompt` / `--max-tokens` / `--temperature` | 见 help | 请求内容 |
| `--evalscope` | 默认关 | evalscope perf 并发档压测（需 `pip install evalscope`） |
| `--evalscope-parallel` / `--evalscope-number` | 1 8 16 32 64 / 20 60 80 100 256 | 并发档 × 各档请求数（一一对应；请求数 ≥2-3×并发，波次太少 steady 会虚高） |
| `--evalscope-tokenizer-path` | 自动 | random 数据集 tokenizer；默认从启动命令 `--model`/`--model-path` 推导，附加模式需显式传 |
| `--evalscope-extra` | 空 | 额外透传给 evalscope perf 的任意参数串 |
| `--no-bandwidth` | 默认开 | 关闭带宽测量（非 AMD / 附加模式自动关） |
| `--amd-bandwidth-full` | - | 校准模式：推算真实平均读尺寸，换模型/量化/卡后跑一次 |
| `--amd-bandwidth-mc-only` | - | 诊断模式：L2 命中率 / MALL 过滤 |
| `--mc-avg-read-bytes` | 128 | fast 模式平均读尺寸（gfx1151 校准值，full 模式重新标定） |
| `--amd-mem-peak-gbps` | 256 | 显存物理峰值（利用率换算基准） |
| `--gpu-id` / `--interval` / `--print-interval` | 0 / 0.5 / 30 | 采样配置 |
| `--startup-timeout` / `--keep-wrapper` | 1200 / 关 | 服务启动控制 |
| `--aggressive-cleanup` | 关 | 退出时杀所有 `/dev/kfd` 持有者（共享机器慎开） |
| `--output-dir` / `--run-name` | `./data` / 时间戳 | 输出目录 |

## 注意事项

- **带宽重放会重启服务 2~4 次**（fast 1 轮 / full 3 轮），不要对生产服务跑；轮与轮之间有显存释放校验门
- **evalscope 是压测**：会打满服务端，显存曲线可按 `phase_windows_main.json` 的 `tasks.evalscope` 时间窗切片；单请求基线（`--num-requests` 序列）在压测之前跑，不受污染
- **RDNA 采 PMC** 需要 `power_dpm_force_performance_level=profile_standard`：裸机 root 自动设置并恢复；容器内需要 `--privileged`（或挂载该 sysfs 文件 / `--pid=host` + CAP_SYS_ADMIN），全部不可用时报告会明确标注数据可能偏低
- **平均读尺寸 = 128 B/请求**是 gfx1151（Strix Halo）+ 2B Q4 的实测校准值；换卡/模型后先用 `--amd-bandwidth-full` 重新标定，再用 fast 日常跑
- **自检行**：fast 表的 "Decode 读 GB/token" 应 ≈ 模型权重体积（如 2B Q4 ≈ 1.8）；偏差大说明校准常量漂移
- NVIDIA GPU：带宽部分自动跳过（rocprofv3 仅 AMD），显存监控正常
- 显存口径为**全局**（`mem_get_info`，跨进程）：used = total − free，包含服务进程的全部占用；进程内 allocator 细分口径本工具不采
