首页/新闻资讯/正文详情

Atlas 300V Pro部署YOLO实战:昇腾推理卡模型转换与调优指南

发布时间:2026/9/25 6:03:43 来源:云帆数科 栏目:资讯中心
Atlas 300V Pro部署YOLO实战:昇腾推理卡模型转换与调优指南
一块Atlas加速卡到底算不算“运算加速卡”这个问题我在不少群里见人问过尤其是当你说到“atlas 300V 24G”这个型号的时候很多人第一反应是24G显存那是不是类似游戏显卡那样做渲染加速的还是像计算卡那样做AI训练的答案其实都不完全对。Atlas 300V Pro这块卡本质上是昇腾310P处理器驱动的AI推理卡24GB是它的显存配置但它的主职是推理不是训练也不是传统意义上的视频渲染加速。它最典型的落地场景就是用YOLO这类目标检测模型做视频解析、工业质检、安防巡检把训练好的权重文件转换成语雀平台能跑的om格式然后用ACL接口或者推理引擎去调它。这篇内容我会从硬件选型、环境搭建、模型转换、推理代码到性能调优完整走一遍用Atlas 300V Pro部署YOLO的流程。适合刚拿到Atlas卡想快速跑通目标检测的开发者也适合正在做选型、不确定该买300I还是300V、不确定这块卡能不能满足你业务需求的人。1. 先搞清楚Atlas 300V Pro到底是什么卡“运算加速”这四个字的真相1.1 300I和300V到底差在哪很多人被Atlas的型号搞得一头雾水我刚开始也一样。Atlas 300I Pro和Atlas 300V Pro都是基于昇腾310P处理器的推理卡显存都是24GB都支持FP16和INT8精度。从表面参数看几乎一模一样。区别在定位上300I系列强调的是通用的AI推理目标检测、图像分类、语义分割都能干300V系列则特别强化了视频编解码能力内置了硬件级视频解码模块可以直接从RTSP流拉流解码然后在卡上完成推理和编码输出。如果你要做的是视频流实时分析300V的硬件解码通道数会比300I高不少有些厂商的高密度视频分析服务器用的就是300V。所以“Atlas 300V 24G是运算加速卡吗”这个问题的正确答案是它是AI推理加速卡它计算的核心对象是神经网络算子的张量运算而不是像GPU那样同时兼顾图形渲染。它也不适合做训练你要真想拿它跑训练大概率会卡在算子支持和显存带宽上。1.2 24GB显存意味着什么以太网上一份有趣的对照“显存大小决定了你能同时跑多大的模型、多少路视频”。YOLOv5s的权重文件大约14MB一个batch_size为1的推理占用大概1GB左右包括中间特征图24GB可以轻松同时跑多个模型或者用更大的batch_size来提升吞吐。但千万别把24GB和NVIDIA显卡的24GB画等号。昇腾的显存由专用硬件管理你没法像使用普通GPU显存那样随心所欲地读写所有地址。而且昇腾的AI Core集群架构决定了它在算子调度上有一套自己的软件栈——CANN你的代码必须通过ACL接口或MindSpore等框架才能控制和访问它。1.3 部署YOLO时的硬件特性边界在Atlas 300V Pro上跑YOLO有几个边界条件要提前知道它只做推理不做训练。训练还是老老实实放到GPU集群。模型需要转换为om格式PyTorch的.pt文件不能直接加载。输入Tensor的排布是NHWC不是PyTorch默认的NCHW转换时如果不注意推理结果会完全错乱。动态shape支持有限建议在转换阶段就固定输入尺寸或者明确使用动态维度配置。后处理NMS等建议保留在CPU侧完成昇腾平台的算子集合对NMS的支持并不完善硬要用NPU做反而会拖慢速度。理解了这些边界后面的流程才不会走弯路。2. 第一次点亮卡片驱动、固件和CANN的版本地狱2.1 安装前必须搞清楚的事项拿到Atlas 300V Pro后第一件事不是立刻插上去跑模型而是梳理整个软件栈。昇腾平台的软件栈和CUDA体系有很大区别分为三块驱动driver、固件firmware和CANN工具包cann toolkit。驱动负责操作系统与硬件之间的通信提供npu-smi等管理工具。固件部署在芯片内部负责底层算子的调度和执行。CANN昇腾的计算架构类似CUDA的工具包包含ATC模型转换工具、ACL运行时库、算子库等。这三者的版本必须匹配。昇腾官方发布了版本配套表比如CANN 8.0.RC1对应XX驱动版本、YY固件版本。你可以通过Ascend社区提供的“ascend-deployer”脚本自动拉取匹配版本也可以手动下载。我的建议是能用ascend-deployer自动部署就不要手动装。因为手动装最容易出现版本失配然后npu-smi能看到卡但跑ATC或加载模型时报各种莫名奇妙的错误。2.2 实际安装操作以x86架构的Ubuntu 20.04/22.04为例整个安装过程大致如下# 1. 安装依赖 sudo apt-get update sudo apt-get install -y gcc g make cmake zlib1g zlib1g-dev openssl libsqlite3-dev libssl-dev libffi-dev unzip pciutils net-tools git # 2. 下载ascend-deployer git clone https://gitee.com/ascend/ascend-deployer.git cd ascend-deployer # 3. 查看可用的版本组合 python3 ascend-deployer.py --list # 4. 选择与你的CANN版本匹配的驱动和固件 python3 ascend-deployer.py --install --cann8.0.RC1安装完成后用npu-smi info验证npu-smi info正常输出会显示一张卡芯片型号类似Ascend 310P显存24GB温度、功耗等状态正常。2.3 常见安装坑我踩过最典型的三个坑这里直接写给你第一个坑环境变量没生效。CANN安装完之后需要source/usr/local/Ascend/ascend-toolkit/set_env.sh有些装完就忘了导致atc命令找不到。建议把source写入~/.bashrc避免每次开终端都要手动执行。第二个坑PCIe带宽相关参数。如果你的服务器是双路或多路CPUAtlas卡可能插入到的是距离CPU较远的PCIe插槽导致DMA传输延迟升高。这个不是软件问题但是会直接影响性能建议用lspci -v确认PCIe的Link Speed和Width。第三个坑容器内使用NVIDIA习惯了以为昇腾也能随便挂载。昇腾有专门的Ascend Docker Runtime直接用--device/dev/davinci0挂设备节点是不够的还需要挂载驱动目录、CANN目录以及设置环境变量。这部分建议参考昇腾官方容器部署文档不要自己猜。3. YOLO模型从PyTorch到omATC转换的前因后果3.1 为什么必须转成om格式PyTorch的模型是图结构和权重分离的GPU推理时由CUDA运行时解释执行。Atlas 300V Pro上的NPU不认识PyTorch的算子表达你需要把模型的计算图编译成昇腾芯片能直接调度的指令序列这个过程由ATCAscend Tensor Compiler完成。ATC会把PyTorch先导出成ONNX然后再将ONNX转换成om。转换过程中ATC会尝试将每个ONNX算子映射到昇腾的AI Core算子库。如果某个算子不支持有时它会自动fallback到CPU执行有时则直接报错。3.2 ONNX导出并检查YOLOv5为例python export.py --weights yolov5s.pt --include onnx --opset 11 --simplify这里有几个细节--opset最好指定为11昇腾对ONNX opset 11支持得最稳高版本算子集容易出歧义。导出后的onnx建议用onnx-simplifier清理一遍把冗余的Reshape、Transpose、Cast节点去掉。如果你使用YOLOv8导出ONNX时可能遇到torchvision::nms自定义算子无法转换的问题解决方法是导出时把NMS去掉后处理全部放到CPU侧完成。python export.py --weights yolov8n.pt --include onnx --opset 11然后打开onnx模型检查一下import onnx model onnx.load(yolov8n.onnx) onnx.checker.check_model(model) print(onnx.helper.printable_graph(model.graph))如果看到输出节点有三个分别是不同尺度的检测头且每个head的输出shape类似[1, 84, 8400]那说明模型已经具备转换条件。3.3 ATC转换命令与参数解释转换的基本命令如下atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_bs1 \ --soc_versionAscend310P3 \ --input_shapeimages:1,640,640,3 \ --loginfo \ --precision_modeallow_fp32_to_fp16几个关键参数--framework5表示ONNX格式。--soc_version必须和你的芯片型号对应Ascend310P3是Atlas 300V Pro/300I Pro的算力版本。用npu-smi info就能看到。--input_shape如果不指定ATC会从ONNX的输入信息中推断但YOLO模型输入可能是动态维度所以建议显式指定。--precision_mode非常重要。allow_fp32_to_fp16表示允许把FP32的算子降成FP16能明显提升推理速度但个别算子可能精度受影响。如果部署后检测结果比原模型差可以改为must_keep_origin_dtype或对特定算子设置精度模式。如果你的卡有多个AI Core且希望开启AI Core专用的算子缓存还需要考虑--fusion相关参数默认配置已经不错建议先用默认值。3.4 转换过程中最容易出现的报错算子不支持。例如某些YOLOv8版本的C2f模块会被导出成Split加多个卷积昇腾310P的算子库是比较全的但偶尔会碰到某个版本的BilinearSample不支持。这时候不要硬刚优先考虑升级CANN版本或者调整模型导出的opset。布局报错。ATC对输入的默认layout是NHWC如果你在导出的ONNX里定义的是NCHW会在转换时报Input/Output data format error。解决方案是在ATC命令里加--input_formatNC1HWC0或者更常见的--input_formatNCHW但底层还是会转成昇腾的五维格式你只需要保证图和输入匹配即可。shape不匹配。原始YOLO是动态shapeATC不喜欢动态转换时会卡在shape推理上。建议用--input_shape固定或者用--dynamic_dims配置多档尺寸例如640,640;1280,1280。但要注意动态shape会带来额外开销不是所有场景都划算。转换成功后会得到yolov5s_bs1.om可以通过msame工具快速验证输出是否正常msame --model yolov5s_bs1.om --input test_input.bin --output outdir但msame只能验证能否正确执行不能直接告诉你检测框对不对。所以我建议直接用ACL Python接口写一个小测试程序把推理结果画出来验证这比反复用工具检查更直观。4. 用Python ACL写一个端到端YOLO推理程序4.1 ACL接口的整体使用逻辑昇腾的ACLAscend Computing LanguageAPI和CUDA Runtime API有点像但风格更接近底层。使用AI核心的完整流程是初始化设备 - 创建Context - 创建Stream - 加载模型 - 准备输入输出内存 - 执行推理 - 处理结果 - 释放资源。这里给出一个可以直接跑的完整示例以YOLOv5格式输出为参考import acl import numpy as np import cv2 import sys # 初始化ACL ret acl.init() assert ret 0, facl.init failed, ret{ret} # 设置设备 device_id 0 ret acl.rt.set_device(device_id) assert ret 0, facl.rt.set_device failed, ret{ret} # 创建Context context, ret acl.rt.create_context(device_id) assert ret 0, facl.rt.create_context failed, ret{ret} # 创建Stream stream, ret acl.rt.create_stream() assert ret 0, facl.rt.create_stream failed, ret{ret} # 加载模型 model_path yolov5s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) assert ret 0, facl.mdl.load_from_file failed, ret{ret} # 获取模型输入输出描述 input_desc acl.mdl.create_input_desc(model_id) output_desc acl.mdl.create_output_desc(model_id) # 获取输入维度 input_num acl.mdl.get_num_inputs(model_id) output_num acl.mdl.get_num_outputs(model_id) print(finputs: {input_num}, outputs: {output_num}) # 准备输入输出内存 # 假设输入固定为 1 x 640 x 640 x 3 input_shape [1, 640, 640, 3] input_size 640 * 640 * 3 * 4 # float32 input_buffer, ret acl.rt.malloc(input_size, 2) assert ret 0 # 同理为每个输出分配内存 # 以YOLOv5为例输出shape是 [1, 25200, 85]需要根据实际情况调整 # 这里动态获取输出的size output_sizes [] output_buffers [] for i in range(output_num): dims acl.mdl.get_output_dims(model_id, i) # 计算byte大小NPU输出通常是float32 size 1 for d in dims[dims]: size * d size * 4 output_sizes.append(size) buf, ret acl.rt.malloc(size, 2) output_buffers.append(buf) # 绑定数据到描述对象 acl.mdl.set_input_data(input_desc, input_buffer) # 实际需要获取input buffer的设备地址 acl.mdl.set_output_data(output_desc, output_buffers) # 准备输入图像 img cv2.imread(test.jpg) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # letterbox resize到640x640保持比例 h, w img.shape[:2] scale min(640 / h, 640 / w) new_w int(w * scale) new_h int(h * scale) resized cv2.resize(img_rgb, (new_w, new_h)) canvas np.full((640, 640, 3), 114, dtypenp.float32) canvas[:new_h, :new_w] resized # 归一化 canvas canvas / 255.0 # 注意ACL输入的数据要按uint8还是float32根据模型转换时的配置决定这里默认是float32 input_data canvas.astype(np.float32).flatten() # 将数据拷贝到device内存 ret acl.rt.memcpy(input_buffer, input_size, input_data.tobytes(), input_size, acl.rt.MEMCPY_HOST_TO_DEVICE) assert ret 0 # 执行推理同步 ret acl.mdl.execute(model_id, input_desc, output_desc) assert ret 0, facl.mdl.execute failed, ret{ret} # 拷贝输出到host for i in range(output_num): output_host np.zeros(output_sizes[i] // 4, dtypenp.float32) ret acl.rt.memcpy(output_host.tobytes(), output_sizes[i], output_buffers[i], output_sizes[i], acl.rt.MEMCPY_DEVICE_TO_HOST) assert ret 0 # 此时output_host 就是模型输出shape需要根据dims reshape4.2 需要注意的几个ACL细节上面这段代码为了保持可读性省略了一些细节。实际开发中有几个点必须处理好输入数据的内存地址绑定。ACL的acl.mdl.set_input_data需要传入的是一个描述模型输入设备内存地址的结构体而不是直接传Python的bytes。正确方式是用acl.rt.get_device_buffer获取到地址对象再传给set_input_data。我这里的写法是示意完整代码请参考昇腾社区提供的pyacl样例。输入的数据类型。图像数据是按uint8传还是按float32传取决于你ATC转换时指定的输入数据类型。如果在ATC里加入了AIPP配置且input_format为YUV420SP_U8或RGB888_U8那输入就是U8格式归一化、resize都可以交给AIPP处理。如果你不配置AIPP那就需要在host侧自己做完resize、归一化、HWC转CHW这些操作并且以float32传入。输出地址的分配时机。建议在模型加载后通过acl.mdl.get_output_dims动态获取维度然后在设备侧malloc。有些模型输出不止一个YOLO一般有三个检测头三个输出都要单独分配。4.3 YOLO输出的后处理YOLOv5的原始输出shape是[1, 25200, 85]其中25200包含640尺寸下三个尺度的anchor数总和85是80类加4个框坐标加1个置信度。拿到NPU输出的float32数组后需要做置信度过滤和NMSimport numpy as np from scipy.optimize import linear_sum_assignment # 假设 output_host 是一个 [1, 25200, 85] 的数组 preds output_host.reshape(1, 25200, 85)[0] # 过滤低置信度 conf preds[:, 4:5] * preds[:, 5:].max(axis1, keepdimsTrue) mask conf 0.25 preds_filtered preds[mask.squeeze()] if len(preds_filtered) 0: print(no detections) # 将中心点坐标转换为左上角右下角格式 box_xy preds_filtered[:, 0:2] box_wh preds_filtered[:, 2:4] box_xy1 box_xy - box_wh / 2 box_xy2 box_xy box_wh / 2 boxes np.concatenate([box_xy1, box_xy2], axis1) # 做NMS这里可以直接使用opencv的dnn.NMSBoxes boxes_list boxes.tolist() scores_list (preds_filtered[:, 4] * preds_filtered[:, 5:].max(axis1)).tolist() nms_indices cv2.dnn.NMSBoxes(boxes_list, scores_list, score_threshold0.25, nms_threshold0.45) # 将检测框坐标映射回原图 # 由于之前做了letterbox需要还原 # ...这里有个容易疏忽的点如果在host侧做了letterbox resize检测框坐标是相对于640x640输入图的而原图尺寸可能是1920x1080所以需要按缩放比例和pad值反算回原图坐标。具体公式x_min_orig (x_min - pad_x) / scale y_min_orig (y_min - pad_y) / scale 其中 scale min(640 / h, 640 / w) pad_x (640 - new_w) / 2 pad_y (640 - new_h) / 2这一步如果漏了你会在调试时看到检测框偏移甚至框在完全错误的位置。5. 实测性能上不去才暴露的问题调优与排错经验5.1 单卡性能大概在什么水平先说一个我自己的实测数据Atlas 300V Pro 24GB运行YOLOv5s640x640FP16单batch推理延迟大约是3-5毫秒换算成单路视频是妥妥的200FPS以上如果跑batch_size4总吞吐还能再提升。但实际业务中单卡往往要同时处理多路视频流所以不能只看单次延迟要看端到端的吞吐和时延稳定性。如果把整个流程串起来——拉流解码、缩放、归一化、推理、NMS、编码输出——瓶颈往往不在NPU推理而在CPU侧的图像预处理和NMS。这也是为什么很多人发现NPU占用率不到50%但业务整体帧率就是上不去。5.2 多batch与多stream的选择Atlas 300V Pro支持多路stream并发执行。在ACL中可以创建多个stream每个stream里执行一个独立的推理任务。这里有两种典型方案方案A提升batch_size。把多路视频的帧打包成一个batch推理适合帧率要求一致、各视频时序同步的场景。比如同时处理4路1080p视频每路25FPS可以每40ms取4帧组成一个batch_size4的输入平均每帧推理延迟相比单batch只有很少增加等效单路时延变化不大。但需要控制帧对齐否则个别帧会等待最慢的那一路。方案B多线程多stream。每个视频流一个线程每个线程有自己的stream其他线程的推理互不干扰。适合各视频流帧率不均、到达时间随机的场景。ACL的异步执行acl.mdl.execute_async配合事件acl.rt.create_event可以实现流水线并行CPU在等待NPU推理的同时已经可以处理下一张图的预处理。两种方案我都实测过。如果你的视频路数固定、帧率固定方案A的整体吞吐更高如果路数动态变化方案B更灵活稳健。实际业务中我倾向于方案B而且用流水线的方式把预处理和推理错开。5.3 异步执行与流水线的具体实现思路使用ACL异步接口有一个基本模型把整个处理过程拆成“取帧 - 预处理 - 数据拷贝H2D - 推理 - 数据拷贝D2H - 后处理”。CPU执行预处理和后处理的时间和NPU执行推理的时间是重叠的。代码如下示意# 创建两个stream交替使用 stream1, ret acl.rt.create_stream() stream2, ret acl.rt.create_stream() # frame N 预处理 preprocess(frame_n, input_buf_n) # 在stream1上启动推理异步 acl.mdl.execute_async(model_id, input_desc_n, output_desc_n, stream1) # 同时继续处理frame N1 preprocess(frame_n1, input_buf_n1) # 在stream2上启动推理 acl.mdl.execute_async(model_id, input_desc_n1, output_desc_n1, stream2) # 在合适时机同步并取得输出 acl.rt.synchronize_stream(stream1) postprocess(output_buf_n)实际生产中可以维护一个可用的stream队列和输入buffer池避免反复创建释放减少资源竞争。5.4 AIPP把图像预处理丢给NPU很重要的调优手段是使用AIPPAscend Image Pre-Processing。通过ATC转换时用--insert_op_conf参数指定一个AIPP配置文件可以把resize、crop、归一化、颜色转换RGB转BGR这些工作全部放到NPU侧硬件执行这样CPU侧的预处理时间几乎降到零。AIPP配置文件示例{ aipp_op: { aipp_mode: static, input_format: RGB888_U8, src_image_size_w: 640, src_image_size_h: 640, mean: [0, 0, 0], min: [0, 0, 0], crop: false, resize: { resize_w: 640, resize_h: 640 } } }然后在ATC命令里加上atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s_aipp \ --soc_versionAscend310P3 \ --input_shapeimages:1,640,640,3 \ --insert_op_confaipp.cfg用AIPP之后host侧只需要把原始图像数据可以是JPG解码后的BGR或者摄像头采集的YUV数据填充到输入buffer里剩下的resize和归一化都交给NPU。这里有一个限制AIPP的输入格式如果是RGB888_U8或BGR888_U8那你仍然需要先把JPG解码成像素数据如果是YUV420SP_U8可以直接把视频解码器输出的YUV帧喂进去连颜色转换都省了。5.5 一个容易被忽视的排错场景模型输出NaN实际部署中我遇到过模型在NPU上输出全部是NaN的情况。排查思路是这样的首先怀疑精度模式把allow_fp32_to_fp16改成must_keep_origin_dtype重新转换问题依旧。然后检查输入归一化确认不是0除问题。最后发现是输入buffer的大小分配错误——ATC的模型声明输入为uint8但我在host侧分配的buffer大小错误地按float32算导致设备侧读了超出实际数据范围的内存。修改输入数据类型和buffer大小后立刻正常。这个案例告诉我们遇到异常输出先排查输入侧的数据格式是否和模型声明的输入类型一致再做算法层面的怀疑。很多时候不是模型坏了是数据通道出了问题。6. 从能跑到跑好日常部署的几个实用建议写到最后分享几个我在实际项目中总结的细节。第一把om模型和推理引擎解耦。如果你需要频繁更新模型建议在代码里把模型加载做一个独立模块支持热加载。Atlas卡支持多模型加载可以同时加载新旧两个模型切流时用新模型推理稳定后再释放旧模型能实现无缝升级。第二合理利用Warmup。NPU的AI Core在第一次执行模型时会有初始化和算子调度开销建议服务启动后先空跑几次推理把预热数据扔掉再开始对外提供服务。第三做好日志和监控。昇腾提供了npu-smi info可以查看实时显存占用、温度、功耗建议周期性记录这些数据。我习惯在每次模型更新后记录一组性能基线单batch延迟、batch4吞吐、P99时延这样后续任何改动都能快速定位性能回退。第四容器化部署时把环境变量和驱动挂载做扎实。不少线上故障是容器内找不到设备或者CANN路径不对导致的。建议把CANN安装在宿主机的固定路径容器内通过环境变量和挂载保持一致不要每个容器各装一套CANN那是灾难。Atlas 300V Pro这块卡对我来说最值得推荐的地方是它的性价比和硬解码能力尤其是视频解析场景一块卡能顶一个中高配GPU服务器的工作量。但它的软件生态确实需要耐心学习CANN的版本管理、ATC的算子差异、ACL接口的各种对象生命周期都需要花时间适应。用顺了之后你会发现它其实和其他加速平台没什么本质区别都是“模型转换 - 内存管理 - 异步执行 - 结果后处理”这条老路子只是换了一套API名字而已。

相关推荐

FlexGen 在 Google Cloud 上的完整环境搭建指南:单 GPU 高吞吐 LLM 推理的 GCP 部署实战
FlexGen 在 Google Cloud 上的完整环境搭建指南:单 GPU 高吞吐 LLM 推理的 GCP 部署实战

推理引擎大模型 【免费下载链接】FlexGen Running large language models on a single GPU for throughput-oriented scenarios. 项目地址: https://gitcode.com/gh_mirrors/fl/FlexGen 点击查看 免费下载 本文是一份面向 Google Cloud Platform(GCP&am… · 2026/9/25 6:03:43

金融场景下智能协作系统架构:插件化与托管代理的工程实践
金融场景下智能协作系统架构:插件化与托管代理的工程实践

1. 金融场景下的智能协作系统拆解1.1 这个项目到底在解决什么问题金融行业的技术团队有个很尴尬的处境:业务侧对响应速度的要求越来越高,合规侧对数据流转的管控越来越严,而工程侧能用的工具链却往往是通用型的,放到金融场景里到处… · 2026/9/25 6:03:37

金融场景下基于托管代理与插件的智能协作系统架构设计与实操
金融场景下基于托管代理与插件的智能协作系统架构设计与实操

1. 金融场景下的智能协作系统拆解金融行业对技术方案的要求向来苛刻,这不是没有原因的。一笔交易、一份报表、一次风控决策,背后牵扯的是真金白银和合规红线。我接触过不少金融科技团队,他们最常挂在嘴边的一句话是:能跑通不代表能… · 2026/9/25 6:03:37

Marchand巴伦设计核心:奇偶模理论与毫米波PCB实现
Marchand巴伦设计核心:奇偶模理论与毫米波PCB实现

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

使用 AutoHotkey 扩展 ElectronBot:八种 SDK 玩法示例与 DllCall 驱动原理详解
使用 AutoHotkey 扩展 ElectronBot:八种 SDK 玩法示例与 DllCall 驱动原理详解

智能硬件机器人嵌入式硬件开发 【免费下载链接】ElectronBot 项目地址: https://gitcode.com/gh_mirrors/el/ElectronBot 点击查看 免费下载 AutoHotkey(AHK)是一种可以用记事本编辑、保存即运行的脚本语言,本仓库的 3.Software/… · 2026/9/25 7:10:06

react-vis 雷达图(RadarChart)完全指南:domains 配置、样式定制与交互实战
react-vis 雷达图(RadarChart)完全指南:domains 配置、样式定制与交互实战

数据可视化图表库前端 【免费下载链接】react-vis Data Visualization Components 项目地址: https://gitcode.com/gh_mirrors/re/react-vis 点击查看 免费下载 说明:本文基于当前仓库中 react-vis 的官方文档 docs/radar-chart.md 展开,并结… · 2026/9/25 7:10:00

Windows Universal Samples 之 PresenceSensor:HumanPresenceSensor API 完整实战指南
Windows Universal Samples 之 PresenceSensor:HumanPresenceSensor API 完整实战指南

示例工程 【免费下载链接】Windows-universal-samples API samples for the Universal Windows Platform. 项目地址: https://gitcode.com/gh_mirrors/wi/Windows-universal-samples 点击查看 免费下载 本指南以 Samples/PresenceSensor 示例为蓝本,系统… · 2026/9/25 7:10:00

大模型Agent技能库:从Prompt到可复用技能包的工程实践
大模型Agent技能库:从Prompt到可复用技能包的工程实践

最近好几个团队朋友都在聊同一个话题:大模型 Agent 跑起来不难,三行代码就能让模型调工具,可真要多步任务稳定执行、跨项目复用,几乎每个人都在重复造轮子。我自己的做法是把这类可复用的能力沉淀成一套结构化的技能包&#xff0c… · 2026/9/25 7:09:54

前端工程师必备:用浏览器开发者工具精准获取HTML/CSS/JS源码
前端工程师必备:用浏览器开发者工具精准获取HTML/CSS/JS源码

1. 这不是“扒”,是前端工程师的日常基本功很多人一看到“获取网页源码”“扒JS CSS HTML”这几个词,第一反应是带点灰色色彩的操作——好像得用什么神秘工具、绕过什么限制、偷偷摸摸搞点东西。其实完全不是。我干这行十多年,每天打开浏览器… · 2026/9/25 7:09:54

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

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

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

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

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

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

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码