2
DCU技术达人
新人贴
把 Unsloth Studio 带到海光 K100-aiDCU:从 HIP 运行时到训练、Chat、RAG 与工具调用的完整适配
2026-08-13 16:04:44
178
> 本文记录一次真实的单卡海光 K100-aiDCU 部署。目标不是让设备“看起来像 CUDA”,而是把厂商差异压缩在 DTK/HIP 边界内,让上层尽量保持 PyTorch、Transformers、TRL、PEFT、Unsloth、vLLM 和 llama.cpp 的通用技术路线。文中的结果、错误和性能数据均来自 2026 年 8 月 12 日的现场测试。 ## 一、最终得到了什么 这次交付不是一个只能运行厂商示例的容器,而是一套可以日常使用的 Unsloth Studio: * 用本地 Transformers/safetensors 模型进行 BF16 LoRA 或全参数训练; * 从 Studio 的 Train 产品接口提交任务,观察加载、训练、保存和历史记录; * 用训练后的 LoRA checkpoint 直接进入 Preview; * 用 GGUF、safetensors 或 LoRA 进行 Chat; * 支持普通响应、SSE 流式输出、多轮历史、重新生成和会话持久化; * 支持知识库、TXT/PDF/DOCX 附件、词法/向量/混合检索; * 支持 Web Search、Python 和终端工具调用; * 提供 OpenAI 风格 API、API Key 生命周期和模型加载/卸载接口; * 保留 SDPA 稳定回滚镜像,并提供隔离的 FlashAttention 增强镜像。 当前推荐服务位于 `127.0.0.1:18887`,使用 DTK 26.04、PyTorch HIP、厂商匹配的 FlashAttention 和 gfx928/HIP llama.cpp。稳定回滚服务位于 `127.0.0.1:18888`,默认关闭服务端工具并保留 SDPA 路线。两个端口、状态目录和安全策略互相隔离。 这套适配没有刷 VBIOS,没有改 PCI Vendor ID,没有伪造 `torch.version.cuda`,也没有把厂商 demo 当成产品入口。PyTorch HIP 仍然通过 `torch.cuda.\\\*` 兼容语义工作,这是 PyTorch 在 HIP 平台上的标准设计;对外审计字段则明确写作 `rocm`,避免把兼容 API 误解成原生 CUDA。 ## 二、Unsloth Studio 是什么 很多人只把 Unsloth 理解为一个更快、更省显存的微调库。Studio 的边界更大:它把模型发现、数据集处理、训练、导出、推理、Chat、知识库、工具调用、历史记录、监控和权限管理放在一个 Web 产品中。 ### 1\. 训练工作台 Studio 的训练层可以配置 LoRA、全参数微调和继续预训练,管理本地或 Hugging Face 数据集,记录 loss、学习率、梯度范数、checkpoint 和最终产物。训练不在 Web 进程中直接执行,而是通过独立子进程运行,这使模型版本切换、失败隔离和 GPU 回收更容易控制。 本次 K100 部署认证了以下链路: ```text 登录鉴权 -> POST /api/train/start -> 数据集和模型安全预检 -> 单卡 GPU 选择 -> 训练子进程 -> BF16 LoRA step -> adapter/checkpoint/trainer state 保存 -> metrics/history -> checkpoint Preview ``` 它与直接运行一段 `SFTTrainer` 脚本的区别在于:产品层的鉴权、路径约束、任务身份、异步状态、历史数据库和产物发现也被一起验证了。 ### 2\. Chat 与推理 Studio 可以在同一界面管理 Transformers 模型、LoRA adapter 和 GGUF。对于 K100: * safetensors/LoRA 走 PyTorch HIP; * GGUF 走 gfx928 编译的 HIP llama.cpp; * vLLM 作为独立推理 profile 使用 eager 模式; * CUDA-only 或不稳定模型优先使用 PyTorch HIP 的 `torch.cuda` 兼容接口、SDPA fallback,或者禁用有问题的 kernel; * 不把 `flash\\\_attn` 能导入等同于每一种 head dimension 都能运行。 实际测试包括官方 Qwen2.5-0.5B-Instruct GGUF、本地 Qwen3 0.6B 基础权重、训练后的 LoRA,以及本地 Gemma 26B GGUF。 ### 3\. RAG 与附件 Studio 自带知识库、文档解析、分块、向量化、检索和签名预览。此次部署使用体积约 68 MiB、已经缓存的 `sentence-transformers/paraphrase-MiniLM-L3-v2`,通过普通 PyTorch HIP 运行。 认证范围包括: * TXT 上传和异步索引; * PDF、DOCX 文本解析; * lexical、dense、hybrid 三种检索; * 签名原文件预览; * 知识库清理; * Chat 附件控件和 RAG scope。 ### 4\. Search、Code 与 API Studio 可以让模型调用 Web Search、Python 和 terminal。工具能力是安全敏感功能,因此本次配置只在回环地址 `18887` 开启;`18888` 默认关闭。API Key 可创建、调用、撤销,撤销后的 key 返回 401。 小模型的工具规划质量和工具执行环境是两件事。Qwen2.5 0.5B 能完成显式 Python 调用,但可能生成错误的自主搜索参数;Gemma 26B 已完成模型自主生成 Python 和 Web Search 参数的闭环测试。 ## 三、与常见方案相比,优势在哪里 没有一个工具在所有维度都最好。下面的比较重点是产品边界,而不是简单地给竞品排座次。 |方案|强项|与本方案的关系| |-|-|-| |Unsloth Studio|训练效率、LoRA、训练与 Chat/RAG/Preview 一体化|本文的产品主体;优势是从数据到训练产物再到 Chat 的闭环| |LLaMA-Factory|模型/数据集覆盖广、训练配置成熟、中文社区活跃|更偏训练平台;Studio 在训练产物 Preview、Chat、RAG 和工具整合上更完整| |Axolotl|YAML 可复现、适合工程化训练流水线|适合纯训练和集群自动化;Studio 更适合希望通过 UI 完成完整模型生命周期的团队| |Open WebUI|Chat、RAG、用户管理和多后端体验成熟|更偏推理前端;不以本地高效微调和训练产物管理为核心| |vLLM|高吞吐服务和 OpenAI API|是推理引擎而非训练产品;本方案把它作为可替换后端而不是整个产品| |Ollama / LM Studio|本地模型开箱体验好|更适合桌面推理;训练、LoRA 生命周期和服务器级可审计部署不是主要目标| |厂商 demo|最容易证明硬件能跑某个算子或模型|可移植性和可维护性弱;本文只把厂商层保留在 DTK/HIP 与必要二进制边界| 本次部署最重要的竞品优势并不是某一个 microbenchmark,而是以下组合: 1. **训练到推理的连续性。** 同一个产品可以提交训练、查看 metrics、保存 adapter,然后直接 Preview 或放入 Chat。 2. **显存效率与小改动原则。** 保留 Unsloth 的 LoRA 优化,同时没有为 K100 维护一个大规模 fork。 3. **后端可替换。** Transformers、FlashAttention、SDPA、llama.cpp、vLLM 各自有明确边界和回滚路径。 4. **适合非 CUDA 设备。** 上层继续使用 PyTorch HIP 的标准兼容语义,对外监控和历史则诚实报告 ROCm/HIP。 5. **产品功能完整。** Chat、RAG、附件、工具、历史、API、账号安全和浏览器 UI 都经过真实测试,而不仅是一个 notebook 成功运行。 代价也很明确:K100 目前没有可直接信任的通用 bitsandbytes 4/8-bit 路线;某些只提供 CUDA 扩展的模型仍需 fallback;图片、视频和音频功能还需要相应模型资产逐项认证。 ## 四、硬件和软件基线 现场环境如下: |项目|观测值| |-|-| |GPU|单卡 K100\_AI,PCI `1d94:6210`| |ISA|`gfx928:sramecc+:xnack-`,120 CU| |显存|65,520 MiB| |容器系统|Ubuntu 22.04 系列基础环境| |DTK|26.04| |编译器|dcc/clang 17| |HIP runtime|6.3.26045/26093 系列| |PyTorch|2.9.0 DTK vendor build,`USE\\\_ROCM=ON`| |Python|CPython 3.10| |FlashAttention wheel ABI|DTK 26.04 + Torch 2.9 + CPython 3.10 + x86\_64| |GPU 设备节点|`/dev/kfd`、`/dev/mkfd`、`/dev/dri`| |驱动边界|`libamdhip64` 最终解析到 `libgalaxyhip`| 主机上的 DTK 24.04.3 用户态与已加载的内核/驱动代际不匹配,因此主机 `rocminfo` 失败,而 DTK 26.04 容器正常。这也是为什么不能随意换成普通上游 ROCm 镜像:当前驱动需要海光提供的 `libgalaxyhip` 边界。 所以需要讲清楚“通用路线”的含义:上层尽量通用,不等于底层驱动 ABI 可以凭空替换。此次唯一不可消除的厂商依赖是 DTK 26.04 基础环境,以及按该 ABI 构建的 FlashAttention/llama.cpp 二进制。 ## 五、适配过程与核心改动 ### 1\. 先证明 HIP,而不是先编译整个 PyTorch 现场审计依次检查系统、PCI、设备节点、DTK、`hipcc`、`rocminfo`、动态链接库、gfx ISA、显存、温度和功耗。随后运行三个最小测试: * HIP runtime vector add; * hipBLAS 1024×1024 SGEMM; * Python `ctypes` 直接加载 HIP runtime。 结果分别为 0.729 ms、17.393 TFLOP/s 的短时 warm GEMM,以及 runtime/driver/device/VRAM 全部可读取。只有这三层成立后,才继续 PyTorch、Unsloth 和 Studio。 这种顺序能快速区分驱动 ABI、runtime、BLAS、Python 包和上层框架问题。否则一个 `model.generate()` 错误很容易被错误归因于硬件。 ### 2\. PyTorch 从零补丁 configure 开始 重新 clone 干净 PyTorch v2.9.0,首先执行零补丁 configure。遇到的问题不是算子源码,而是 DTK CMake 导出差异: * CMake 3.29 不接受 `hipcc` 作为 `CMAKE\\\_HIP\\\_COMPILER`; * DTK 缺少上游期望的 `hiprtcConfig.cmake`; * PyTorch 查找 `hip::amdhip64`,DTK 导出的是 `hip::galaxyhip`。 最终补丁范围只有一个外部 `Findhiprtc.cmake` 和 CMake 参数,没有修改 PyTorch operator、ATen 或 CUDA 身份逻辑。去掉 `CMAKE\\\_MODULE\\\_PATH` 即可回滚。 ### 3\. 明确禁用不可用的 bitsandbytes 通用 bitsandbytes wheel 先声称找不到 ROCm 6.3,再尝试加载其他版本对象并出现解压错误,却可能让上层误以为量化可用。对此不能只捕获 import error,因为“能 import”和“原生 kernel 可运行”不是一回事。 适配增加了显式环境开关: ```bash UNSLOTH\\\_DISABLE\\\_BITSANDBYTES=1 ``` 它让 Unsloth 不再宣传 4/8-bit 能力,同时保留一个不可调用的类型 stub,满足上游某些无条件类型导入。BF16、FP16、LoRA 和全参数训练不受影响。只有拿到 DTK 26.04 对应的原生 bitsandbytes 并完成算子测试后才应重新开启。 ### 4\. FlashAttention 必须精确匹配 ABI 选用的文件是: ```text flash\\\_attn-2.8.3+das.opt1.dtk2604.torch290-cp310-cp310-manylinux\\\_2\\\_28\\\_x86\\\_64.whl ``` 选择依据逐项对应: * `dtk2604`:DTK 26.04; * `torch290`:PyTorch 2.9; * `cp310`:Python 3.10; * `x86\\\_64`:主机架构。 安装必须使用 `--no-deps`,否则 pip 可能用通用 PyPI torch 替换厂商 PyTorch: ```bash python3 -m pip install --no-deps flash\\\_attn-...whl ``` wheel 的 distribution metadata 是 2.8.3,但内部 `version.py` 报告 2.6.1。我们保留并披露该不一致,没有增加版本伪装。其动态对象链接到 `libgalaxyhip.so.5`,FP16/BF16、causal/non-causal、varlen 和 Qwen GQA forward/backward 均通过。 FlashAttention forward microbenchmark 在 `\\\[2,1024,16,64]` BF16 上约 0.169 ms,SDPA math 为 3.911 ms,约 23.2 倍。但这是固定形状 forward microbenchmark,不应外推为完整训练提速。 ### 5\. RAG 的 sqlite-vec 兼容修复 RAG 安装上游所需依赖后,dense search 返回: ```text A LIMIT or 'k = ?' constraint is required on vec0 knn queries. ``` 独立 sqlite-vec 0.1.9 复现实验证明:带 partition key 时,无论参数化还是字面量 `LIMIT` 都被拒绝,而 `k=?` 可用。最终改动只有一条 SQL: ```python # before WHERE scope=? AND embedding MATCH ? ORDER BY distance LIMIT ? # after WHERE scope=? AND embedding MATCH ? AND k=? ORDER BY distance ``` 没有修改数据库 schema、向量格式或检索算法。修复后 lexical、dense、hybrid 和签名预览均通过。 ### 6\. 训练历史不能把 HIP 写成原生 CUDA PyTorch HIP 内部使用 `DeviceType.CUDA` 和 `torch.cuda` 是正常兼容设计,但 Studio 直接持久化 `get\\\_device().value` 会让训练历史显示 `cuda`。硬件 API 已经有 ROCm-aware label,因此训练配置改为复用同一函数: ```python config\\\["device\\\_backend"] = \\\_backend\\\_label(get\\\_device()) ``` 这是一处展示和审计语义修复,不改变 worker 的设备选择和 PyTorch 调用。复验后的历史明确记录 `device\\\_backend: rocm`。 ### 7\. 训练产物 Preview 的双重自锁 真实训练完成后,`has\\\_preview\\\_model=true` 并不能证明 Preview 可生成。第一次调用签名 Preview URL 在 300 秒后超时,没有 worker、没有 OOM。 根因有两个: 1. keep-warm 中间件把 Preview Chat 识别为推理请求,并先持有进程级生命周期锁; 2. Preview 内部调用 `load\\\_model\\\_gated()`,再次获取同一个非可重入 `threading.Lock`;绕过重复获取后,model-switch drain 又把当前 Preview 请求本身当成“其他正在推理的请求”等待。 不能简单把锁改成 `RLock`:同一个事件循环中的不同协程运行在同一线程,`RLock` 会错误地允许两个独立请求同时进入。最终方案是给内部加载增加两个默认关闭的参数: ```python await load\\\_model\\\_gated( LoadRequest(model\\\_path=str(path)), request, DEFAULT\\\_ADMIN\\\_USERNAME, lifecycle\\\_gate\\\_held=True, current\\\_request\\\_counted=True, ) ``` 只有 Preview 调用传入它们;普通 `/load` 路径仍获取原锁,跨 event loop 串行化不变。定向测试 19/19 通过。修复后 cold Preview 54.47 秒完成,warm 请求 4.682 秒,worker 明确报告 ROCm、K100、FlashAttention 和 LoRA adapter enabled。 ## 六、实际测试结果 |测试|结果|数据| |-|-|-| |HIP vector add|PASS|1,048,576 元素,0.729 ms| |hipBLAS SGEMM|PASS|1024 方阵,17.393 TFLOP/s 短测| |PyTorch FP32/FP16/BF16|PASS|forward/backward 均通过| |Triton|PASS|gfx928 vector add| |Qwen3 0.6B BF16 LoRA|PASS|2 steps,loss 4.6922,峰值约 1.30 GiB| |Studio 真实训练|PASS|1 step,loss 2.6198,产品墙钟 64.042 s| |训练 adapter Preview|PASS(传输)|cold 54.47 s,warm 4.682 s| |FlashAttention|PASS|dense/varlen/GQA forward/backward| |Qwen2.5 0.5B GGUF|PASS|prompt 249.7 tok/s,生成 316.2 tok/s| |Gemma 26B GGUF|PASS|warm 生成 65.6–68.3 tok/s| |vLLM Qwen3 eager|PASS|22.31 output tok/s| |RAG|PASS|TXT/PDF/DOCX,三种检索和签名预览| |浏览器产品流程|PASS|7/7 Chat 200,历史、重生成、Recipes、账号轮换等| |模型自主工具|PASS|Gemma 完成 Python 和 Web Search 闭环| 性能数字只用于说明当前环境可工作,并非跨机器 benchmark。特别是首次模型加载、缓存状态、prompt 长度和 GGUF 量化方式都会显著改变结果。 ## 七、部署与使用 本文交付包有两种使用方式: 1. **离线镜像方式**:加载 `docker-images.tar.zst`,不需要重新构建 Python 环境; 2. **源码构建方式**:使用包内的优化源码、Dockerfile 和本地 FlashAttention wheel重建。 ### 1\. 预检 ```bash cd unsloth-studio-k100-dtk2604-20260812 ./bin/preflight.sh ``` 必须满足: * x86\_64 Linux; * Docker Engine 和 Compose v2; * `/dev/kfd`、`/dev/mkfd`、`/dev/dri`; * `/opt/hyhal` 可挂载; * 单卡 K100-ai/gfx928; * 至少 32 GiB shared memory 配额和足够的镜像磁盘空间。 ### 2\. 加载镜像并启动完整服务 ```bash ./bin/load-images.sh ./bin/start.sh full curl http://127.0.0.1:18887/api/health ``` 首次启动会把 bootstrap 密码写到: ```text state/full/auth/.bootstrap\\\_password ``` 用 `unsloth` 登录后必须立即修改。密码未修改时,Studio 会按安全策略在一小时后停止。 ### 3\. 稳定回滚服务 ```bash ./bin/stop.sh full ./bin/start.sh stable curl http://127.0.0.1:18888/api/health ``` 不要在单卡上同时执行两个服务的训练任务。服务可以同时处于空闲状态,但模型加载和训练会争用同一张卡。 ### 4\. 使用内置小模型 便携包附带官方 Qwen2.5-0.5B-Instruct Q4\_K\_M: ```text /workspace/models/qwen2.5-0.5b-instruct-gguf/qwen2.5-0.5b-instruct-q4\\\_k\\\_m.gguf ``` 它适合验证 Chat、SSE、历史和 UI,不适合代表大模型工具规划能力。可将自己的 Gemma/Qwen GGUF 放入包内 `models/`,容器会以 `/workspace/models` 只读/读写挂载方式发现它。 ### 5\. 提交训练 Studio UI 中选择本地 safetensors 模型和上传数据集,关闭 4-bit,使用 BF16、LoRA、`adamw\\\_torch` 和 SDPA/自动 attention。API smoke 示例: ```bash STUDIO\\\_PASSWORD='<修改后的密码>' \\\\ python3 smoke/studio\\\_training\\\_http\\\_smoke.py \\\\ --base http://127.0.0.1:18887 \\\\ --model /workspace/models/your-transformers-model ``` 本地数据集必须通过 Studio 上传,或放在其受控 `assets/datasets` 根目录。不要为了方便放宽绝对路径校验;第一次测试对 `/workspace/data/...` 的 HTTP 400 正是正常的任意文件读取防护。 ## 八、维护和安全注意事项 ### 不要做的事 * 不要刷 VBIOS 或伪装 PCI Vendor; * 不要把 `torch.version.cuda` 改成假值; * 不要用 import 成功证明 bitsandbytes/FlashAttention kernel 可用; * 不要让 pip 自动解析 FlashAttention 的 torch 依赖; * 不要在脏 PyTorch 源码树上持续叠补丁; * 不要把带 terminal/Python 工具的 Studio 直接绑定到 `0.0.0.0`; * 不要在单卡上同时运行训练、大模型 Chat 和 vLLM 压测。 ### FlashAttention 回滚 如果某个模型的 head dimension、GQA 或 backward 不稳定: 1. 切换到 stable profile; 2. 设置 `attn\\\_implementation="sdpa"`; 3. 禁用 compile 和不稳定 kernel; 4. 保留原始错误和模型形状,再决定是否增加模型级 allowlist。 ### 版本约束 当前 FlashAttention wheel 不能随意用于: * Python 3.11/3.12; * PyTorch 2.5/2.7; * DTK 24.x 或其他 DTK 版本; * ARM64; * 普通 CUDA torch。 任一项变化都应重新选择 wheel,而不是改文件名强行安装。 ### 数据与许可证 离线包不包含现有用户的账号数据库、密码、Chat 历史、RAG 内容或 Gemma 大模型。Unsloth Studio 的相应源码包含 AGPL-3.0-only 标识;对外分发或提供网络服务前,应阅读包内上游许可证并履行相应义务。Qwen 模型和 llama.cpp 也保留各自的来源、commit 和许可证说明。 ## 九、为什么这条路线更可维护 这次适配真正新增的行为代码很少:bitsandbytes 能力门控、一个 sqlite-vec 查询、一处 ROCm 历史标签、一个 Preview 生命周期修复和一个关机时序调整。硬件特有内容被控制在四处: ```text DTK 26.04 base image ├── libgalaxyhip / hyhal ├── gfx928 target ├── matched FlashAttention wheel └── matched llama.cpp HIP runtime 通用应用层 ├── PyTorch HIP torch.cuda semantics ├── Transformers / TRL / PEFT / Unsloth ├── vLLM eager └── Unsloth Studio Train / Chat / RAG / Tools ``` 这意味着未来升级时可以逐层验证,而不是重新维护一个“海光专版 AI 平台”:先验证 DTK runtime,再验证 PyTorch,再验证 kernel,最后验证 Studio 产品链路。任何一层失败都有明确回滚点。 ## 十、结语 非 CUDA 加速卡最容易掉进两个极端:要么完全依赖厂商 demo,要么为了兼容而伪造 CUDA 身份。K100-aiDCU 的实际结果说明还有第三条路:承认底层 ABI 的厂商边界,但让 PyTorch HIP、Transformers、Unsloth、vLLM 和 llama.cpp 各自保持清晰、可测试、可回滚的接口。 最终价值不只是“模型能跑”,而是训练任务能从 Studio 提交并保存,产物能 Preview,Chat 能在真实浏览器中多轮使用,RAG 和工具能工作,错误能保留,补丁能反向应用,服务能安全地留在回环地址。这才是一套可以继续维护的产品部署。
bw100
deepspeed
apex
torch
LLama-Factory
全部评论(1)
只看楼主
杜
杜逸凡
楼主
1楼
本文所需镜像或源码:https://github.com/Entropic-Silence/unsloth-studio-k100-dtk2604
8/13
没有更多内容了
--
楼主
Level.2
0 帖子
楼主热帖
暂无数据