C++版vLLM:用C++实现高性能大模型推理引擎的实践指南
C 的 vLLM 听起来像是一个伪命题。vLLM 本身就是 Python 写的底层调用 CUDA为什么要搞一个 C 版本如果你有这个疑问这篇内容值得看完。先说结论C 版本的 vLLM本质上不是把 vLLM 的 Python 代码逐行翻译成 C而是指一条更底层的技术路线——用 C 直接实现大模型推理服务替代 Python 运行时、GIL 锁、以及依赖链路的性能损耗。换句话说我们关心的是能不能用 C 写一个类似 vLLM 的推理引擎能不能保持 PagedAttention、Continuous Batching、量化推理、OpenAI 兼容接口这些核心能力同时把延迟和资源占用压得更低。这个方向最大的价值在于部署形态。Python 版本 vLLM 跑起来需要一整套 Python 环境、torch、tokenizers、若干依赖库而 C 版本理论上可以编译成一个独立的二进制启动速度更快内存占用更小也更适合嵌入到现有的 C 服务中。本文会从核心能力、适用场景、编译部署、功能测试、接口调用、资源占用、排查方法几个维度展开帮你判断这个技术路线值不值得跟进。1. 核心能力速览在深入之前先把 C 版本 vLLM 的能力面拉一个表格。需要说明的是不同开源项目的实现程度差异很大以下参数需要以你实际拉取的仓库和版本为准。能力项说明项目类型大模型推理服务框架C 实现对标 vLLM 的功能集底层语言C17/C20CUDA/C 内核可选集成 cuBLAS、CUTLASS主要功能LLM 推理、连续批处理、PagedAttention、KV Cache 管理、量化推理、OpenAI 兼容 API显存需求取决于模型大小和量化精度需按实际模型测试支持平台Linux 为主Windows 需确认是否支持 CUDA 编译链启动方式命令行启动 HTTP 服务或作为 C 动态库嵌入自有服务支持 API通常提供 OpenAI 风格接口具体路径以项目 README 为准批量任务支持 Continuous Batching可并发处理多路请求适合场景高并发推理服务、边缘部署、C 技术栈集成、低延迟场景这个表格里最值得关注的不是“支持 API”这一行而是“启动方式”和“底层语言”。C 版本的核心优势在于它可以把推理引擎做成库直接 link 进你的 C 服务不用再维护一个 Python 子进程也不用操心 Python 环境冲突。2. 适用场景与使用边界C 版本的 vLLM 并不是用来替代 Python vLLM 的它面向的是另一类需求。2.1 适合谁服务端主语言是 C不想为了接一个大模型推理服务引入 Python 技术栈的团队。对启动速度敏感的在线服务。Python 进程加载 torch 和模型权重需要较长时间C 二进制通常更快。需要把推理引擎嵌入现有 C 应用比如游戏服务端、嵌入式设备、实时音视频服务。对内存占用有要求的场景。去掉 Python 运行时和 torch 封装理论上可以减少冗余内存分配。2.2 能解决什么问题最直接的问题是依赖治理。Python 版 vLLM 的依赖树非常庞大包括 torch、transformers、tokenizers、safetensors、fastapi、uvicorn、pydantic 等版本稍微不对就会出现兼容问题。C 版本可以把这些依赖收敛到编译器层面通过 CMake 管理最终产出一个相对独立的可执行文件或动态库。2.3 不适合什么场景快速原型验证。C 编译时间长迭代速度远不如 Python。需要大量使用 Python 生态模型工具链的场景比如 HuggingFace 生态中的 Peft、TRL。模型结构频繁变化的实验阶段。C 推理引擎通常针对特定模型架构优化换一个模型结构可能需要重新实现算子。Windows 环境支持不完善的阶段。虽然 C 本身跨平台但 CUDA 工具链、算子库在 Windows 上的适配往往滞后。2.4 使用边界与合规提醒涉及大模型推理有几个红线必须强调模型权重来源。确认你使用的模型权重具有合法授权尤其是商用场景。用户输入数据。C 推理服务如果对外提供 API日志中可能包含用户输入文本要注意隐私保护必要时应做脱敏处理。生成内容审核。在线推理服务要对输出内容有过滤机制不能裸奔上线。如果接入语音、图像等多模态能力涉及人脸、声音等生物特征数据必须获得明确授权。3. C 版本 vLLM 的核心架构思路要理解这个项目不能只看表面。C 版本 vLLM 的设计思路是对 vLLM 技术栈做分层拆解然后把 Python 层替换为 C 实现。3.1 推理引擎分层一个大模型推理服务通常分成三层前端 API 层处理 HTTP 请求、鉴权、参数解析。调度层管理请求队列、KV Cache 分配、Continuous Batching 决策。计算层Transformer 算子的前向推理包括 Attention、MLP、LayerNorm、Embedding。Python 版 vLLM 用 FastAPI 做前端用 Python 事件循环做调度用 torch 和自定义 CUDA kernel 做计算。C 版本如果做彻底三层全部用 C 实现前端可以用 CrowCpp、Drogon、cpp-httplib 这类库调度层自己写计算层直接用 CUDA 或调用 cuBLAS、CUTLASS。从热词里可以看到很多人关心sglang和vllm、vllm max-num-seq、vllm --enforce-eager这类问题这些概念在 C 版本中同样存在只是实现位置变了。3.2 PagedAttention 的 C 实现vLLM 最核心的优化是 PagedAttention把 KV Cache 分成固定大小的块按需分配减少显存碎片。C 版本要保留这一能力关键是自己管理显存块// 伪代码示例KV Cache 块管理 class KVCacheManager { public: // 分配一个 block返回 block id int AllocateBlock() { if (free_blocks_.empty()) { // 从显存池中切分新块 void* ptr cudaMalloc(block_size_); // 记录显存占用 } int block_id free_blocks_.back(); free_blocks_.pop_back(); return block_id; } // 释放 block放回空闲池 void FreeBlock(int block_id) { free_blocks_.push_back(block_id); } private: std::vectorint free_blocks_; size_t block_size_; };这个只是示意。实际实现里还需要管理 block 之间的映射表、前缀共享、swap 到 CPU 内存等逻辑。但核心思想不变显存不再按序列长度预先分配而是按需分配小块。3.3 Continuous Batching 调度Continuous Batching 的核心是每一轮迭代调度器把当前所有请求的 token 拼接成一个 batch 输入到模型然后根据请求的结束状态动态增删请求。C 实现里需要维护一个请求池struct Request { int64_t request_id; std::vectorint input_tokens; std::vectorint output_tokens; int max_tokens; bool is_finished; }; class Scheduler { public: std::vectorRequest running_requests; std::dequeRequest waiting_queue; // 每个 decode 迭代调用一次 void Schedule() { // 把 waiting_queue 中的请求放入 running直到达到显存上限 while (!waiting_queue.empty() CanAllocate()) { running_requests.push_back(waiting_queue.front()); waiting_queue.pop_front(); } // 剔除已完成的请求 running_requests.erase(...); } };这个调度循环Python 版用 asyncio 处理C 版可以用线程池或事件循环。性能差异不大但 C 版少了 GIL 锁的约束多线程并发处理请求时更可控。4. 环境准备与前置条件不管项目实现到哪个阶段环境准备都是第一步。C 版本的依赖和 Python 版完全不同需要按照 C 工程的思路来配置。4.1 操作系统与编译器LinuxUbuntu 20.04/22.04是最稳妥的选择CUDA 工具链支持最好。如果项目支持 Windows需要确认 MSVC 版本和 CUDA 版本的兼容性。编译器建议 GCC 9 以上或 Clang 12 以上C17 标准是底线。4.2 CUDA 与 GPU 环境需要安装 CUDA Toolkit版本通常要求 11.8 或 12.x具体看项目的 CMakeLists 配置。GPU 建议 NVIDIA 显卡显存至少 8GB 起如果要跑 7B 模型并支持长上下文建议 16GB 以上。如果没有 NVIDIA GPU可以看项目是否支持 CPU 推理或 AMD ROCm。确定前先查项目文档不要默认所有能力都可用。4.3 构建工具CMake 3.20 以上。如果需要加载 HuggingFace 格式的模型权重可能需要集成 safetensors 的 C 解析库或者单独写一个权重转换脚本来导出为项目自定义格式。4.4 磁盘空间7B 模型 FP16 权重约 14GB4bit 量化约 4GB。编译产物和依赖库预留 10GB 以上空间。4.5 动态库与运行依赖如果项目用了 cuBLAS、CUTLASS需要确认这些库在系统路径中。运行时要关注 NCCL多卡通信、OpenMPCPU 并行等库是否完整。5. 编译部署与启动C 项目的部署方式不是 pip install而是 cmake make。下面给出一套通用流程实际命令需要按你拉取的项目替换路径。5.1 拉取代码并初始化子模块git clone https://github.com/your-project/cpp-vllm.git cd cpp-vllm git submodule update --init --recursive很多 C 项目会把第三方库作为 git submodule 管理这一步不能省。5.2 CMake 构建mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease \ -DCUDA_TOOLKIT_ROOT_DIR/usr/local/cuda-12.1 \ -DUSE_CUDAON make -j$(nproc)如果不需要 CUDA只想先验证 CPU 推理流程可以关闭cmake .. -DCMAKE_BUILD_TYPERelease -DUSE_CUDAOFFCPU 模式适合功能验证但性能会差很多。5.3 启动 HTTP 推理服务编译完成后通常会生成一个可执行文件名字可能是cpp_vllm_server或者类似名称。启动方式一般是./cpp_vllm_server \ --model /path/to/your/model \ --tokenizer /path/to/tokenizer \ --host 127.0.0.1 \ --port 8000 \ --gpu-memory-utilization 0.9 \ --max-model-len 4096参数说明--model模型权重目录。--tokenizer分词器目录或路径如果权重目录中已包含可以不单独指定。--host和--port服务监听地址默认通常为 8000。--gpu-memory-utilization显存利用率上限0.9 表示最多使用 90% 显存。--max-model-len最大序列长度超过会报错或截断。如果项目支持--enforce-eager之类参数通常是为了禁用 CUDA Graph 优化减少显存占用但降低推理速度。参考热词中使用vllm命令启动服务是--enforce-eager有什么影响在 C 版本中这个参数的效果是类似的关闭图捕获换取更低的显存占用和更快的启动时间。5.4 验证服务是否启动启动后用 curl 检查健康状态curl http://127.0.0.1:8000/health如果返回OK说明服务就绪。如果端口不通先检查进程是否存活ps aux | grep cpp_vllm_server再检查端口监听ss -tlnp | grep 80006. 功能测试与效果验证服务启动只是第一步。重点要验证生成的正确性、并发处理能力、批量任务稳定性。6.1 基础生成测试先测最简单的 Completion 接口确认模型能正常输出。用 curl 发送请求curl http://127.0.0.1:8000/v1/completions \ -H Content-Type: application/json \ -d { model: your-model-name, prompt: 什么是 C 中的智能指针, max_tokens: 128, temperature: 0.7 }预期结果返回一个 JSON包含choices[0].text内容为一段关于智能指针的文本。判断标准返回内容是否通顺。是否包含明显的乱码或重复。响应时间是否在合理范围内。如果返回 4xx 错误优先看请求字段名称是否正确。C 项目的 API 字段可能和 OpenAI 原始规范略有差异需要查看项目的README或api.md。6.2 Chat 对话测试如果项目支持 Chat 接口测试多轮对话curl http://127.0.0.1:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: your-model-name, messages: [ {role: system, content: 你是一个技术助手。}, {role: user, content: 用三句话解释 vLLM 的作用。} ], max_tokens: 256 }这里重点观察两点多轮对话的上下文是否被正确拼接。C 版本如果 tokenizer 集成不完整很容易在拼接历史消息时出现错位。KV Cache 在多轮对话中的释放是否正常。如果连续对话多次后显存持续上涨说明 KV Cache 存在泄漏。6.3 并发请求测试这是 C 版最值得测的部分。用 Python 脚本或ab工具发起并发请求观察服务是否稳定。写一个简单的 Python 并发测试脚本import concurrent.futures import requests url http://127.0.0.1:8000/v1/completions payload { model: your-model-name, prompt: 请写一段关于并发编程的说明。, max_tokens: 64 } def send_request(i): try: resp requests.post(url, jsonpayload, timeout30) return resp.status_code, resp.text[:50] except Exception as e: return 500, str(e) with concurrent.futures.ThreadPoolExecutor(max_workers8) as executor: results list(executor.map(send_request, range(32))) print(results)判断标准32 个并发请求是否全部成功。是否存在请求超时或连接拒绝。返回内容的 token 数量是否一致。如果并发请求时服务崩溃排查方向顺序是显存不足、调度器线程安全问题、KV Cache 分配冲突。C 项目如果并行处理没有做好互斥很容易在并发场景暴露内存错误。6.4 批量任务测试批量任务在 C 版中更多体现在多请求同时进入队列由调度器做 Continuous Batching 合并。可以准备一个包含多个 prompt 的文本文件逐行读取并异步发送请求import json import requests from concurrent.futures import ThreadPoolExecutor url http://127.0.0.1:8000/v1/completions prompts [ 解释一下 RAII。, 什么是 PagedAttention, C 20 有哪些新特性, 如何优化大模型推理速度, 解释 CUDA Graph。, ] def call_api(prompt): payload { model: your-model-name, prompt: prompt, max_tokens: 128 } resp requests.post(url, jsonpayload, timeout60) return resp.json().get(choices, [{}])[0].get(text, ) with ThreadPoolExecutor(max_workers4) as executor: results list(executor.map(call_api, prompts)) for prompt, result in zip(prompts, results): print(fPrompt: {prompt}) print(fOutput: {result[:80]}...) print(---)这个测试主要验证调度器能否把不同长度的请求合并到同一个 batch 中以及长请求和短请求混合时是否互相阻塞。6.5 长文本与长上下文测试给模型输入一段较长的文本测试是否超出max-model-len限制以及输出是否在接近上限时出现退化。先设置一个较长的 prompt比如 3000 token 的技术文档摘要然后请求模型继续生成。观察是否有显存溢出错误。是否在接近上下文上限时输出质量急剧下降。是否出现 token 重复循环。如果长文本请求频繁失败可能需要调低max-model-len或者关闭--enforce-eager观察是否有改善。6.6 量化模型测试如果项目支持 int8 或 int4 量化权重建议单独做一组测试。量化后的模型能显著降低显存占用但可能带来精度损失。测试步骤准备量化后的权重文件。用--quantization int8或项目支持的量化参数启动。用同一份 prompt 对比量化前后输出。记录显存占用差异。注意C 项目对量化格式的支持往往局限在特定模型结构比如 Llama、Qwen 等不是所有模型都支持。测试前先确认项目支持的模型架构列表。7. 接口 API 与批量任务设计C 版本的 API 设计一般会参考 OpenAI 格式方便已有的工具链迁移。但具体实现可能不完整需要先确认支持哪些接口。7.1 接口兼容性常见接口包括GET /health健康检查。POST /v1/completions文本补全。POST /v1/chat/completions对话补全。GET /v1/models列出已加载模型。其中/v1/models接口很有用它可以帮你确认服务端当前加载的模型名称和配置curl http://127.0.0.1:8000/v1/models很多项目不会严格校验model字段的值只要传一个非空字符串即可。但有些项目会校验模型名是否匹配需要注意。7.2 接口响应结构一个典型的 completions 响应结构如下{ id: cmpl-xxx, object: text_completion, created: 1735000000, model: your-model-name, choices: [ { index: 0, text: 生成的文本, finish_reason: stop } ], usage: { prompt_tokens: 12, completion_tokens: 64, total_tokens: 76 } }usage字段用来统计 token 消耗上线计费或配额管控时会用到。7.3 Python 客户端调用C 服务端对客户端语言没有限制。用 Python 请求库可以快速完成功能验证import requests import json url http://127.0.0.1:8000/v1/completions headers {Content-Type: application/json} payload { model: your-model-name, prompt: 用 C 实现一个线程安全的单例类。, max_tokens: 256, temperature: 0.6 } response requests.post(url, headersheaders, jsonpayload, timeout120) if response.status_code 200: data response.json() print(data[choices][0][text]) print(Token usage:, data[usage]) else: print(Error:, response.status_code, response.text)7.4 批量任务队列设计虽然推理引擎本身支持 Continuous Batching但上层业务如果需要批量处理大量文本建议在客户端做一层任务队列。一个简单的批量任务模块import queue import threading import requests import time task_queue queue.Queue() results {} def worker(): while True: task_id, prompt task_queue.get() if task_id is None: break payload { model: your-model-name, prompt: prompt, max_tokens: 128 } try: resp requests.post( http://127.0.0.1:8000/v1/completions, jsonpayload, timeout60 ) results[task_id] resp.json()[choices][0][text] except Exception as e: results[task_id] fERROR: {e} finally: task_queue.task_done() # 启动 4 个消费者线程 threads [] for i in range(4): t threading.Thread(targetworker) t.start() threads.append(t) # 添加任务 for i, prompt in enumerate([任务1, 任务2, 任务3, 任务4]): task_queue.put((i, prompt)) task_queue.join() # 停止消费者 for i in range(4): task_queue.put((None, None)) for t in threads: t.join() print(results)批量任务的关键点失败重试。请求超时或返回 5xx 时要能重新入队。任务日志。记录每个任务的开始时间、耗时、Token 数方便定位瓶颈。并发上限。根据服务端的吞吐能力限制客户端并发数避免打满显存。8. 资源占用与性能观察C 版本的核心卖点之一是更低的资源占用。但不能凭感觉判断要用数据说话。8.1 显存观察方法启动服务后用nvidia-smi观察显存占用watch -n 1 nvidia-smi重点关注进程占用的显存总量。加载模型后、空闲状态下的显存基线。请求进来后KV Cache 动态增长的显存容量。请求结束后显存是否回落到基线。如果持续上涨大概率存在显存泄漏。更细粒度的观察可以采集多轮数据nvidia-smi --query-gpumemory.used,memory.total,utilization.gpu --formatcsv -l 1输出示例实际数值以本机为准memory.used, memory.total, utilization.gpu 8123 MiB, 24576 MiB, 35 %8.2 CPU 推理与 GPU 推理差异如果项目支持 CPU 推理可以用做功能验证但不建议用于生产。CPU 推理的延迟通常比 GPU 高一个数量级以上尤其是 Attention 部分即使有 OpenMP 并行也难以匹配 GPU 的算力。参考热词中vllm可以在windows10中使用吗、qwen3.6 vllm rtx2080ti 部署 ubuntu这类问题实际部署环境往往受限于显卡和驱动的组合。C 版本如果只做 CUDA 实现那么非 NVIDIA 显卡就基本无法使用。8.3--enforce-eager的影响热词中有人问使用vllm命令启动服务是--enforce-eager有什么影响这在 C 版本中同样值得关注。默认情况下vLLM 会使用 CUDA Graph 捕获一组固定 shape 的 kernel 并复用减少 kernel launch 开销。启用--enforce-eager后关闭 CUDA Graph每次推理都直接 launch kernel。影响启动时间变短显存占用降低不需要为 CUDA Graph 预留显存但单 token 生成速度会变慢。如果你的显存紧张可以开--enforce-eager如果追求吞吐保持默认即可。8.4 如何降低显存占用几个常见手段使用量化权重int8/int4。调低--max-model-len减小 KV Cache 上限。调低--gpu-memory-utilization给其他进程留出显存。关闭 CUDA Graph即启用--enforce-eager。需要注意的是这些手段都会以不同程度的性能损失为代价需要在测试环境中做取舍。8.5 端口冲突与进程残留C 服务如果异常退出可能留下僵死进程占用端口。排查命令lsof -i :8000或者fuser -k 8000/tcp生产环境中建议用 systemd 或 Docker 管理服务生命周期。参考热词ubantu docker 部署vllmDocker 部署确实能降低环境迁移成本C 版本也可以做镜像FROM nvidia/cuda:12.1-runtime-ubuntu22.04 COPY ./build/cpp_vllm_server /app/cpp_vllm_server COPY ./models /app/models WORKDIR /app EXPOSE 8000 CMD [./cpp_vllm_server, --model, /app/models, --host, 0.0.0.0, --port, 8000]构建镜像时注意 CUDA 运行时版本要和宿主机驱动兼容。9. 常见问题与排查方法下面把 C 版本最常见的坑整理成表遇到问题按表排查。问题现象可能原因排查方式解决方案CMake 配置失败CUDA 路径未设置或版本不匹配检查cmake ..时输出的错误信息显式指定CUDA_TOOLKIT_ROOT_DIR或安装匹配的 CUDA 版本编译报找不到头文件第三方库未初始化或未编译检查git submodule和依赖目录执行git submodule update --init --recursive启动时提示模型文件不存在权重路径错误或权重格式不支持检查--model路径和文件类型确认项目支持的权重格式必要时转换权重启动后 API 无响应端口被占用或服务崩溃查看启动日志和ss -tlnp更换端口或重启进程显存溢出模型过大或并发过高nvidia-smi观察显存降低--max-model-len、开量化、启用--enforce-eager并发请求时服务崩溃调度器线程安全问题查看 core dump 日志升级到最新版本或减少并发数验证API 返回 400 错误请求字段不匹配对比接口文档调整 JSON 字段名或类型生成内容重复重复采样参数不合理调整 temperature、top_p设置repeat_penalty或提高 temperature长文本输入报错超过max-model-len查看错误日志中的 token 数调大--max-model-len或截断输入多卡运行失败NCCL 或设备拓扑问题检查多卡通信日志确认 CUDA_VISIBLE_DEVICES 设置更新 NCCL9.1 依赖安装失败的通用排查思路C 项目的依赖安装失败先确认三件事编译器和 CMake 版本是否达标。第三方库版本是否和项目要求一致。网络环境是否能访问依赖下载源。不要一上来就改代码。C 编译错误信息通常是准确的把第一条错误信息贴进搜索引擎比盲改 CMakeLists 更有效。9.2 CUDA 无法使用如果启动时提示 CUDA error优先检查nvidia-smi确认驱动是否正常。再检查nvcc --version确认 CUDA Toolkit 版本。驱动和 Toolkit 版本不匹配是最常见的问题。如果nvidia-smi显示正常但nvcc命令不存在说明 Toolkit 没装或者没加入 PATH。9.3 推理速度异常慢影响推理速度的因素按优先级排列是否误用 CPU 推理。是否启用了--enforce-eager。显存是否被打满导致频繁 swap。是否开启了其他高占用进程。模型权重是否为非量化 FP32。其中显存 swap 是最容易被忽略的。如果nvidia-smi显示显存占用接近上限同时 GPU 利用率波动频繁大概率是 KV Cache 在 CPU 和 GPU 之间频繁换入换出。10. 最佳实践与使用建议C 版本的 vLLM 还处于快速演进阶段工程化落地时建议遵循以下原则。第一次启动一定要用小参数。先用最小模型把max-model-len设低一点比如 512验证服务能通再逐步加大。保留一套最小可运行配置。把模型路径、启动参数、端口、CUDA 版本写进一个配置文件避免每次启动都要临时拼参数。项目如果支持 yaml 配置优先使用。目录管理要规范。模型权重、输入素材、输出结果、日志分开目录存放。比如data/ models/ inputs/ outputs/ logs/批量任务必须加日志和重试机制。C 服务端本身可能不提供任务队列能力客户端要做补偿。接口服务要限制访问范围。如果服务部署在公网必须加鉴权。最简单的方式是在网关层做 IP 白名单或 Token 校验不要裸奔。涉及用户数据时要注意合规。如果服务面向真实用户接入前要确认数据加密、日志脱敏、内容审核方案。发布或商用前要做效果复核。C 版本可能在算子精度上和 Python 版有微小差异尤其是低精度量化条件下需要准备一组标准测试用例对比输出质量确认没有明显的精度劣化。不要轻易在生产环境追最新 commit。C 项目构建链长编译失败或运行时崩溃的修复成本更高。每次升级前先在测试环境完整跑一遍功能测试用例。11. 总结与下一步这个方向最值得尝试的点是把大模型推理从 Python 技术栈中解耦出来。如果你的团队有坚实的 C 基础并且对延迟、内存占用、部署形态有硬性要求C 版本的 vLLM 值得投入时间去验证。最先应该验证的功能不是并发而是基础生成的正确性。先跑通一个模型确认输出质量没问题再考虑性能和并发优化。最容易踩的坑集中在编译阶段。CUDA 版本、CMake 版本、第三方库版本任何一个不匹配都可能导致编译失败。作为新手优先选择 Docker 镜像或项目提供的预编译产物能省掉大量踩坑时间。如果项目没有预编译产物再考虑本地编译。后续可以继续扩展的方向很多多卡推理支持、量化算子优化、vLLM 风格的 Prefix Caching、流式输出SSE、多模态模型接入。这些能力和 Python 版 vLLM 对齐后C 版才能真正成为生产可用的替代方案。建议收藏备用等这个方向成熟之后可以直接拿来和 Python 版 vLLM 做一套完整的对比评测。

相关新闻