上周有个朋友问我Atlas 300V 24G到底是不是运算加速卡这个问题听着简单真要解释清楚得从华为Atlas整个产品线说起。简单说它是一块AI推理加速卡不是传统意义上的“运算加速卡”更不是GPU通用计算卡。它最大的价值在于把训练好的模型比如YOLO目标检测模型高效部署到边缘或者数据中心推理场景里用很低的功耗实现很高的吞吐。这篇文章不聊虚的我会从Atlas的产品线定位、部署环境搭建、YOLO模型转换、推理代码实现再到多路视频场景的性能调优完整过一遍我实际踩坑后总结出来的经验。不管是刚接触昇腾平台的新手还是已经在用CANN做推理但想深挖性能的工程师都应该能从里面找到点有用的东西。1. Atlas到底是个啥先搞清楚它的产品线定位1.1 300V 24G是不是运算加速卡一张表说清定位网上关于Atlas的型号特别乱什么300I、300V、310P、800T很多人一上来就懵。我先把最容易混淆的两个型号给大家理一遍。Atlas 300I Duo和Atlas 300V Pro都基于昇腾310P芯片但面向的场景完全不同型号芯片算力INT8显存形态主要用途Atlas 300I Duo昇腾310P140 TOPS24GB半高半长PCIe卡视频分析、目标检测、图像分类Atlas 300V Pro昇腾310P140 TOPS24GB半高半长PCIe卡视频分析、目标检测、图像分类Atlas 300T昇腾910B376 TFLOPSFP1664GB全高全长PCIe卡大模型训练、高性能推理Atlas 800T训练服务器昇腾910B x8多卡互联多卡共享4U训练服务器大规模分布式训练所以“Atlas 300V 24G是不是运算加速卡”这个问题的答案是它严格来说是AI推理加速卡核心任务是跑神经网络推理而不是通用运算。它不是用来跑CUDA程序的也不适合做科学计算或者高性能计算集群如果你要拿它做通用浮点计算那思路就偏了。1.2 为什么选Atlas而不是GPU来跑YOLO很多人会问我有NVIDIA的卡为什么还要折腾Atlas这个问题我在项目里正面回答过很多次最核心的理由就三个第一是成本。在推理场景里一张Atlas 300V 24G的卡能同时处理几十路1080P视频流的YOLOv5推理在相同路数下整机成本可能比用T4还低。当然平台不同价格波动大但整体上昇腾方案在推理场景确实有价格优势。第二是功耗。Atlas 300V单卡功耗大约72W左右而一张T4的TDP是70W看起来差不多但Atlas的算力密度更高跑同样的负载需要的卡更少机房的电力开销能省下一大截。第三是国产化替代需求。很多项目招标明确要求使用国产AI芯片Atlas几乎是绕不开的选择。这一点在实际交付的时候价值巨大。补充一点不是所有场景都适合Atlas。如果你的团队完全不会昇腾生态也没有任何时间学习那直接用NVIDIA可能短期内效率更高。但如果你要大规模落地推理、重复部署那Atlas的性价比优势会非常明显。1.3 选型前置条件什么场景才适合用Atlas这么多年下来我总结出一个规律只要你的核心负载是卷积网络推理Atlas就值得认真评估。特别是下面这几类场景视频结构化人脸识别、车牌识别、行为分析这类多路视频流处理Atlas的多路解码AI推理流水线做得相当成熟。工业质检产线上几百上千个检测点位每个点位跑一个YOLO模型Atlas可以作为边缘盒子来部署。智慧零售、智慧园区客流统计、姿态识别等轻量级推理负载Atlas的性价比很高。反过来如果业务里大量涉及Transformer大模型全精度推理、自定义算子非常多或者重度依赖PyTorch生态的库那就要慎重。昇腾框架虽然现在兼容性越来越好但并不是所有算子都原生支持迁移成本不能忽视。2. 部署前最重要的一步驱动、固件和CANN环境2.1 拿到一张Atlas卡装环境前先确认这些事新手最容易犯的错误就是拿到卡就急着装驱动结果各种报错最后发现是固件和驱动版本不匹配。我先给一个标准流程。第一步确认你拿到的卡具体是哪个型号。从板卡背面标签上可以看到具体的型号编码比如“Atlas 300V Pro 24G”。这一步非常重要因为不同型号对应不同的固件版本。第二步确认你当前的操作系统。昇腾官方目前对Ubuntu 20.04/22.04和openEuler的支持最完善CentOS 7.6/7.9也在支持范围内。我实际测试下来Ubuntu 20.04最省心坑最少。第三步准备好全套驱动、固件和CANN安装包。这里有个协调点CANN Toolkit、Driver、Firmware三者之间是有版本配套关系的。官方每发布一个新版本都会出一个“配套表”下载时直接看配套表就行。2.2 版本兼容性是最大的坑我把昇腾平台的版本依赖关系列一下方便理解Driver驱动向上支持固件向下对接CANN。装错驱动通常是起不来卡。Firmware固件管理芯片底层硬件版本不对你执行npu-smi info会显示不出卡。CANN Toolkit昇腾的软件栈类似CUDA Toolkit。包含acl、算子库、图编译工具链等。CANN Kernels算子包需要在安装完Toolkit之后再装否则跑模型时会报算子不匹配的错误。MindX Toolkit包含MindX SDK等上层封装组件用于做多路视频流推理、业务编排。我踩过的坑是用最新版CANN Toolkit 7.0配了一个较老的Driver结果一执行模型推理就报“runtime error, please send info”这种完全摸不着头脑的错误。排查了半天最后在昇腾社区看到有人提到版本配对表一查果然不对。所以在这里郑重提醒安装前第一件事去昇腾社区查最新配套表把驱动、固件、Toolkit版本全部对齐再动手。2.3 实测的环境安装流程以Ubuntu 20.04 Atlas 300V Pro为例我完整跑通的过程如下# 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 python3-dev python3-pip # 2. 安装Driver驱动包一般是 .run 格式 # 下载对应版本的 Ascend-hdk-310P-npu-driver_xxx_linux-aarch64.run chmod x Ascend-hdk-310P-npu-driver_xxx_linux-aarch64.run sudo ./Ascend-hdk-310P-npu-driver_xxx_linux-aarch64.run --full # 3. 安装Firmware固件包 sudo ./Ascend-hdk-310P-npu-firmware_xxx.run --full # 4. 重启系统 sudo reboot # 5. 检查NPU状态 npu-smi info执行完npu-smi info如果能看到卡信息比如“310P”芯片、24GB显存、温度功率正常说明驱动和固件这层已经通了。如果npu-smi info看不到卡优先排查两件事一是固件是否安装成功二是卡有没有正确插在PCIe槽位上可以用lspci | grep -i ascend看设备是否被识别。接着安装CANN# 安装CANN Toolkit比如 Ascend-cann-toolkit_7.0.0_linux-aarch64.run chmod x Ascend-cann-toolkit_7.0.0_linux-aarch64.run sudo ./Ascend-cann-toolkit_7.0.0_linux-aarch64.run --install # 安装CANN Kernels算子包 chmod x Ascend-cann-kernels-910b_7.0.0_linux.run sudo ./Ascend-cann-kernels-910b_7.0.0_linux.run --install # 设置环境变量 source /usr/local/Ascend/ascend-toolkit/set_env.sh到这里环境就算搭好了。我建议把这个set_env.sh追加到~/.bashrc里省得每次开终端都要source一次。3. YOLO模型落地从pt权重到OM离线模型3.1 为什么要转换成OM格式CANN推理不直接跑PyTorch的.pt文件也不直接跑ONNX它需要把模型文件转换成昇腾平台专用的OM格式Offline Model。你可以把OM理解为昇腾平台的“可执行程序”里面已经包含了图优化、算子调度、内存分配等编译产物推理时不需要再动态构图性能更高、启动更快。整个链路是这样的PyTorch权重(.pt) - ONNX(.onnx) - OM(.om) - 昇腾运行3.2 用ATC完成ONNX到OM的转换ATCAscend Tensor Compiler是昇腾的模型转换工具。以YOLOv5s为例先要把.pt转成ONNX。在PyTorch环境下执行import torch model torch.load(yolov5s.pt, map_locationcpu)[model].float() model.eval() # 设置输入尺寸YOLOv5默认是640x640 dummy_input torch.randn(1, 3, 640, 640) # dynamic_axes允许动态batch便于后期多路视频处理时自己控制batch torch.onnx.export( model, dummy_input, yolov5s.onnx, opset_version11, input_names[images], output_names[output], dynamic_axes{images: {0: batch}, output: {0: batch}} )注意这里我导出的输出是原始推理结果包含box坐标、置信度、类别概率也就是没有做NMS的输出。很多人会把后处理也塞进导出过程在昇腾上建议不要把NMS放进模型里原因后面讲。然后切换远程到Atlas环境执行ATC转换source /usr/local/Ascend/ascend-toolkit/set_env.sh # 设置输入shape atc --modelyolov5s.onnx \ --framework5 \ --outputyolov5s \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --input_formatNCHW \ --output_typeFP16 \ --insert_op_confaipp.cfg这里有几个参数需要特别说明--framework5表示ONNX模型框架。--soc_version一定要和实际芯片对应我是310P芯片所以填Ascend310P3如果你的卡是310P的某个具体版本用npu-smi info查看芯片型号后到CANN文档里找到对应的SoC名称。--output_typeFP16可以把模型权重和中间计算结果用FP16推理Atlas的INT8/FP16算力远高于FP32推理性能翻倍这里值得加。aipp.cfg是AIPPAI Preprocessing配置文件用来把图片缩放、归一化、RGB转换这些预处理步骤固化到模型转换阶段推理时省去CPU预处理的开销。一个典型的aipp.cfg长这样aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 csc_switch: true rbuv_swap_switch: false min_chn_0: 0 min_chn_1: 0 min_chn_2: 0 var_reci_chn_0: 0.003921569 var_reci_chn_1: 0.003921569 var_reci_chn_2: 0.003921569 }这样转换出来的yolov5s.om就已经把“resize到640归一化”内置了。推理时输入原始图像数据即可CPU侧省了一次完整的图像预处理流程在跑多路视频时优势非常大。如果你不想把所有预处理都放进AIPP比如想灵活控制缩放比例也可以在推理代码里自己用OpenCV做预处理OM就配置成不做AIPP的模式。两种我都试过建议能放AIPP就放AIPP省心。3.3 demo推理用pyACL让模型跑起来模型转换好了接下来是写推理代码。昇腾提供pyACLPython接口的AscendCL和MindX SDK两种方式。对新手我直接推荐pyACLAPI比较底层但可控性强排错也直观。一个最小可运行的YOLOv5推理代码如下import acl import numpy as np import cv2 # 初始化 ret acl.init() ret acl.rt.set_device(0) # 创建context context, ret acl.rt.create_context(0) stream, ret acl.rt.create_stream() # 加载om模型 model_path byolov5s.om model_id, ret acl.mdl.load_from_file(model_path) # 获取模型输入输出信息 input_desc acl.mdl.create_input_desc(model_id) output_desc acl.mdl.create_output_desc(model_id) input_size acl.mdl.get_input_size_by_index(model_id, 0) output_size acl.mdl.get_output_size_by_index(model_id, 0) # 分配device内存 input_data np.zeros((1, 3, 640, 640), dtypenp.uint8) img cv2.imread(test.jpg) img cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img cv2.resize(img, (640, 640)) input_data[0] img.transpose(2, 0, 1) data_ptr acl.util.np_to_ptr(input_data) input_buffer, ret acl.rt.malloc(input_size, 2) acl.rt.memcpy(input_buffer, input_size, data_ptr, input_size, 2) output_buffer, ret acl.rt.malloc(output_size, 2) # 推理 ret acl.mdl.execute(model_id, input_buffer, input_size, output_buffer, output_size) # 输出结果拷贝回host output_np acl.util.ptr_to_np(output_buffer, (output_size,), np.uint8) output_ptr acl.util.np_to_ptr(output_np) output_result np.zeros(output_size, dtypenp.uint8) acl.rt.memcpy(output_result.__array_interface__[data][0], output_size, output_ptr, output_size, 2) # 解析输出结果shape一般是 [batch, 25200, 85] 之类 # 后面接NMS和画框即可这段代码省略了输出解析和NMS的完整实现主要是展示pyACL的基本调用链路。实际项目中我不会在Python里逐像素解析输出而是把推理主体写成C动态库Python只做业务层调用这是工程后期要做的事情。关于NMS为什么我说不要把NMS放进模型里因为在昇腾平台上自定义算子如果写成动态shape的NMS很容易触发不支持的分支造成模型转换失败。更稳妥的做法是让模型输出原始的预测张量在Host端用OpenCV、NumPy或者MindX SDK自带的后处理模块完成NMS。实测这样做的性能损失很小调试还方便。4. 工程化与性能调优把FPS榨出来4.1 多路视频流场景的架构设计模型能跑只是第一步真实项目里更复杂的是架构设计。我之前做过一个智慧园区项目要求同时处理32路1080P摄像头流每路都跑YOLOv5s目标检测。最初实现是每路视频一个线程每个线程独立推理结果CPU和NPU都在空转吞吐量根本不达标。后来我改成生产者-消费者流水线架构主线程负责从摄像头拉流拿到RTSP帧后只做解码解码好的帧放到环形缓冲区。推理线程从缓冲区批量取帧凑成batch为4或8的输入一次性丢给NPU。后处理线程专门做NMS、坐标映射和结果上报。这样改造之后32路视频用一张Atlas 300V Pro就能稳定跑到30路实时CPU占用率还降了不少。经验就一句话不要每路视频单独推理一定要batch化。一张卡的分时复用效率远不如batch一次跑。4.2 模型量化和算子优化Atlas平台对INT8的支持特别好同一个YOLOv5s模型FP16推理和INT8推理的吞吐量能差到2-3倍。我建议在生产环境尽可能跑INT8。昇腾上做量化的工具叫AMCTAscend Model Compression Toolkit它支持训练后量化PTQ和量化感知训练QAT。PTQ的流程很简单准备几百张有代表性的测试图喂给AMCT做校准就能生成量化模型。实际操作中要注意校准集要覆盖各种光照、天气、场景不然量化后特定场景的精度会掉得很厉害。除量化外算子融合也是性能提升的大头。昇腾CANN在编译OM模型时会自动做算子融合比如把ConvBNReLU融合成一个算子。你要做的最重要的事是保证ONNX模型本身是经过简化的不要带多余节点。可以先用torch.onnx.export时设置do_constant_foldingTrue再看ONNX结构是否干净必要时用手动重构的方式去掉一些无效节点。4.3 一次真实调优案例从36ms到11ms这个案例我记得很清楚是一个工业质检项目客户要求单个缺陷检测延迟低于15ms。初版方案跑YOLOv5s边缘部署单帧推理时间36ms严重超标。我做了三件事把延迟压到了11ms第一把输入分辨率从1280降到800。经过和算法团队一起评估发现原图1280分辨率下模型AP只比800高0.3个点但推理时间多了快20ms。用800x800分辨率后延迟直接从36ms降到24ms。第二开启AIPP并合并预处理到模型内部。原本预处理在CPU上做缩放、归一化、数据拷贝耗时约6ms。挪到AIPP后CPU和NPU并行处理这部分时间几乎归零延迟降到15ms。第三开启动态batch装配。原来每次推理都是batch1一次性只检测一张图。改为等同一批次的图凑满8张后再一起推理NPU利用率大幅提升。虽然单帧延迟不是等比例下降但整体吞吐提升明显最终稳定在11ms以内。调优不是拍脑袋改参数每一步都要用profiling工具确认瓶颈在哪。昇腾上可以使用msprof工具采集NPU的算子耗时、AICore利用率、内存搬移耗时。用数据说话不要凭感觉优化。5. 踩坑实录这些问题排查最花时间5.1 常见问题速查表建议直接收藏下面这几个问题是我在实际项目里遇到过的也是社区里被问得最多的。整理成表格方便排查现象常见原因解决办法npu-smi info看不到卡固件未装好、PCIe识别异常重装Firmware查看lspci是否识别设备模型加载失败报module not foundCANN Kernel包未安装安装对应版本的Ascend-cann-kernels包ATC转换失败提示算不支持版本不匹配或算子图优化失败查CANN版本适配算子列表尝试更换opset版本推理结果全为0输入数据未正确拷贝到Device检查acl.rt.memcpy方向参数确认数据已经放到Device端多线程调用pyACL崩溃context/stream未分离确保每个线程拥有独立的aclrtContext编译C代码找不到头文件环境变量未设置source set_env.sh确认头文件路径正确模型精度大幅下降量化校准集太单一扩展校准集覆盖真实推理场景显存占用异常增长推理循环里未释放buffer推理后调用acl.rt.free释放Device内存5.2 几个值得单独说的坑第一个是多线程推理时的Context隔离问题。pyACL有个隐蔽的坑默认Context和线程绑定是弱关联的你如果在一个线程里创建了Context又在另一个线程里调用推理程序可能直接崩掉。解决办法是在每个线程创建自己独立的Context并在线程函数入口acl.rt.set_context。第二个是共享内存和Device内存拷贝的性能问题。使用acl.rt.memcpy从Host到Device拷贝数据时如果用同步拷贝整个线程会等待数据搬移完成再做推理时间全花在IO上。建议改用acl.rt.memcpy_async把数据搬移和上一帧的推理重叠起来。配合Stream机制能把CPU等待时间完全隐藏掉。第三个是CANN版本升级后老模型跑不了。千万不要觉得OM模型是静态的就一劳永逸。CANN大版本升级后老的OM模型可能因为编译器的算子实现变了而无法加载。升级后重新执行ATC转换并重新测试精度和性能。第四个值得说实时流处理里的CPU解码瓶颈。很多人只盯着NPU的算力忽略了RTSP拉流和H264解码的CPU占用。我见过一个项目NPU利用率才50%CPU已经100%跑满了就是因为用的OpenCV的VideoCapture做解码。建议用昇腾的DVPP硬件解码模块或者FFmpeg的硬件解码把解码压力从CPU转移到专用硬件上。5.3 如何从社区和工具里获得帮助昇腾的问题排查跟NVIDIA生态不太一样。NVIDIA有大量的第三方博客和StackOverflow问答昇腾相对少一些。我一般按这个次序查先看Ascend/cann-community的GitHub仓库很多已知问题都会标出来。再上昇腾社区论坛搜索报错关键字一般都能找到类似案例。启动msprof工具把profiling数据导出来结合mindstudio --debug看算子调度定位到具体算子。如果上面都没解决就要学会分析报错日志了。CANN的日志默认在~/ascend/log目录下里面有plog和device日志。看到“ERROR”开头的日志别慌往上翻几行看是哪个模块报出来的基本能定位到驱动、CANN还是模型转换的问题。写在最后的个人体会Around Atlas这套平台我用下来最大的感受是它确实不是“装上就能跑”级别的生态前期要啃文档、要磨环境、要接受各种版本之间的兼容性问题。但一旦熟悉了CANN的开发思路把模型转换、AIPP、多线程推理、流水线编排这几套玩熟了它的稳定性和吞吐量在推理场景里是真的很能打。有一点我要特别强调不要用GPU的开发习惯去套Atlas。在NVIDIA上很多容错的空间在昇腾上是不存在的比如动态shape的支持比如自定义算子门槛这些决定了你前期必须认真设计模型和推理链路而不是靠“先跑起来再说”的方式慢慢调。我个人在实际操作中还有一个心得多路视频场景里把解码、预处理、推理、后处理全部做成独立的流水线阶段再通过队列解耦是整个项目能稳定交付的关键。Node级别的优化永远慢于架构级别的优化这个原则在Atlas上比在GPU上更明显。如果你正在做类似的目标检测推理项目我的建议是从小处入手用一张Atlas卡先把单模型跑通、跑稳再一点点加复杂度。环境准备好、版本配对好、流程理解透之后Atlas真能给你带来不少惊喜。
企业数字化 ERP 产品动态
相关推荐
游戏自动化脚本实战:图像识别与输入模拟3步框架 1. 从“解放双手”说起:自动化脚本到底在解决什么问题“炉石传说脚本”这个词,在玩家圈子里一直是个绕不开的话题。很多人第一次听到它,脑子里浮现的画面是:电脑自己开游戏、自己出牌、自己领奖励,人该干嘛干嘛。这个理… · 2026/9/25 7:26:18
Atlas 300V 24G推理卡实战:从环境配置到YOLO部署全记录 从"它到底是不是运算加速卡"说起:Atlas 300V 24G实战部署YOLO的完整记录最近总有人在群里问同一个问题:"Atlas 300V 24G是运算加速卡吗?" 还有人拿着它当训练卡用,烧了几天才发现跑不动反向传播,回… · 2026/9/25 7:26:18
51单片机16×16点阵流动字幕实现原理与硬核调优 /* 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:26:18
Atlas 300V 24G部署YOLOv5指南:从ONNX到OM的昇腾推理 最近在技术群里被问到最多的两个问题,一个是“Atlas 300V 24G是运算加速卡吗”,另一个是“网上说的atlas部署YOLO到底怎么搞”。这两个问题其实指向同一件事:昇腾生态的Atlas系列AI推理设备越来越普及,但大量开发者在第一步就被卡… · 2026/9/25 7:55:53
使用 Flowbite 与 Tailwind CSS 构建网站页脚(Footer)组件的完整指南 UI组件前端 【免费下载链接】flowbite Open-source UI component library and front-end development framework based on Tailwind CSS 项目地址: https://gitcode.com/gh_mirrors/fl/flowbite 点击查看 免费下载 页脚(footer)位于每个页面… · 2026/9/25 7:55:53
Atlas 300V部署YOLOv5实战:模型转换与多路视频推理优化 开工之前先把话放到前面:如果你和我一样,第一次听到“Atlas 300V 24G”的时候脑子里冒出来的问题是“这东西到底是不是运算加速卡”,那这篇文章就是为你准备的。是,但不是我们熟悉的“显卡”那种加速卡。它是昇腾生态里专门做推理… · 2026/9/25 7:55:53
AI视频生成镜头语言六维拆解:从Prompt到导演的实操指南 1. 为什么光靠Prompt写不出好镜头1.1 从“抽卡”到“导演”的认知转变很多人用AI视频生成工具,习惯把全部精力砸在Prompt的遣词造句上,反复堆砌“4K、超写实、电影感、丁达尔效应”这类形容词,结果生成出来的画面要么像PPT翻页,要… · 2026/9/25 7:55:47
多智能体协同工程化落地:从单兵作战到可管理、可复现的研发流水线 1. 从单兵作战到团队协作:多智能体协同到底在解决什么问题如果你最近一年在关注 AI 研发领域的动态,大概率会频繁刷到“多智能体协同”这个词。但很多人第一次听到它的时候,脑子里浮现的画面可能是几个聊天窗口同时开着、互相转发消息——这其… · 2026/9/25 7:55:47
IronClaw 中的 QA Review 技能实战:从测试覆盖率分析到回归风险防控的代码评审方法论 人工智能AI 应用交互助手AI Agent 【免费下载链接】ironclaw IronClaw is an Agent OS focused on privacy, security and extensibility 项目地址: https://gitcode.com/gh_mirrors/iro/ironclaw 点击查看 免费下载 在 IronClaw(一个以隐私、安全与可扩… · 2026/9/25 7:55:41
创维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 /* 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