news 2026/9/26 9:57:00

Atlas 300V部署YOLO实战:从ONNX到OM的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Atlas 300V部署YOLO实战:从ONNX到OM的完整指南

如果你最近在调研边缘AI推理硬件,Atlas这张卡一定绕不开。尤其是Atlas 300V 24G,讨论的人不少,但很多话题停留在"是不是运算加速卡"这个层面。我的回答很直接:它确实是运算加速卡,专门为AI推理设计的,而且我手上的生产项目就是拿它跑YOLO做目标检测。这篇文章不打算复读宣传册上的参数,而是完整分享一次从零开始的部署经历——包括这张卡到底是什么定位、为什么我选它而不是GPU、PyTorch训练好的YOLO模型怎么一步步变成能跑在Atlas上的OM文件、推理代码怎么写、性能怎么调优,以及过程中遇到的那些让人头疼的问题。

如果你想在边缘侧或者已有服务器上做视频目标检测、工业质检、智慧安防这类项目,手里正好有一张Atlas 300V 24G,或者正纠结要不要入手,这篇应该能帮你少走不少弯路。

1. Atlas 300V 24G是什么,先把它看透

1.1 一张怎样的卡:外观、参数与定位

第一次拿到这张卡的时候,说实话我愣了一下——半高半长、单槽、被动散热片,没有独立供电接口,猛一看像块大号的NVMe SSD。但它确确实实是一张AI推理加速卡,基于昇腾310P系列芯片,板载24GB LPDDR4X内存。这颗芯片采用达芬奇架构,里面是专门为神经网络矩阵运算设计的AI Core,不是通用GPU的流处理器。

这张卡的定位非常明确:跑推理,不跑训练,也不跑图形渲染。它要做的事情就是把已经训练好的模型,以低功耗、高吞吐的方式跑起来。24GB内存听起来不大,但对于目标检测模型来说相当够用。像YOLOv5s这种模型,权重文件也就几MB到几十MB,模型加载进内存后,剩下的空间足够让你开多个推理流、多batch并发,甚至把多个模型同时放进去做服务。我自己在项目里就是一张卡同时跑检测和分割两个模型实例,内存余量还很充足。

功耗方面,Atlas 300V系列走的是低功耗路线,整卡功耗比同算力的GPU低不少,加上被动散热设计,部署在现有机房服务器里基本不用改散热方案。不过要注意,被动散热依赖服务器自身的风道,机箱风扇如果太弱,长时间高负载跑卡会过热降频,这个后面在问题排查部分详细说。

注意:Atlas 300V有普通版和Pro版,算力和部分规格有差异,购买和开发前一定先确认自己手里是哪个型号、对应的SoC版本是什么。ATC转换模型时要填--soc_version,填错会导致模型加载失败。

1.2 是运算加速卡,但不能对着GPU的思维用

回到那个高频问题:"Atlas 300V 24G是运算加速卡吗?"答案可以拆成两半。

说它是,因为它确实做运算加速,而且是硬件级的神经网络加速。它的算力体现在AI Core的矩阵乘加运算上,对卷积、全连接这类算子的执行效率非常高。YOLO这类目标检测模型,网络主体就是一堆卷积和上采样,正好是它的强项。

但说"不能按GPU的思维用"也对。它不是通用计算卡,不支持CUDA,不能直接跑PyTorch的.pth权重,也不适合用来做渲染或者跑通用并行程序。它的软件生态是CANN一套,模型要先转换成OM格式才能被硬件识别执行。这个限制让它在灵活性上不如GPU,但换来的是更低功耗和更低的单位算力成本。

我做了个简单的对比表,方便你快速判断它适不适合自己的场景:

对比维度通用GPU(T4/RTX系列)Atlas 300V
芯片类型GPU(流处理器/CUDA核心)AI专用ASIC(达芬奇AI Core)
编程生态CUDA/OpenCLCANN/AscendCL
模型格式TensorRT/ONNX Runtime等OM(ATC转换产出)
主要场景训练、推理、图形通用固定模型推理
功耗通常70W-250W较低
灵活性强聚焦AI算子

如果你的需求是"找一个能随时跑各种新模型的卡",Atlas不会让你满意;但如果你和我一样,是"模型已经定死,就准备大规模部署",那它反而比GPU划算得多。

2. 为什么选Atlas 300V部署YOLO:我的选型思考

2.1 算力功耗比:边缘侧部署的账要这么算

我遇到的实际项目是这样一个情况:机房里有几台现成的服务器,要在不更换服务器整机的前提下,增加8路1080p视频流的实时目标检测能力,模型用YOLOv5s,要求每路不低于25帧。

一开始我想直接插GPU。但算了笔账:要同时跑8路YOLOv5s,单路25帧,对单卡推理吞吐的要求大约是200FPS。消费级显卡显存够但功耗高、稳定性不及专业卡,专业推理卡价格又上去了。而且机房的服务器电源和散热余量有限,加装一张大功率GPU意味着供电和风道都要动,工程成本一下就上去了。

Atlas 300V 24G在这种场景下优势就出来了。首先是功耗,整卡不用外接供电,被动散热,插上就完事;其次是24G内存,模型可以全部常驻,多路视频帧可以组batch推理,不再像以前那样抠显存。实际跑下来,一张卡吃下8路YOLOv5s(配合合适的批处理策略)是完全够用的。

如果你手头是Atlas 300V Pro,算力会再高一些,跑更大的模型或者更多路数也从容。总之,在"固定模型、固定场景、大批量部署"这种典型边缘推理需求里,Atlas 300V的算力功耗比确实是个不能忽视的选项。

2.2 从PyTorch到OM:理解昇腾的模型生态

用Atlas部署YOLO,很多人第一反应是"那我用它来训练吗?"不用。训练还是在你的常规环境(比如GPU服务器或者云端)完成,Atlas负责的是训练之后的推理环节。

整个部署链路是:PyTorch训练好的模型 → 导出ONNX → 用ATC工具转换成OM → 部署在Atlas上,通过AscendCL(也常叫pyACL/C++ ACL)接口调用推理。

这个模型转换步骤是昇腾生态和CUDA生态最大的区别。CUDA生态里,你训练完可以直接用PyTorch或者ONNX Runtime加载权重跑推理。昇腾不是不行,但官方推荐的性能最优路径是转成OM。OM格式相当于把计算图、算子、权重都编排好,和硬件深度绑定,运行时不需要再做算子解析和优化,性能更好。

理解这个"训练生态与推理部署解耦"的思路很重要。模型转换时,算子是否能被昇腾原生支持,直接决定了转换是否顺利。YOLOv5、YOLOv8这类主流检测模型,用到的卷积、BN、SiLU、Upsample、Concat这些算子,CANN基本都有原生支持,这也是我敢选YOLO部署的原因之一。如果你用的是一个非常冷门的模型结构,里面有些特殊算子,转换时就要小心,可能要多花不少时间处理算子替换问题。

2.3 pyACL还是mxVision:工具选型别纠结太久

Atlas的推理开发接口主要有两条路:一条是用AscendCL直接写推理逻辑,Python的话就是pyACL,C++则是C++ ACL;另一条是用MindX SDK(mxVision)做流程编排,通过配置pipeline把解码、预处理、推理、后处理串联起来。

我的建议是分阶段选择。前期做算法验证、看模型能不能在Atlas上跑通、性能大概多少,用pyACL就够了,灵活、少一层封装,出问题也好定位。等到项目要上生产,如果只是简单的"输入视频流输出检测结果",mxVision的编排确实方便;但我自己生产环境的经验是,一旦业务逻辑复杂起来——比如多路流管理、自定义跟踪器、结果上报、异常处理——用C++ ACL反而更好控制。

所以别在工具选型上纠结太久。先跑通一个pyACL的最小demo,性能、精度、工程模型都验证OK了,再考虑是不是值得上mxVision或者重写成C++。

3. 从0到1:Atlas 300V部署YOLOv5的完整流程

3.1 环境准备:驱动、固件、CANN工具链

正式开始部署前,先把环境装好。这一步最磨人,也最关键,因为后续所有问题,百分之八十都和版本不配套有关。

第一,确认服务器和操作系统兼容性。Atlas 300V是标准PCIe卡,一般x86服务器都能插,但建议去官方查一下兼容性列表,避免主板或者机箱空间不够。操作系统方面,Ubuntu 20.04/22.04、openEuler这些主流的都支持,但内核版本会有要求,装之前先看版本配套表。

第二,安装驱动和固件。这里面有个容易忽略的点:NPU驱动和固件是两个不同的包,都要装。驱动提供内核模块和用户态接口,固件是卡上芯片运行的程序。两个必须配套,版本不一致或单独升级其中一个,都会导致设备状态异常。装完以后用npu-smi info验证,能看到卡型号、芯片状态、内存占用,说明驱动和固件基本没问题。

第三,安装CANN工具包。CANN是昇腾的计算架构,包含ATC、AscendCL、算子库等。安装之后要source /usr/local/Ascend/ascend-toolkit/set_env.sh加载环境变量,然后跑一个简单的sample确认接口可用。

注意:驱动、固件、CANN三个版本必须对照官方的版本配套表来选。我第一次部署时图省事装了个最新版CANN,结果驱动不兼容,npu-smi看得到卡但一调接口就报设备异常,最后老老实实回退到配套版本才解决。这一步别偷懒。

装好之后,建议立刻跑一下CANN自带的示例(比如resnet50分类demo),确认整条链路是通的。这样后面排查问题的时候,至少能确定问题出在模型转换还是环境本身。

3.2 模型转换:PyTorch权重到OM文件

环境好了,接下来把YOLO模型转到Atlas上。

我的做法是用YOLOv5官方仓库,训练或者下载预训练权重之后,先导出ONNX。这里有几个细节需要注意:

  • 导出ONNX时,opset版本要设置成11到13之间,太老或者太新的opset可能导致ATC转换时算子兼容问题。
  • YOLOv5导出时会默认带上NMS后处理吗?不会,但有些改造过的仓库会把它加进去。我建议导出时把后处理留在模型外面。NMS这类动态逻辑在昇腾上虽然也有算子支持,但会引入不少转换难题,而且性能不见得比在CPU上做快。模型只负责输出原始预测结果就行了。
  • 输入尺寸建议固定。比如固定为1x3x640x640,训练如果用640就保持640。不要搞动态shape,ATC对动态shape的支持比较有限,而且固定shape才能用AIPP优化。

导出ONNX之后,用ATC工具转换:

atc --model=yolov5s.onnx \ --framework=5 \ --output=yolov5s_bs1 \ --input_shape="images:1,3,640,640" \ --soc_version=Ascend310P3 \ --insert_op_conf=aipp.cfg

参数说明:

  • --framework=5:表示输入模型是ONNX。
  • --output:输出文件名。
  • --input_shape:固定输入shape,batch为1,3通道,640x640。
  • --soc_version:根据芯片型号填写。Atlas 300V用的是昇腾310P系列,常见填Ascend310P3,具体按你的芯片版本查表。
  • --insert_op_conf:插入AIPP配置文件,把图像预处理合并到模型计算流程里。

为什么建议配AIPP?因为图像推理之前通常要做resize、色域转换、归一化。如果不配AIPP,这些操作全在CPU上做,视频流一多CPU就吃紧;配了AIPP,这些预处理就跑到卡上的专用单元里,CPU负载大幅降低。AIPP配置里,mean_chn和var_reci_chn要和你训练时的归一化参数一致。

YOLOv5训练时用的是ImageNet的mean/std,均值是123.675、116.28、103.53,方差的倒数是0.01712475、0.017507、0.01742918,可以直接参考。

转换成功后会生成.om文件。如果转换失败,报错里一般会指名是哪个算子不支持。不用慌,先去查昇腾算子清单,看有没有替代算子;实在没有,有些算子还能用--op_type指定为AICPU实现,变通一下。

3.3 推理代码:用pyACL写一个最小检测服务

模型转换好了,我们写推理代码。下面是我常用的pyACL最小流程,结构很固定,多看几遍就能记住。

import acl import cv2 import numpy as np # 1. 初始化 acl.init() ret = acl.rt.set_device(0) context, ret = acl.rt.create_context(0) stream, ret = acl.rt.create_stream() # 2. 加载模型 model_id, ret = acl.mdl.load_from_file("yolov5s_bs1.om") model_desc = acl.mdl.create_desc() ret = acl.mdl.get_desc(model_desc, model_id) input_size = acl.mdl.get_input_size_by_index(model_desc, 0) output_size = acl.mdl.get_output_size_by_index(model_desc, 0) input_ptr, ret = acl.rt.malloc(input_size, 2) output_ptr, ret = acl.rt.malloc(output_size, 2) # 3. 预处理:只做resize和通道转换,归一化交给AIPP def preprocess(img): img = cv2.resize(img, (640, 640)) img = img[:, :, ::-1] # BGR -> RGB img = np.ascontiguousarray(img) return img # 4. 推理 def infer(img): data = preprocess(img) acl.rt.memcpy(input_ptr, input_size, data, input_size, 2) ret = acl.mdl.execute(model_id, input_ptr, input_size, output_ptr, output_size) result = acl.util.np_from_ptr(output_ptr, output_size, np.float32) return np.copy(result) # 5. 后处理:YOLOv5输出为 [1, 25200, 85],需要解析和NMS def compute_iou(box, boxes): x1 = np.maximum(box[0], boxes[:, 0]) y1 = np.maximum(box[1], boxes[:, 1]) x2 = np.minimum(box[2], boxes[:, 2]) y2 = np.minimum(box[3], boxes[:, 3]) inter = np.maximum(0, x2 - x1) * np.maximum(0, y2 - y1) area_box = (box[2] - box[0]) * (box[3] - box[1]) area_boxes = (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) return inter / (area_box + area_boxes - inter + 1e-6) def postprocess(pred, conf_thres=0.25, iou_thres=0.45): pred = pred[0] # [25200, 85] class_scores = pred[:, 5:].max(axis=1) class_ids = pred[:, 5:].argmax(axis=1) mask = class_scores > conf_thres xywh = pred[mask, :4] scores = class_scores[mask] class_ids = class_ids[mask] x1 = xywh[:, 0] - xywh[:, 2] / 2 y1 = xywh[:, 1] - xywh[:, 3] / 2 x2 = xywh[:, 0] + xywh[:, 2] / 2 y2 = xywh[:, 1] + xywh[:, 3] / 2 boxes = np.stack([x1, y1, x2, y2], axis=1) idxs = np.argsort(scores)[::-1] keep = [] while len(idxs) > 0: i = idxs[0] keep.append(i) ious = compute_iou(boxes[i], boxes[idxs[1:]]) idxs = idxs[1:][ious < iou_thres] return boxes[keep], scores[keep], class_ids[keep]

代码里需要注意几点。

第一,acl.rt.memcpy的最后一个参数是拷贝类型,2代表host到device,语义上要搞清楚。

第二,acl.util.np_from_ptr拿到的是device内存映射回来的numpy数组,但它是共享底层内存的,最好用np.copy拷回去再处理,避免后续操作把推理内存污染。

第三,后处理不能省。YOLOv5原始输出是一个[1, 25200, 85]的张量,25200是640x640输入下三个尺度锚框的总数,85是4个坐标、1个置信度、80个类别。你要解析出坐标,做置信度过滤,再做NMS。NMS一般用CPU跑就行,在批量检测场景里它不太会成为瓶颈。

跑通之后,可以对一张测试图做推理,把检测框画出来看效果。这一步主要是验证前面的链路有没有问题。

3.4 我的第一次跑通记录:性能摸底

我第一次跑通YOLOv5s在Atlas 300V 24G上的推理,bs=1,输入640x640,从模型加载完成开始计时,单帧推理时延在20到40毫秒之间波动(具体数值受CANN版本、机器配置影响很大,仅供参考)。这个数字初看不惊艳,但注意这是没做任何调优的结果,而且不是纯推理,还包括了内存拷贝和部分预处理。

接着我做了两个小验证:一是把后处理从同步改成异步梳理,二是测试连续推理而不是单帧,吞吐量立刻有明显提升。这说明性能优化空间很大,后面专门有节讲怎么调。

4. 性能调优与生产化:让YOLO在Atlas上跑得更稳

4.1 三个立竿见影的调优手段:AIPP、固定shape、多batch

如果推理链路已经跑通,下一步就要看性能了。我的经验是,先做这三件事,收益最大、改动最小。

第一,打开AIPP。前面转换模型时已经配置了AIPP,但代码里如果还自己在CPU上做归一化,等于白配。记得把预处理只保留resize和通道转换,归一化交给卡。CPU侧少了一大块浮点运算,多路视频时差别很明显。

第二,固定shape。如果你模型转换时用了动态shape,运行时的shape推导、内存分配都会增加额外开销。把输入定为1x3x640x640,在工程上会方便很多,模型实例的内存管理也更高效。

第三,使用多batch。如果场景是多路视频流,不要一路一路地送单帧推理,把多路帧拼成一个batch送进去,能充分利用AI Core的并行计算能力。举个实际例子,把4路1080p视频帧拼成batch=4,每路单独看时延略增,但总吞吐比一路一路跑高得多。batch怎么拼?需要维护一个队列,等够batch数或者超时时间到了再一起推理,这是典型的生产级优化手段。

注意:多batch会增加单次推理的时延,所以不是越大越好。如果对时延敏感(比如实时交互场景),要测算batch增大后的时延增量,找一个吞吐和时延都合适的平衡点。

4.2 生产落地:多路视频流应该怎么搭

前面讲的技术,在单张图片或者单路视频上做验证没问题,但真到了生产环境,往往是多路视频同时进。我的生产架构大概是这样的:

RTSP流 -> FFmpeg/设备SDK拉流 -> DVPP硬解码 -> AIPP预处理 -> ACL推理 -> 后处理(NMS) -> 业务输出

这里要特别说一下解码环节。很多人在Atlas上跑视频检测,习惯用OpenCV的VideoCapture或者FFmpeg的软解码拉流,然后直接把帧交给模型。这个方案在跑通阶段没问题,一路两路还好,一旦到了8路、16路,CPU解码开销会和模型预处理抢资源,整机吞吐直线下降。

昇腾卡上有DVPP模块,专门做视频硬件解码,支持H.264/H.265,直接输出YUV420SP格式,这个格式对后续AIPP也友好。把解码放到DVPP上,CPU只负责拉流和控制逻辑,视频流再多的场景也不至于被解码卡死。

架构搭好之后,建议用流水线的方式组织模块:拉流线程、解码线程、推理线程、后处理线程各司其职,中间用队列传递数据。异步化做得好不好,直接决定多路视频场景下的稳定性。

4.3 INT8量化:再压榨一截性能

Atlas的AI Core对INT8算力利用效率高,如果模型能接受精度小幅下降,INT8量化是很值得做的优化。YOLOv5s转成INT8后,推理时延往往能再降一大截。

量化工具用AMCT(昇腾模型压缩工具),步骤不复杂:准备一批代表真实场景的校准图片,加载模型做校准,然后导出量化后的OM模型。校准集很关键,最好覆盖你实际部署时会遇到的场景。比如你做的是工地安全帽检测,校准图就应该以工地场景为主,而不是拿一个不相关的公开数据集。

我实测下来,YOLOv5s转INT8后,mAP一般下降2到3个点,有时甚至更少,在多数业务场景里完全可接受。但如果你的检测目标是细小物体、或者对框的精度要求极高,量化掉精度就可能让产品不达标。所以上线前一定要用验证集评估。

提示:量化后一定要重新测试性能,不要只看转换时输出的预估性能。实际部署中的时延、内存占用变化,都要以实测为准。

5. 常见问题与排查技巧实录

5.1 部署期高频报错速查表

这一节我把部署过程中最容易遇到的问题整理成了一张速查表,都是我实际碰到过的,你照着排查基本能解决。

现象可能原因排查与解决办法
npu-smi info看不到卡驱动未装好、卡没插好、权限不足检查驱动加载,确认卡在PCIe槽中插紧;普通用户加入HwHiAiUser组后重新登录
调用ACL接口报"Device not ready"驱动与固件版本不匹配对照版本配套表,把驱动和固件一起升级到匹配版本
acl.rt.set_device报错CANN版本和驱动不兼容统一回退或升级到配套版本;source正确的环境变量
ATC转换时报算子不支持模型里有昇腾不支持的算子查算子清单,优先替换成支持的算子;必要时用AICPU方式绕过
推理输出全是0输入数据格式不对、AIPP配置错误检查输入通道顺序、是否归一化两次、mean/std是否写错
多batch推理报shape错误模型固定为bs=1但传了bs=4重新用对应batch转换模型,或者保证输入shape一致
跑一阵后卡变热、推理变慢被动散热,机箱风道不足检查风扇转速,加强服务器风道;降低持续负载

5.2 几个印象深刻的坑

第一个坑是权限。驱动都装好了,npu-smi info也正常,但一跑Python推理就报/dev/davinci0权限拒绝。原因是默认只有HwHiAiUser组的用户能访问设备节点。解决办法很简单:把当前用户加入HwHiAiUser组,重新登录就OK。这个坑太基础了,但很容易被忽视。

第二个坑是进程残留。开发调试阶段,我有一次连续跑了好几轮推理脚本,某一次突然报内存不足。检查发现是前面的进程退出了,但模型句柄、context没有释放干净。用npu-smi info可以看到卡的显存占用居高不下。以后凡是要反复跑模型,记得在脚本里加try...finally,确保finally里释放模型和context;或者在调试阶段,每次改完代码主动查一下有没有残留进程,该杀的杀掉。

第三个坑是ONNX动态维度。有一版模型转换时为了图省事,导出的ONNX带着动态batch维度。ATC转换确实成功了,但一跑多batch推理就报shape错误,查了半天发现是模型输入还带dynamic标记。解决方式就是转换时强制固定--input_shape,别贪这个动态的便利。

第四个坑是关于AIPP的色域顺序。YOLOv5训练时用的是RGB输入,但OpenCV读出来是BGR。AIPP里有个rbuv_swap_switch开关,相当于是RGB和BGR互换。如果这个开关没开,而且你又没在代码里做通道翻转,模型会性能大降——目标一个都检测不出来。这类问题不会报错,只能靠肉眼排查,很难受。

5.3 帧率上不去?这样定位瓶颈

最后给一个排查性能问题的通用方法。如果你觉得部署完模型推理速度不理想,先别慌,把整个链路拆开,逐个环节打点计时。

用一份测试脚本分别统计:

  • 拉流和帧读取耗时
  • 解码耗时(软解还是DVPP,差距很大)
  • 预处理耗时(resize、色域转换、归一化)
  • 推理耗时(acl.mdl.execute)
  • 后处理耗时(解析、NMS)

正常情况下,推理耗时应该占大头。如果预处理占比高,说明该上AIPP;如果解码占比高,说明该上DVPP;如果内存拷贝占比高,检查是不是频繁在host和device之间搬数据,能不能复用内存;如果推理本身就慢,考虑INT8量化。

我遇到过一种情况是,单帧推理本身没什么问题,但多路视频一开,帧率就往下掉。后来排查发现是多个推理请求混在同一个stream里,互相排队。改用多stream,让不同路的推理可以并行执行,情况立刻改善。Atlas支持创建多个stream,多路场景下把stream分开是很重要的工程手段,这个细节在官方文档里往往不会强调,但非常实用。

最后分享一点我自己的体会。Atlas 300V 24G这张卡,用对了场景其实是很有性价比的,但它和GPU是两种思维模式。GPU像是万能工具箱,什么都能干,什么都能临时上手;Atlas更像是流水线上的专用机器,前期调试成本高一些,一旦模型转好、链路调通,后面就是稳定、低功耗地跑。如果你正准备在Atlas上部署YOLO,我建议先别急着做性能优化,老老实实把"PyTorch导出ONNX、ATC转OM、pyACL跑推理"这条链路走通,再考虑AIPP、多batch、INT8量化这些进阶手段。第一次部署的时候我也被版本不匹配、算子不支持这些事折磨过,但熟悉之后,再上新的检测模型就快多了,基本一次转换就能搞定。希望这篇能帮你少踩几个坑。

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

5GSA无线网切片配置实战:S-NSSAI、PLMN ID与VLAN ID映射落地指南

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

作者头像 李华
网站建设 2026/9/26 9:55:52

Agent of Empires Diff审查指南:AI代理的代码改动一目了然

Agent of Empires Diff审查指南&#xff1a;AI代理的代码改动一目了然 【免费下载链接】agent-of-empires Manage multiple Claude Code, OpenCode agents from either TUI or Web for easy access on mobile. Also supports Mistral Vibe, Codex CLI, Gemini CLI, Pi.dev, Cop…

作者头像 李华
网站建设 2026/9/26 9:53:10

MCP 完整学习指南与 Spring AI 实战:从零搭建可复用的 MCP 服务端

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

作者头像 李华
网站建设 2026/9/26 9:52:56

macOS Homebrew 四层适配指南:权限、架构、换源与生态

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

作者头像 李华
网站建设 2026/9/26 9:52:11

FAST-LIO2落地实战:ikd-tree增量地图与重定位全链路解析

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

作者头像 李华