尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

WSL2 上 libtorch1.10.0-CPU 部署 PyTorch1.12.1 模型:TaoToken 统一 Key 配置与推理验证

WSL2 上 libtorch1.10.0-CPU 部署 PyTorch1.12.1 模型:TaoToken 统一 Key 配置与推理验证 1. WSL2 里跑 libtorch 推理为什么总在第一步卡住如果你在 WSL2 里用 C 加载 PyTorch 模型大概率会遇到这么一串报错undefined reference to torch::jit::load、cannot find -ltorch、或者 CMake 配置阶段直接告诉你TorchConfig.cmake not found。这些问题的根源往往不是代码写错了而是环境路径、ABI 版本、模型导出方式三件事没对齐。这篇要聊的场景很具体在 WSL2 的 Linux 环境里用 libtorch 1.10.0-CPU 去加载一个 PyTorch 1.12.1 训练并导出的模型走完从模型转换、CMake 配置、编译链接到 CPU 推理验证的完整链路。同时把 TaoToken 的统一 Key 和 API 通道接进这套 AI 工具链让模型调试、代码补全、报错排查这些环节能在一个入口里完成。适合谁看已经在 WSL2 里写过 C、手里有.pth模型、想把它变成可执行推理程序的人。libtorch 和 PyTorch 的版本关系这里要强调一下官方建议版本对应但实际项目里经常出现 PyTorch 高版本、libtorch 低版本的情况。我这次就是 PyTorch 1.12.1 导出、libtorch 1.10.0 加载属于「高导低载」能跑通但导出方式必须用torch.jit.trace而不是直接torch.save整个模型对象。下面按步骤拆开讲。2. TaoToken 前置统一 Key 接入 AI 工具链在开始编译之前先把工具链的「入口」理清楚。TaoToken 提供的是一个统一的 API 通道官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 端点是 https://taotoken.net/api 。它的作用是让你用同一个 Key 去调用不同模型省得在多个平台之间来回切换配置。对这篇的场景来说TaoToken 主要用在两个地方一是模型导出阶段如果torch.jit.trace报错可以把报错信息丢给模型对话去分析二是 C 编译阶段CMake 或链接报错时用 Coding Plan 做长上下文排查。你不需要在 WSL2 里装额外的客户端直接用 curl 或 Python 请求就行。先拿 Key。进入控制台创建 API Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 。创建完之后复制那串sk-开头的字符串后面配置里会用到。如果你只是想先验证模型能不能通可以直接用模型对话页面测试地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。配置方式很简单在 WSL2 的 shell 里设一个环境变量export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api如果你习惯用config.toml管理可以建一个~/.taotoken/config.toml[api] base_url https://taotoken.net/api api_key sk-你的key timeout 60 [model] default claude-sonnet这个配置文件的作用是给后续的脚本和工具链一个统一读取入口。比如你写个 Python 脚本去调模型分析 trace 报错直接读这个 toml 就行不用每次硬编码 Key。注意不要把 Key 提交到 git建议加进.gitignore。3. 可复制配置从 .pth 到 .pt 再到可执行文件3.1 模型导出trace 而不是 savePyTorch 1.12.1 训练完的模型如果直接torch.save(model, saved_model.pth)libtorch 1.10.0 是加载不了的因为整个模型对象序列化依赖 Python 类定义。正确做法是用torch.jit.trace导出成 TorchScript。import torch import torch.nn as nn import numpy as np class Net(nn.Module): def __init__(self, n_features): super(Net, self).__init__() self.l1 nn.Linear(n_features, 32) self.l2 nn.ReLU() self.l3 nn.BatchNorm1d(32) self.l4 nn.Linear(32, 64) self.l5 nn.ReLU() self.l6 nn.BatchNorm1d(64) self.l7 nn.Linear(64, 128) self.l8 nn.ReLU() self.l9 nn.BatchNorm1d(128) self.l10 nn.Linear(128, 64) self.l11 nn.ReLU() self.l12 nn.BatchNorm1d(64) self.l13 nn.Linear(64, 32) self.l14 nn.ReLU() self.l15 nn.BatchNorm1d(32) self.l16 nn.Linear(32, 1) def forward(self, inputs): out self.l1(inputs) out self.l2(out) out self.l3(out) out self.l4(out) out self.l5(out) out self.l6(out) out self.l7(out) out self.l8(out) out self.l9(out) out self.l10(out) out self.l11(out) out self.l12(out) out self.l13(out) out self.l14(out) out self.l15(out) out self.l16(out) return out device torch.device(cpu) model Net(n_features24) model.load_state_dict(torch.load(saved_model.pth, map_locationdevice)) model.eval() # 关键trace 时输入 shape 要和推理时一致 example_input torch.randn(1, 24) traced torch.jit.trace(model, example_input) traced.save(model.pt) print(export done)这里有个坑如果forward里有torch.from_numpy这种把 numpy 转 tensor 的操作trace 会失败。导出前把这类代码注释掉输入统一用 tensor。3.2 libtorch 下载与解压libtorch 1.10.0-CPU 的包名是libtorch-cxx11-abi-shared-with-deps-1.10.0cpu.zip。在 WSL2 里建目录解压mkdir -p ~/libtorch cd ~/libtorch unzip libtorch-cxx11-abi-shared-with-deps-1.10.0cpu.zip -d ~/libtorch解压后目录结构是~/libtorch/libtorch/{bin,include,lib,share}。注意share/cmake/Torch这个路径CMake 找的就是它。3.3 main.cpp 推理代码#include torch/script.h #include iostream #include memory #include chrono int main(int argc, const char* argv[]) { if (argc ! 2) { std::cerr usage: main path-to-exported-script-module\n; return -1; } torch::Device device(torch::kCPU); torch::jit::script::Module module torch::jit::load(argv[1]); module.to(device); module.eval(); std::vectortorch::jit::IValue inputs; inputs.push_back(torch::ones({1, 24}).to(device)); auto begin std::chrono::high_resolution_clock::now(); at::Tensor output module.forward(inputs).toTensor(); auto end std::chrono::high_resolution_clock::now(); auto elapsed std::chrono::duration_caststd::chrono::nanoseconds(end - begin); printf(Time measured: %.6f seconds.\n, elapsed.count() * 1e-9); std::cout Output: output.itemfloat() \n; std::cout ok\n; return 0; }3.4 CMakeLists.txt 骨架cmake_minimum_required(VERSION 3.12 FATAL_ERROR) project(main) find_package(Torch REQUIRED) set(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}) add_executable(main main.cpp) target_compile_features(main PUBLIC cxx_range_for) target_link_libraries(main ${TORCH_LIBRARIES}) set_property(TARGET main PROPERTY CXX_STANDARD 14)3.5 编译与运行mkdir -p build cd build cmake -DCMAKE_PREFIX_PATH$HOME/libtorch/libtorch .. make -j4 ./main ../model.pt如果find_package(Torch)报找不到检查CMAKE_PREFIX_PATH是否指向libtorch根目录里面要有share/cmake/Torch/TorchConfig.cmake。4. 验证请求一次可复现的 CPU 推理编译成功后运行./main ../model.pt预期输出类似Time measured: 0.000123 seconds. Output: 0.4523 ok这个Output是模型对全 1 输入的预测值。为了确认结果可复现可以在 Python 侧用同样的输入跑一遍 trace 后的模型import torch ts torch.jit.load(model.pt) out ts(torch.ones(1, 24)) print(out.item())两边数值应该一致浮点误差范围内。如果 C 侧输出和 Python 侧差很多大概率是输入 shape 或 dtype 不一致检查torch::ones({1, 24})是否和 trace 时的torch.randn(1, 24)维度匹配。TaoToken 在这个环节的用法把 C 运行输出和 Python 输出一起贴到模型对话里让它帮你比对数值差异原因。地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite 。如果是链接阶段的报错用 Coding Plan 做长上下文分析更合适入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。5. 本篇常见错排查5.1 undefined reference to torch::jit::load链接阶段报这个通常是target_link_libraries没写对或者TORCH_LIBRARIES为空。检查find_package(Torch REQUIRED)是否成功可以在 CMakeLists 里加一行message(STATUS Torch libs: ${TORCH_LIBRARIES})看输出。5.2 ABI 不匹配导致崩溃libtorch 有cxx11-abi和pre-cxx11-abi两个版本。如果你用 GCC 5 以上编译选cxx11-abi。选错了会在运行时报undefined symbol或直接 segfault。WSL2 默认 GCC 版本一般够用gcc --version确认。5.3 trace 报错Expected a value of type Tensor这是forward里有 numpy 操作导致的。把torch.from_numpy(inputs)这类代码删掉输入直接用 tensor。如果模型必须接受 numpy就在 Python 侧包一层trace 外层 wrapper。5.4 运行时报找不到 libtorch.so编译通过但运行./main时报error while loading shared libraries: libtorch.so。解决方式是设LD_LIBRARY_PATHexport LD_LIBRARY_PATH$HOME/libtorch/libtorch/lib:$LD_LIBRARY_PATH或者把 libtorch 的 lib 路径写进/etc/ld.so.conf.d/再ldconfig。5.5 模型输出 NaNCPU 推理出现 NaN常见原因是 BatchNorm 在 eval 模式下统计量不对。确认导出前调用了model.eval()并且 trace 时模型处于 eval 状态。如果训练时 BatchNorm 的track_running_stats是 False导出后也会有问题。6. 把 Key 和推理链路固定下来整套流程跑通之后建议把几个东西固定成脚本模型导出脚本、CMake 配置命令、运行时的环境变量。TaoToken 的 Key 放在config.toml里统一管理后续不管是排查 trace 报错还是分析链接日志都从同一个入口走。API Keys 管理页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。如果你后续要把这套推理程序接进更大的 C 工程或者用 Claude Code 做自动化构建可以走 Coding Plan 那条线把编译、测试、报错分析串成一个长上下文任务。实测下来把CMAKE_PREFIX_PATH和LD_LIBRARY_PATH写进 shell 的 rc 文件比每次手动 export 省事得多。
返回列表