时隔16年Jeff Barr重返10.23-25 QCon上海站,带你看透AI如何重塑软件开发! 了解详情
写点什么

vLLM 社区原生支持 HAMi,实现推理效率飞跃

  • 2025-09-30
    北京
  • 本文字数:8334 字

    阅读完需:约 27 分钟

大小:321.09K时长:01:49
vLLM 社区原生支持 HAMi,实现推理效率飞跃

在大模型推理进入生产阶段后,如何最大化利用 GPU 资源、实现多模型共存、提高部署灵活性,成为了许多企业与开发者关注的重点。最近,vLLM 社区正式合并了 PR#579,原生支持了 CNCF Sandbox & CNAI Project HAMi。这不仅代表 HAMi 的能力被主流推理框架接纳,更意味着 vLLM 用户可以通过搭配 HAMi,开箱即用地进行 GPU 显存与算力切分部署。


本文将以该 PR 为切入点,结合社区 Issue 和邮件交流记录,从部署到验证,完整还原一条 "HAMi × vLLM" 的落地路径,帮助你在 Kubernetes 中快速实现多模型部署与资源复用。

一、1+1>2:vLLM × HAMi 的结合点


vLLM 是一款开源高性能推理引擎,以 PagedAttention 与连续批处理提升吞吐/并发并兼容 OpenAI 接口;vLLM Production Stack 的定位是把 vLLM 在 Kubernetes 上产品化,补齐弹性伸缩、可观测监控、流量路由/灰度与运维发布,使其可运营、可扩展地落地到生产环境。而 HAMi 提供了 GPU 的精细化切分与调度能力,包括:


  • GPU 算力控制(SM Util)

  • GPU 显存限制(MB / %)

  • 节点/GPU 调度策略(Binpack / Spread)

  • 拓扑感知调度(NUMA / NVLink)


实现生产级的 LLM 推理优化,是一个需要同时解决“计算”与“调度”的系统性工程。vLLM 专注于计算层,通过革新内存管理,将单张 GPU 的吞吐性能推向极致;HAMi 则专注于调度层与虚拟化,为 Kubernetes 带来了 GPU 资源的精细化切分与管理能力。二者结合,完美覆盖了从资源调度到性能优化这两大关键环节。

二、社区驱动的融合:源自真实需求的 PR #579


vLLM 与 HAMi 的这次集成并非项目方“自上而下”的规划,而是一次由真实用户需求驱动、“自下而上”的社区贡献。


这一切都始于 PR #579,社区贡献者 Andrés Doncel 来自西班牙 toB 电商搜索与商品发现平台提供商 Empathy.co。正如该公司在官方博客中所阐述的,其核心技术目标是“弥合生成式 AI 与事实准确性之间的鸿沟”——通过一种先进的 RAG(检索增强生成)框架,确保 AI 的回答有据可查、杜绝“幻觉”。


这种对事实准确性的极致追求,在技术实现上意味着需要将 Embedding(向量召回)、Reranking(模型精排)、事实校验等多个 AI 模型进行高效、低成本的协同部署。正是源于这一真实且迫切的生产需求,Andrés 贡献了 vLLM 对 HAMi 的支持,并被社区认可、合并,为所有 vLLM 用户带来了这套经过生产验证的降本增效方案。


为了探寻这一贡献背后的动机,我们与 Andrés 进行了交流。他提到:


“Our use case is to serve LLM-powered applications while minimizing the dependency from third party providers. We use HAMi and vLLM on top of Kubernetes... using the memory constraints to allow multiple models to reside in the same GPU.”


“我们的使用场景是服务基于大模型的应用,同时尽量减少对第三方提供商的依赖。我们在 Kubernetes 上使用 HAMi 和 vLLM,并通过内存限制允许多个模型共享同一张 GPU。”


这印证了社区用户真实使用 HAMi + vLLM 组合的场景需求。



价值的迅速印证:Issue #649

该 PR 合并后不久,vLLM 社区用户在 Issue #649(https://github.com/vllm-project/production-stack/issues/649)中询问:“是否支持单卡部署多个模型?”



社区用户 @Nimbus318 回复指出:


“Hi, the Production-Stack community recently added native support for HAMi (a CNCF Sandbox project: Project-HAMi/HAMi) GPU slicing parameters, which fits exactly the GPU partitioning scenario you mentioned.

You can already find these parameters in the latest Helm values:

production-stack/helm/values.yaml Lines 41 to 43 in 8367d43

41 # - limitGPUMem: (Optional, string) Requires HAMi. The limit of GPU memory, e.g., 3000. Each unit equals

42 # - limitGPUMemPercentage: (Optional, string) Requires HAMi. The limit of GPU memory of GPU, e.g.,"80"

43 # - limitGPUCores: (Optional, string) Requires HAMi. The limit of GPU cores, e.g., "10". Each unit equals

To use them, you'll first need to install HAMi in your cluster. The setup is simple:

· Stop the default NVIDIA device plugin (for GPU Operator: --set devicePlugin.enabled=false).

· Then follow the HAMi installation guide to deploy it via helm install ...

After that, you can configure GPU slicing directly in your Production-Stack Helm values.”

@Nimbus318 回复指出:


“Production Stack 已原生支持 HAMi 参数,只需安装 HAMi 并配置切分参数即可。”


Issue 发起者 @ExplorerRay 认可并关闭 Issue:“Thanks for your help. I think HAMi fits my needs.”


从一个真实需求的 PR 贡献,到一个社区问题的完美解决,这形成了一个教科书式的开源社区正向循环。

三、完整实战:从安装部署到测试监控

3.1 准备工作:安装 HAMi 并接管 GPU 调度与分配

# 1. 若使用 NVIDIA GPU Operator,通过 Helm 禁用其默认 devicePluginhelm upgrade --install gpu-operator nvidia/gpu-operator \  -n gpu-operator \  --set devicePlugin.enabled=false \  --set dcgmExporter.serviceMonitor.enabled=true \  --version=v25.3.1
# 2. 为需启用 GPU 共享的节点打标签kubectl label nodes <your-gpu-node-name> gpu=on
# 3. 安装 HAMihelm repo add hami-charts https://project-hami.github.io/HAMi/helm install hami hami-charts/hami -n kube-system
复制代码


执行完毕后,HAMi 正式接管集群的 GPU 调度与分配,基础环境准备就绪。

3.2 核心步骤:通过 Production Stack 部署多模型


由于原生支持功能已合并到主干分支但未包含在正式发版中,需从 vLLM Production Stack 的 GitHub 仓库最新 Helm Chart 安装:


  1. 拉取最新源码并创建自定义配置文件

  2. 进入 production-stack 项目的 helm 目录,创建 values-hami-demo.yaml 文件:


git clone https://github.com/vllm-project/production-stack.gitcd production-stack/helmtouch values-hami-demo.yaml
复制代码


将以下内容写入 values-hami-demo.yaml(部署蓝图:单张 L4 卡通过 binpack 策略部署 14GB 显存的 Embedding 模型与 8GB 显存的 Reranker 模型):


servingEngineSpec:  modelSpec:  # BAAI/bge-m3 Embedding Model  - name: "bge-m3-embed"    repository: "vllm/vllm-openai"    tag: "latest"    modelURL: "BAAI/bge-m3"    replicaCount: 1    requestCPU: 2    requestMemory: "6Gi"    requestGPU: 1    limitGPU: 1    requestGPUMem: "14000"    limitGPUMem: "14000"    podAnnotations:      nvidia.com/use-gputype: "L4"      hami.io/gpu-scheduler-policy: "binpack"    pvcStorage: "10Gi"
vllmConfig: dtype: "auto" maxModelLen: 8192 maxNumSeqs: 32 gpuMemoryUtilization: 0.85 extraArgs: ["--task", "embed"]
# BAAI/bge-reranker-v2-m3 Reranker Model - name: "bge-reranker-v2-m3" repository: "vllm/vllm-openai" tag: "latest" modelURL: "BAAI/bge-reranker-v2-m3" replicaCount: 1 requestCPU: 2 requestMemory: "4Gi" requestGPU: 1 limitGPU: 1 requestGPUMem: "8000" limitGPUMem: "8000" podAnnotations: nvidia.com/use-gputype: "L4" hami.io/gpu-scheduler-policy: "binpack" pvcStorage: "5Gi"
vllmConfig: dtype: "auto" maxModelLen: 512 maxNumSeqs: 8 gpuMemoryUtilization: 0.85 extraArgs: ["--task", "score"]
复制代码


  1. 从本地源码执行部署(末尾 . 代表使用当前目录 Chart):


helm upgrade --install vllm -f values-hami-demo.yaml .
复制代码


3.3 资源验证与功能测试

1. 资源分配验证:检查 GPU 共享状态

进入两个模型容器内部,执行 nvidia-sminvidia-smi -L 命令,验证 GPU 共享与显存分配是否符合配置:


  • Embedding 模型容器vllm-bge-m3-embed-deployment-vllm-54fb85bf7c-gwjrn):


root@vllm-bge-m3-embed-vllm-stack:/vllm-workspace# nvidia-smiMon Sep 1 03:40:08 2025+-----------------------------------------------------------------------------+| NVIDIA-SMI 570.148.08   Driver Version: 570.148.08   CUDA Version: 12.8     ||-------------------------------+----------------------+----------------------+| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC || Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. ||                               |                      |               MIG M. ||===============================+======================+======================||   0  NVIDIA L4           On   | 00000000:00:04.0 Off |                    0 || N/A   63C    P0    37W /  72W |   1389MiB / 14000MiB |      0%      Default ||                               |                      |               N/A    |+-------------------------------+----------------------+----------------------+                                                                              +-----------------------------------------------------------------------------+| Processes:                                                                  ||  GPU   GI   CI        PID   Type   Process name                  GPU Memory ||        ID   ID                                                   Usage      ||=============================================================================||    0   N/A  N/A       112      C   vllm::EngineCore                1490MiB |+-----------------------------------------------------------------------------+
root@vllm-bge-m3-embed-vllm-stack:/vllm-workspace# nvidia-smi -LGPU 0: NVIDIA L4 (UUID: GPU-ed8ae6fb-ac66-2346-e6a5-d440223e29a2)
复制代码


  • Reranker 模型容器vllm-bge-reranker-v2-m3-deployment-vllm-7dcb7965d9-xwvr7):


root@vllm-bge-reranker-v2-m3-vllm-stack:/vllm-workspace# nvidia-smiMon Sep 1 03:38:24 2025+-----------------------------------------------------------------------------+| NVIDIA-SMI 570.148.08   Driver Version: 570.148.08   CUDA Version: 12.8     ||-------------------------------+----------------------+----------------------+| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC || Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. ||                               |                      |               MIG M. ||===============================+======================+======================||   0  NVIDIA L4           On   | 00000000:00:04.0 Off |                    0 || N/A   63C    P0    37W /  72W |   1373MiB /  8000MiB |      0%      Default ||                               |                      |               N/A    |+-------------------------------+----------------------+----------------------+                                                                              +-----------------------------------------------------------------------------+| Processes:                                                                  ||  GPU   GI   CI        PID   Type   Process name                  GPU Memory ||        ID   ID                                                   Usage      ||=============================================================================||    0   N/A  N/A       112      C   vllm::EngineCore                1450MiB |+-----------------------------------------------------------------------------+
root@vllm-bge-reranker-v2-m3-vllm-stack:/vllm-workspace# nvidia-smi -LGPU 0: NVIDIA L4 (UUID: GPU-ed8ae6fb-ac66-2346-e6a5-d440223e29a2)
复制代码


2. 协同功能测试:模拟真实 RAG 调用链路


通过 rag_bench.py 脚本模拟 RAG 调用链路,验证多模型并发协同能力:


脚本源码(rag_bench.py)


import os, time, random, asyncio, aiohttpimport numpy as np
BASE_URL = os.getenv("BASE_URL", "http://localhost:30080/v1")EMBED_MODEL = os.getenv("EMBED_MODEL", "BAAI/bge-m3")RERANK_MODEL = os.getenv("RERANK_MODEL", "BAAI/bge-reranker-v2-m3")DOC_MULT = int(os.getenv("DOC_MULT", "600")) # 语料倍数,控制候选集规模Q_CONCURRENCY = int(os.getenv("Q_CONCURRENCY","16"))Q_TOTAL = int(os.getenv("Q_TOTAL","400")) # 总查询数K_RECALL = int(os.getenv("K_RECALL","40"))K_RERANK = int(os.getenv("K_RERANK","8"))
DOCS_SEED = [ "边缘计算是在靠近数据源头侧进行分布式处理的计算范式。", "云计算通过集中式数据中心提供按需算力与存储资源。", "向量检索将文本映射为稠密向量并按相似度召回候选。", "RAG 通过外部检索到的证据提高生成答案的可靠性。", "BM25 是基于倒排索引的稀疏检索算法,适合关键词匹配。"]
def pct(arr, p): return float(np.percentile(arr, p)) if arr else 0.0
async def detect_rerank_path(session): # 优先 /v1/rerank,不行则回退 /v1/score for path in ("/rerank", "/score"): try: payload = {"model": RERANK_MODEL, "query": "ping", "documents": ["a","b"], "top_n": 1} async with session.post(f"{BASE_URL}{path}", json=payload, timeout=5) as r: if r.status == 200: return path except Exception: pass raise RuntimeError("Neither /v1/rerank nor /v1/score is available.")
async def embed_batch(session, texts, batch=64): vecs = [] for i in range(0, len(texts), batch): payload = {"model": EMBED_MODEL, "input": texts[i:i+batch], "encoding_format": "float"} async with session.post(f"{BASE_URL}/embeddings", json=payload, timeout=60) as r: j = await r.json() vecs.extend([d["embedding"] for d in j["data"]]) return np.array(vecs, dtype=np.float32)
async def query_once(session, rerank_path, q, doc_texts, doc_vecs): t0 = time.time() # embed query payload = {"model": EMBED_MODEL, "input": [q], "encoding_format": "float"} async with session.post(f"{BASE_URL}/embeddings", json=payload, timeout=15) as r: ej = await r.json() qv = np.array(ej["data"][0]["embedding"], dtype=np.float32) t1 = time.time() # ANN(内存余弦相似度;生产里换向量库) qn = qv / (np.linalg.norm(qv) + 1e-8) dn = doc_vecs / (np.linalg.norm(doc_vecs, axis=1, keepdims=True) + 1e-8) sims = dn @ qn top_idx = np.argpartition(sims, -K_RECALL)[-K_RECALL:] cand_idx = top_idx[np.argsort(-sims[top_idx])] docs = [doc_texts[i] for i in cand_idx[:K_RECALL]] # rerank payload = {"model": RERANK_MODEL, "query": q, "documents": docs, "top_n": K_RERANK} async with session.post(f"{BASE_URL}{rerank_path}", json=payload, timeout=15) as r: rj = await r.json() t2 = time.time() return (t1 - t0, t2 - t1, t2 - t0), rj.get("results", [])
async def main(): queries = [f"什么是{w}?" for w in ["边缘计算","向量检索","RAG","BM25","混合检索"]] * (Q_TOTAL // 5) random.shuffle(queries) async with aiohttp.ClientSession() as session: # 端点探测 rerank_path = await detect_rerank_path(session) print(f"[info] rerank endpoint = {BASE_URL}{rerank_path}") # 构造“候选库”并嵌入(离线建库) docs = DOCS_SEED * DOC_MULT print(f"[info] building doc embeddings: {len(docs)} docs ...") doc_vecs = await embed_batch(session, docs, batch=64) lat_e, lat_r, lat_t = [], [], [] sem = asyncio.Semaphore(Q_CONCURRENCY) t_start = time.time() async def worker(q): async with sem: (e, r, t), _ = await query_once(session, rerank_path, q, docs, doc_vecs) lat_e.append(e); lat_r.append(r); lat_t.append(t) await asyncio.gather(*[worker(q) for q in queries]) dur = time.time() - t_start n = len(queries) to_ms = lambda x: round(x*1000, 1) print(f"\nRequests={n} Duration={dur:.1f}s QPS={n/dur:.1f}") print(f"Embed p50/p95: {to_ms(pct(lat_e,50))} / {to_ms(pct(lat_e,95))} ms") print(f"Rerank p50/p95: {to_ms(pct(lat_r,50))} / {to_ms(pct(lat_r,95))} ms") print(f"Total p50/p95: {to_ms(pct(lat_t,50))} / {to_ms(pct(lat_t,95))} ms")
if __name__ == "__main__": asyncio.run(main())
复制代码


执行测试步骤


# 将 vLLM 路由服务端口转发到本地kubectl port-forward svc/vllm-router-service 30080:80 &
# 运行功能测试脚本(模拟 2000 次查询)Q_TOTAL=2000 python3 rag_bench.py
复制代码


注:该脚本为功能测试,存在三处与生产环境的简化:

  1. 检索方式非生产级:向量检索在内存中完成,仅为模拟,不代表专用向量数据库性能;

  2. 缺乏容错性:无重试或错误处理逻辑,不具备生产级健壮性;

  3. 只验证通路:仅确认 API 正常返回,不评估结果相关性,非性能基准测试。但脚本无错误运行,可证明共享部署方案功能可用、服务畅通。

3.4 测试结果与监控看板

1. 测试结果输出

> Q_TOTAL=2000 python3 rag_bench.py[info] rerank endpoint = http://localhost:30080/v1/rerank[info] building doc embeddings: 3000 docs ...
Requests=2000 Duration=176.9s QPS=11.3Embed p50/p95: 160.6 / 427.6 msRerank p50/p95: 1225.6 / 1401.4 msTotal p50/p95: 1395.5 / 1647.9 ms
复制代码


2. 监控看板


  • vLLM 服务监控:含 Available vLLM instances、Average Latency、Request latency distribution 等指标(参考链接:https://github.com/vllm-project/production-stack/tree/main/observability)

  • GPU 资源监控:含 GPU 温度(平均 69.3°C)、功耗(平均 38.6W)、显存/算力使用率等(DCGM 监控)

  • HAMi 专属监控:含容器级 GPU 显存/算力分配详情(参考链接:https://github.com/Project-HAMi/HAMi/blob/master/docs/dashboard_cn.md)


总结与展望


这次 PR #579 的合入标志着:HAMi 已成为 vLLM Production Stack 官方集成并认可的 GPU 共享方案。二者的结合,为大模型推理生产环境提供了“计算优化+资源调度”的完整解决方案,帮助企业在有限 GPU 资源下部署更多模型、降低成本。


我们期待未来更多模型推理部署工程化方案能原生对接 HAMi,推动 GPU 资源利用效率进一步提升,让大模型推理在生产环境中更灵活、更高效。



HAMi,全称是 Heterogeneous AI Computing Virtualization Middleware(异构算力虚拟化中间件),是一套为管理 k8s 集群中异构 AI 计算设备设计的“一站式”架构,能提供异构 AI 设备共享能力与任务间资源隔离。HAMi 致力于提升 k8s 集群异构计算设备利用率,为不同类型异构设备提供统一复用接口,当前是 CNCF Sandbox 项目,已被纳入 CNCF CNAI 类别技术全景图。


社区相关链接:


  • 官网:https://project-hami.io

  • Github:https://github.com/Project-HAMi

  • Reddit:https://www.reddit.com/r/HAMi_Community/

2025-09-30 15:5811138
用户头像
李冬梅 加V:busulishang4668

发布了 1185 篇内容, 共 808.1 次阅读, 收获喜欢 1302 次。

关注

评论

发布
暂无评论

工业设计 自控设计经验总结(12)

万里无云万里天

设计师 工业 工厂运维

多模块项目使用ElasticSearch报错

刘大猫

人工智能 云计算 算法 物联网 大模型

动态加速中优化失败路径反馈的方法

天翼云开发者社区

CDN 全站加速

Sight AI 入门:5分钟实现OpenAI兼容的多模型AI调用

SightAI

MaaS 大模型 API 工具 开源‘

怎么避免无意义劳动?奇富科技摈弃分库分表后,代码改造成本节省90%

老纪的技术唠嗑局

数据库 TiDB #OceanBase

企业发展的刚需:零碳园区如何为入园企业创造价值?

西格电力

绿色能源转型 碳中和碳达峰 零碳园区 能源可再生 智能化技术

微擎:让每个创意都能开花的小程序生态引擎

微擎应用市场

云栖实录|MaxCompute全新升级:AI时代的原生数据仓库

阿里云大数据AI技术

阿里云 数据仓库 MaxCompute

火山引擎Data Agent再拓新场景,重磅推出用户研究Agent

字节跳动数据平台

斩获双项第一,天翼云问鼎中国医学影像云解决方案市场!

天翼云开发者社区

云服务 医疗云

StarRocks 数据分析加速:ETL 如何实现实时同步与高效查询

谷云科技RestCloud

数据处理 数据同步 ETL 数据集成 StarRocks

Nginx的ngx_thread_pool模块解析:提升性能与可伸缩性

天翼云开发者社区

nginx CDN

智能制造 柔性制造经验总结(5)

万里无云万里天

工业 智能制造 柔性制造

自动化运维新时代:智能调度与监控让集成更简单

谷云科技RestCloud

数据传输 数据同步 ETL 数据监控 数据集成工具

AI不再“卖梦想”,Anthropic教行业用CFO的语言讲价值

Alter

AI

夜莺监控设计思考(二)边缘机房架构思考

巴辉特

Nightingale 监控告警 夜莺监控 开源监控

Sight AI 入门:5分钟实现OpenAI兼容的多模型AI调用

SightAI

MaaS 大模型 API 工具 开源‘

Vercel+Cloudflare搞定出海域名,10分钟完美绑定丨小白AI出海教程

阿星AI工作室

AI 产品经理 Vercel Cloudflare

新手该如何选择AI编程工具?文心快码Comate全方位体验

Comate编码助手

AI编程 文心快码 AI编程助手

🔥 2025 OCP 峰会大爆点抢先看

GPU算力

破壁者万里眼,点亮示波器的东方之眼

脑极体

AI

焱融科技携手哈工大(深圳)共启AI推理存储研究,推进AI基础设施创新

焱融科技

AI推理 焱融存储 KVCache 哈尔滨工业大学(深圳)

云栖实录 | 通义实验室基于MaxCompute进行大模型数据管理及处理

阿里云大数据AI技术

阿里云 数据处理 大模型 MaxCompute 通义实验室

Sight AI 入门:5分钟实现OpenAI兼容的多模型AI调用

SightAI

MaaS 大模型 API 工具 开源‘

你的程序为何卡顿?从LINUX I/O三大模式寻找答案

poemyang

RPC Liunx

低代码新建表单实操:纯表单 / 列表表单配置 + 表名避坑

引迈信息

面向软件厂商的低代码解决方案:如何无需重构现有系统即可满足客户定制化需求?

星云低代码中间件

低代码 数字化 业务系统

复盘:如何用Coze+Kimi,搭建一个能自动分析财报的“金融助理”?

测试人

行业热点丨仿真驱动设计:兼顾性能、可持续性与效益

Altair RapidMiner

汽车 制造业 仿真 CAE hyperworks

医疗公有云市场第一!

天翼云开发者社区

公有云 天翼云

作为测试工程师,我们该如何应用AI?

思码逸研发效能

AI 自动化测试 API测试 AI编程 思码逸

vLLM 社区原生支持 HAMi,实现推理效率飞跃_生成式 AI_开源项目HAMi Project_InfoQ精选文章