news 2026/9/4 16:19:54

用32块矿卡堆出2TB显存,DIY超级计算机跑vLLM推理

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用32块矿卡堆出2TB显存,DIY超级计算机跑vLLM推理

这次我们来看一个相当硬核的 DIY 项目:用 32 块 Nvidia CMP170HX 矿卡拼出一台“家用超级计算机”,目标是把显存堆到 2TB 级别,然后用来跑 vLLM 推理服务。这个思路的本质很简单,就是把原本面向专用计算市场的矿卡,改造成一张张纯计算卡,通过多卡并行凑出超大显存,用低成本覆盖大模型推理和高并发场景。

这项目最值得关注的点有三个。第一是显存规模,2TB 显存在常规单机方案里几乎不可能做到,单张 80GB 的 H100 要 25 张才能持平;第二是成本,CMP170HX 在二手市场的价格和同显存专业卡完全不在一个量级;第三是 vLLM 能否在这种“杂牌多卡”上稳定工作,这才是整个方案能不能落地的关键。下面我会按“硬件选型 -> 驱动/环境 -> 部署 vLLM -> 功能测试 -> API 调用 -> 性能观察 -> 排错”的顺序,把这套方案拆开讲清楚。

1. 核心能力速览

能力项说明
项目类型DIY 多卡推理服务器,面向 vLLM 大模型部署
核心硬件32 × Nvidia CMP170HX(矿卡/计算卡改造)
总显存目标2TB(以 32 卡方案计,实际单卡容量需按购买版本确认)
主要用途本地大模型推理、长文本生成、高并发 API 服务、批量任务
启动方式Ubuntu + Python 虚拟环境 + vllm serve 命令行启动
是否支持 API支持,vLLM 默认提供 OpenAI 兼容接口
是否支持批量任务支持,可通过并发请求或批处理脚本实现
推荐系统Ubuntu 22.04/24.04,不建议 Windows 直接跑 vLLM
主要限制矿卡无视频输出、需要机架/转接/电源改造、散热考验大
适合读者有一定硬件改造经验、想低成本堆大显存、熟悉命令行部署的开发者

从这张表能看出,这不是开箱即用的一键包项目,而是硬件与软件都要打磨的长期方案。如果你的目标是“买回来就能跑”,那直接考虑 4090 或者租云 GPU 更合适;如果你追求的是“极限单位显存成本”,那这套方案值得认真研究。

2. 适用场景与使用边界

2.1 适合做什么

这套 2TB 显存多卡方案,最大的优势是“显存容量”。大模型推理中最贵的资源就是 KV Cache,上下文越长、并发数越高,KV Cache 占用越大。2TB 显存可以支撑:

  • 超长上下文测试:比如 128K 甚至更长上下文的开源模型,不需要频繁做量化压缩。
  • 高并发 API 服务:在显存充足的情况下,vLLM 可以同时处理更多请求,吞吐量明显优于 24GB 单卡。
  • 多模型常驻:不用来回切换模型,几个 70B 级别模型可以同时常驻显存。
  • 批量离线推理:对一批文本、代码或文档做批处理,显存够大就不容易 OOM。

2.2 不适合做什么

  • 大模型训练和全参微调:没有 NVLink,PCIe 通信带宽有限,训练效率会很低,微调也容易受跨卡通信瓶颈影响。
  • 图像/视频渲染类任务:CMP170HX 本来就是无视频输出的计算卡,装进机箱也只是纯算力卡,不适合做图形渲染。
  • 需要官方质保和稳定业务支持的生产环境:矿卡来源、改造成本和故障率都需要自己承担。
  • 对功耗和噪音敏感的家庭环境:32 张卡的功耗和散热不是普通电脑桌能承受的。

2.3 使用边界与合规提醒

CMP170HX 属于特殊市场定位的显卡,通常以二手或拆机件流通。DIY 过程需要在合规测试环境中进行,购买硬件前要确认来源、型号、显存容量和接口规格。项目本身只能用于开发测试、开源模型部署和个人学习,不能用于挖矿,也不能用未授权数据或模型提供对外服务。涉及模型部署时,请优先使用具有明确开源许可证的模型;使用自有数据做推理时,要做好隐私保护和访问控制。这篇文章讨论的全部内容,都以合法采购、合法使用和测试环境验证为前提。

3. 环境准备与前置条件

3.1 操作系统

vLLM 对 Linux 的支持最成熟,这套多卡方案建议使用 Ubuntu 22.04 或 Ubuntu 24.04。Windows 下虽然可以通过 WSL 做部分验证,但 32 张卡的驱动、CUDA 和 PCIe 设备识别在 Windows 下会非常折腾,不建议走这条路。

用下面命令确认系统版本:

lsb_release -a uname -m

3.2 GPU 驱动与 CUDA

CMP170HX 虽然来源特殊,但识别方式还是 NVIDIA 驱动那一套。先确认系统能看到多少张卡:

nvidia-smi -L nvidia-smi --query-gpu=index,name,memory.total --format=csv

如果nvidia-smi没有输出,说明驱动没装好,或者卡的 PCIe 供电/转接线有问题。建议按 NVIDIA 官方驱动流程安装,完成后用nvidia-smi检查每一张卡是否被正确识别。

CUDA 版本与 PyTorch、vLLM 的匹配关系需要保持一致。更稳妥的做法是先装好 NVIDIA 驱动,再通过 pip 安装匹配的 PyTorch 和 vLLM。

3.3 Python 与虚拟环境

vLLM 依赖较多,强烈建议用虚拟环境隔离,不要直接装在系统 Python 里。

sudo apt update sudo apt install python3 python3-pip python3-venv -y # 创建虚拟环境 python3 -m venv vllm_env source vllm_env/bin/activate # 可以看到当前 Python 路径已在虚拟环境内 which python

3.4 硬件前置检查

在跑 vLLM 之前,先确认这几点:

  • 主板和 PCIe 通道够不够:32 张卡需要多路 PCIe 转接,通常要用矿机主板或带多条 PCIe x16/x1 插槽的服务器主板。
  • 电源功率是否足够:单张 CMP170HX 的功耗不低,32 张卡的整机功耗会非常大,需要按单卡功耗总和留足余量。
  • 散热风道:矿卡多为被动散热或涡轮散热,装入机箱后要保证风道能覆盖所有卡。
  • 转接线和供电线:PCIe 转接线、电源模组线、机架固定件都要提前准备好。

如果这些前置条件没准备好,后面 vLLM 启动时会出现“识别不到 GPU”“显存不足”“驱动报错”等问题,并且很难判断是软件还是硬件导致的。

4. 部署 vLLM 与启动服务

4.1 安装 vLLM

激活虚拟环境后,直接安装 vLLM。

pip install --upgrade pip pip install vllm

安装完成后,检查版本:

python -c "import vllm; print(vllm.__version__)"

如果安装的是最新版本,它通常会依赖特定版本的 PyTorch 和 CUDA。可以先让 pip 自动解析依赖,遇到版本冲突再单独调整。

4.2 确认多卡可用性

启动 vLLM 前,先用 PyTorch 检查 GPU 是否可以正常访问:

python -c "import torch; print(torch.cuda.device_count()); print(torch.cuda.get_device_name(0))"

如果打印出的设备数和 32 差距很大,说明部分卡没有被正确识别。排查方向一般是 PCIe 转接线是否插稳、供电是否充足、驱动是否识别完整。

4.3 启动 vLLM 推理服务

vLLM 提供vllm serve命令,可以一键启动一个 OpenAI 兼容的推理服务。下面以 Qwen2.5-7B-Instruct 为例启动:

vllm serve Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.9 \ --max-model-len 32768 \ --port 8000 \ --host 0.0.0.0

参数说明:

  • --tensor-parallel-size:指定使用多少张卡并行切分模型。7B 模型其实用不了 32 卡,可以先从 1 卡起步,再逐步扩大到 4、8 卡。
  • --gpu-memory-utilization:每个 GPU 最多使用的显存比例。0.9 表示预留 10% 显存给 CUDA context,避免 OOM。
  • --max-model-len:最大上下文长度。显存越大,这个值可以调得越大,但也要看模型本身支持的窗口长度。
  • --host 0.0.0.0:允许局域网内其他机器访问。如果只想本机测试,可以用127.0.0.1

如果模型文件还没有下载,vLLM 启动时会在~/.cache/huggingface下自动下载模型。下载量可能在十几 GB 到几十 GB 不等,首次启动会比较慢。

国内网络环境下,如果模型下载困难,可以改用 ModelScope 下载模型后,再用本地路径启动:

vllm serve /data/models/Qwen2.5-7B-Instruct \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.9 \ --max-model-len 32768 \ --port 8000

具体路径以你下载到的模型位置为准。

4.4 验证服务是否启动成功

启动日志中如果出现类似下面的信息,说明服务已经就绪:

INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000

这时打开另一个终端,用 curl 访问:

curl http://127.0.0.1:8000/v1/models

如果返回模型列表,说明推理服务已经正常启动,可以进行下一步测试。

5. 功能测试与效果验证

5.1 基础文本生成测试

先用最简单的请求验证模型能不能正常推理。vLLM 支持 OpenAI 兼容的/v1/chat/completions接口:

curl http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [ {"role": "user", "content": "用一句话解释什么是 KV Cache"} ], "max_tokens": 256, "temperature": 0.7 }'

判断标准:

  • 返回 JSON 中有choices[0].message.content
  • 生成内容没有乱码。
  • 没有出现 timeout 或 connection refused。
  • 如果能正常返回,说明模型加载、前向推理、采样流程都跑通了。

5.2 长文本与超长上下文测试

2TB 显存方案的重点之一,就是长上下文。可以用一段较长的输入文本测试模型的上下文处理能力:

curl http://127.0.0.1:8000/v1/chat/completions \ -H "Content-Type: application/json" \ -d '{ "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [ {"role": "user", "content": "请你阅读下面的长文本,然后总结核心观点。"} ], "max_tokens": 1024, "temperature": 0.2 }'

测试时要重点观察两个地方:

  • 服务端是否报context length exceeded错误。如果报错,说明--max-model-len设置得比输入长度小。
  • nvidia-smi里显存占用是否在输入变长后明显上升。KV Cache 会随输入长度增加而增长。

5.3 多并发请求测试

vLLM 的核心优势是 PagedAttention 和 Continuous Batching,并发请求多时吞吐量仍然能保持稳定。可以用一个简单的 Python 脚本做并发测试:

import requests import concurrent.futures import time url = "http://127.0.0.1:8000/v1/chat/completions" payload = { "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [ {"role": "user", "content": "讲一个关于程序员的笑话。"} ], "max_tokens": 128, "temperature": 0.8 } def call_one(i): try: resp = requests.post(url, json=payload, timeout=120) return i, resp.status_code, len(resp.text) except Exception as e: return i, -1, str(e) start = time.time() with concurrent.futures.ThreadPoolExecutor(max_workers=32) as executor: results = list(executor.map(call_one, range(64))) suc = [r for r in results if r[1] == 200] fail = [r for r in results if r[1] != 200] print(f"成功: {len(suc)}, 失败: {len(fail)}") print(f"总耗时: {time.time() - start:.2f}s")

判断标准:

  • 成功数量等于请求总数。
  • 没有超时和连接错误。
  • 总耗时时长在可接受范围内。
  • 如果在高并发下大量请求超时,优先检查--max-model-len是否偏大、显存是否被占满、模型服务日志是否有 OOM 报错。

5.4 批量任务测试

除了并发请求,还可以做离线批量任务。准备好一批输入文件,例如batch_input/目录下放多个.txt文件,然后用脚本逐个读取并调用 vLLM 接口:

import os import glob import requests import json input_dir = "./batch_input" output_dir = "./batch_output" os.makedirs(output_dir, exist_ok=True) url = "http://127.0.0.1:8000/v1/chat/completions" files = glob.glob(os.path.join(input_dir, "*.txt")) for idx, fp in enumerate(files): with open(fp, "r", encoding="utf-8") as f: text = f.read()[:2000] payload = { "model": "Qwen/Qwen2.5-7B-Instruct", "messages": [ {"role": "user", "content": f"请对以下内容做摘要:\n{text}"} ], "max_tokens": 512, "temperature": 0.3 } try: resp = requests.post(url, json=payload, timeout=180) data = resp.json() summary = data["choices"][0]["message"]["content"] out_path = os.path.join(output_dir, f"result_{idx}.json") with open(out_path, "w", encoding="utf-8") as f: json.dump({"input": fp, "output": summary}, f, ensure_ascii=False, indent=2) print(f"[OK] {fp} -> {out_path}") except Exception as e: print(f"[FAIL] {fp}: {e}")

批量任务真正跑起来后,要关注的是任务队列和失败重试机制。生产环境中建议给每个任务编号,记录输入文件、请求时间、返回状态、输出路径,失败后自动重试指定次数。

6. 接口 API 与批量任务设计

6.1 OpenAI 兼容接口说明

vLLM 启动后默认提供以下接口:

  • GET /v1/models:查看当前加载的模型。
  • POST /v1/chat/completions:对话补全接口。
  • POST /v1/completions:文本补全接口。
  • POST /v1/embeddings:部分模型支持 Embedding 接口,具体看模型和 vLLM 版本。

这套接口标准的好处是,原来接 OpenAI SDK 的代码,只需要改一下 base_url 就能切换到本地 vLLM 服务。

6.2 Python 调用示例

from openai import OpenAI client = OpenAI( base_url="http://127.0.0.1:8000/v1", api_key="EMPTY" ) resp = client.chat.completions.create( model="Qwen/Qwen2.5-7B-Instruct", messages=[ {"role": "user", "content": "介绍一下 vLLM 的特点"} ], max_tokens=512, temperature=0.6 ) print(resp.choices[0].message.content)

如果安装过openai库,这个脚本可以直接运行。

6.3 批量任务架构建议

对于批量离线任务,不建议把几万个请求直接循环发送,容易给服务造成压力。更稳妥的方式是:

  1. 把待处理文本拆成若干小任务文件。
  2. 用少量 worker 并发请求 API。
  3. 每个任务记录状态:pendingrunningsuccessfailed
  4. 对失败任务做有限次重试。
  5. 所有输出写入独立目录,避免多线程写同一个文件导致覆盖。
batch_input/ task_001.txt task_002.txt batch_output/ result_001.json result_002.json logs/ task.log

这样即使中途程序崩溃,也可以根据日志和结果目录恢复进度。

7. 资源占用与性能观察方法

7.1 显存占用怎么看

vLLM 启动后,可以持续用nvidia-smi观察每张卡的显存占用:

watch -n 1 nvidia-smi

重点看两个值:

  • Memory-Usage:每张卡已经使用的显存。
  • Volatile GPU-UtilUtilization:GPU 计算核心使用率。

如果多张卡显存分配不均,或者某些卡显存占用明显偏低,需要检查--tensor-parallel-size是否设置正确,以及 PCIe 通信是否成了瓶颈。

7.2 GPU 利用率与卡间通信

vLLM 在做 Tensor Parallel 推理时,每生成一个 token,跨卡通信都会拉高 PCIe 总线占用。CMP170HX 系列没有 NVLink,多卡通信完全通过 PCIe,这也是这套方案的主要性能瓶颈。观察方法:

nvidia-smi dmon -s pucvmet

pcie相关字段可以看 PCIe 读写速率。如果多卡扩展后吞吐量没有线性提升,甚至下降,大概率是卡间通信带宽不够。

7.3 如何降低显存占用

如果显存不足或想塞下更多模型,可以考虑:

  • 降低--gpu-memory-utilization,从 0.9 降到 0.7。
  • 减小--max-model-len,例如从 32768 降到 16384。
  • 使用量化模型,比如 AWQ、GPTQ 量化版模型。
  • 使用--enforce-eager关闭 CUDA Graph,但会降低推理性能,需要根据实际表现取舍。
  • 对超大模型,用小 batch 并发,避免瞬时 KV Cache 暴涨。

7.4 如何避免端口冲突和进程残留

vLLM 默认监听 8000 端口。如果之前启动过服务,再次启动前先确认端口没有被占用:

ss -lntp | grep 8000

如果端口被占用,可以换端口启动:

vllm serve Qwen/Qwen2.5-7B-Instruct --port 8001

已经启动但想要停止的 vLLM 服务,找到 PID 后正常结束:

ps aux | grep vllm kill <PID>

不要频繁用kill -9,可能导致缓存文件和进程残留。

8. 常见问题与排查方法

问题现象可能原因排查方式解决方案
nvidia-smi 看不到部分显卡供电不足、PCIe 转接线松动、驱动未完整加载检查 PCIe 物理连接,查看系统日志重新插拔转接线,检查电源功率和模组线
vLLM 启动报 CUDA out of memory显存被其他进程占用,或模型加载所需显存超过单卡容量nvidia-smi 检查空闲显存关闭其他进程,调整 gpu-memory-utilization,使用量化模型
模型下载速度慢或失败网络问题或模型仓库连接超时检查网络,确认模型名称拼写使用国内模型源下载后改为本地路径启动
请求返回 context length exceeded输入长度超过 max-model-len检查输入文本长度调大 --max-model-len,或截断输入文本
并发请求超时显存不足、模型过大、并发数过高查看服务日志和显存状态降低并发数,减小 max-model-len,增加 batch 调度参数
多卡扩展后性能不升反降卡间通信带宽不足用性能监控查看 PCIe 读写减少 tensor-parallel-size,优先用 4 卡或 8 卡并行
Python 依赖安装冲突vLLM 和 PyTorch 版本不匹配查看 pip 报错信息单独创建虚拟环境,按 vLLM 官方要求安装对应版本
调用 OpenAI SDK 报 404base_url 配置错误检查接口路径确保 base_url 以/v1结尾

这些问题是多卡 vLLM 部署中最常见的几类。遇到问题时,先看日志,再查硬件,不要直接重装系统。

9. 最佳实践与使用建议

9.1 先单卡验证,再逐步扩展

第一次部署不要直接上 32 卡。先用--tensor-parallel-size 1跑通 7B 模型,确认驱动、依赖、接口都没问题后,再逐步扩展到 4 卡、8 卡。这样定位问题会容易很多。

9.2 保留一套最小可运行配置

把验证过的关键命令和配置保存下来,最好是写成脚本。例如:

# start_vllm.sh #!/bin/bash source /opt/vllm_env/bin/activate vllm serve Qwen/Qwen2.5-7B-Instruct \ --tensor-parallel-size 8 \ --gpu-memory-utilization 0.9 \ --max-model-len 32768 \ --port 8000

以后重启服务,直接执行脚本,避免记错参数。

9.3 输入、模型、输出分目录管理

模型文件、输入素材、输出结果不要混在一起。推荐结构:

/home/user/vllm-lab/ models/ inputs/ outputs/ logs/ scripts/

模型文件用models/单独存放,批量任务输入放inputs/,生成结果放outputs/,这样不会边跑边找文件。

9.4 批量任务要加日志和失败重试

批量任务一旦跑起来,大概率会碰到网络抖动、模型超时、显存暂时不足等问题。日志和重试机制不是可选项,而是必选项。每个任务记录状态,失败重试最多 3 次,重试间隔可以指数退避。

9.5 接口服务要限制访问范围

虽然 vLLM 本身没有复杂的鉴权体系,但暴露在局域网或公网时要非常小心。建议:

  • 只在可信内网访问,不要直接绑定0.0.0.0暴露公网。
  • 如果需要对外开放,放在 Nginx 等反向代理后面,并增加访问控制。
  • 不要用默认的api_key=EMPTY对外提供服务。

9.6 合规与授权提醒

涉及模型权重下载、数据集使用、生成内容对外发布时,必须确认:

  • 模型许可证是否允许商用或二次分发。
  • 输入数据是否包含个人隐私或敏感信息。
  • 生成内容是否可能涉及版权、肖像权、名誉权。
  • 如果是二手或来源不明硬件,要确认硬件来源合法。

这套方案从硬件到模型全部在测试环境中验证,不要用于任何违规用途。

10. 总结与下一步

CMP170HX 多卡改造方案的核心价值,是用低成本换大显存,给 vLLM 大模型推理提供了非常广阔的试验场。2TB 显存意味着你可以同时常驻多个大模型,也可以用超大上下文做文档分析和批量推理。这个方向最适合对硬件改造和命令行部署都有经验的开发者。

最开始验证时,建议先跑通 7B 模型单卡,然后扩展到 8 卡测试tensor-parallel-size的效果,最后再上 32 卡满配并观察卡间通信和显存分配,整个过程按“软件先行、硬件扩展”的顺序推进。最容易踩的坑集中在三个地方:供电和转接导致部分卡掉线、PCIe 通信带宽撑不起大规模并行、以及模型下载源不稳定。这三个问题只要在规划阶段提前准备好,后面的部署会顺畅很多。

下一步可以继续折腾的方向包括:测试 AWQ/GPTQ 量化模型在这个显存规模下的并发能力、在同一套机器上部署多个不同尺寸的模型、把批量任务改成完整的任务队列并接入异步处理框架,或者把接口服务接到自己的业务系统里做成一个家庭级 AI 推理网关。这套方案的实验属性很强,但能跑通的东西确实不少,建议收藏备用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 16:19:01

AI创业如何抓住破局点?从YC史上最快独角兽AfterQuery说起

创业圈每隔一段时间就会出现一个让所有人抬头看一眼的名字。这一次&#xff0c;主角是 AfterQuery&#xff1a;一家被传闻以 32 亿美元估值完成新一轮融资的 AI 公司&#xff0c;还背上了一个更醒目的标签——“Y Combinator 史上最快独角兽”。先说结论&#xff1a;这个传闻最…

作者头像 李华
网站建设 2026/9/4 16:18:34

61.吃透 FPGA 高速接口核心!DDR3 协议分析 + RTL 实现 + 上板调试全教程

摘要 本文以FPGA接口设计为主线,从最基础的同步时序模型出发,逐步深入到DDR3 SDRAM控制器接口的完整实现。文章摒弃空洞理论,以一段可直接运行的Verilog代码为核心,详细拆解接口设计的每个环节:时钟域处理、状态机设计、时序约束、读写调度。通过本文,读者将掌握FPGA接口…

作者头像 李华
网站建设 2026/9/4 16:15:13

【单片机课设毕设项目】基于 STM32 或 51 单片机的多参数室内火灾隐患监测装置设计 基于 STM32 或 51 单片机的可参数配置物联网安防监测系统设计(023806)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华
网站建设 2026/9/4 16:10:18

小米网关HAD1.16.2固件:本地自动化与Home Assistant接入实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华