我们平时说的AI部署一提推理加速卡大多数人脑子里先蹦出来的是NVIDIA的Tesla T4、A10这类。但如果你在信创机房、运营商项目或者一些国产化整机里待过一定绕不开另一个名字——昇腾Atlas。手头这张Atlas 300V 24G我已经用了不短时间YOLOv5、YOLOv8以及一些检测模型都在上面跑过。先说结论这是一张不折不扣的AI推理加速卡不是显卡更不是训练卡它的定位就是干“模型部署上线”这摊活的。这篇文章想写给三类人一是刚拿到Atlas卡不知道怎么下手的新手二是在x86服务器上被CANN、MindX SDK各种报错折磨的部署工程师三是想在Atlas 300V上跑YOLO系列但还没摸清模型转换和推理链路的人。我会从硬件认知、环境搭建、模型转换、推理部署到性能调优完整走一遍尽量把那些文档里不写、社区里翻半天才找到的坑都给你踩平了。1. 先说清楚Atlas 300V 24G是什么适合干什么1.1 它和普通显卡、训练卡有什么区别很多人第一次看到Atlas 300V会下意识拿它跟GPU比这其实是理解这卡的第一道坎。Atlas 300V不是显卡它没有显示输出接口不能接显示器也不做图形渲染。它的全称是AI推理加速卡核心是昇腾AI处理器专门为神经网络推理场景设计的。跟训练卡的区别更明显。训练卡要跑反传、要不断地更新权重对算力精度和显存带宽要求极高而推理卡只做前向计算输入一张图输出一个结果。所以Atlas 300V在设计上省掉了很多训练才需要的电路和缓存机制换来了更低的功耗、更高的能效比还有更实在的硬件视频解码能力。官方标称INT8算力在百TOPS级别显存24GB单卡最大功耗才几十瓦这放在GPU里是不敢想的功耗水平。回到热搜词那个问题Atlas 300V 24G是运算加速卡吗答案很明确是但它加速的是神经网络运算不是通用数值计算。你拿它跑MATLAB、跑CUDA程序是跑不了的它的生态是CANN昇腾异构计算架构是MindSpore、MindX SDK这套东西。1.2 算力规格怎么看24G显存、视频解码、INT8我手头这张Atlas 300V 24G的规格挑几个关键的说AI算力INT8格式下标称百TOPS级别具体数值以官方规格书为准。这个算力跑YOLOv5s这种小模型单路1080P视频实时推理完全没压力。显存24GB LPDDR4X注意这不是GDDR6也不是HBM带宽跟训练卡没法比但对推理场景来说容量比带宽更关键。24G能装下不少大模型YOLO系列的权重文件撑死几十MB就算用TensorRT、用AIPP做多batch显存也绰绰有余。视频解码这是Atlas 300V非常能打的地方支持H.264/H.265硬件解码官方资料里给出的路数在百路级。这意味着做视频分析平台时你可以把解码、缩放、推理整个链路都压在这张卡上不占用CPU资源。功耗整卡功耗不高无风扇被动散热为主服务器里需要确保风道通畅。这点我后面专门讲。这张卡最合适的场景就是视频结构化、目标检测、OCR、人脸识别这类CV推理任务。你要是做纯NLP的大模型推理虽然也能跑但性价比不如专门的语言模型加速卡来得高。1.3 一张卡能跑什么不能跑什么我帮不少同事评估过这张卡核心结论是它能干的事和不能干的事同样清晰。能干的YOLOv5、YOLOv8等目标检测模型这是最成熟的生态网上资料最多踩坑最浅。图像分类模型ResNet、MobileNet系列。OCR方向的检测识别模型比如DBNetCRNN。视频解码、图像预处理缩放、归一化、色域转换。不能干的或者说干得很难受的大语言模型微调、从头训练。它只有推理能力做不了训练。直接跑PyTorch/TensorFlow的GPU代码。算子、显存管理全都不一样必须过CANN这一层。任何依赖CUDA的第三方库比如某些语音处理库直接不支持。说白了Atlas 300V就是为你把模型“送上线”而生的别指望它像3090那样啥都能干。2. 环境搭建从硬件到CANN工具链一次到位2.1 硬件安装与服务器适配Atlas 300V的物理形态是标准PCIe全高全长卡安装本身没什么特别的跟装网卡一样插进PCIe x16槽位就行。但有几个细节我建议你注意第一供电和散热。这张卡虽然功耗不高但被动散热意味着它完全靠服务器机箱的系统风扇散热。如果你把它插在塔式工作站里而工作站本身风道设计差跑高负载推理时很容易触发降频甚至温度报警。我踩过一次在塔式机里跑4路视频流跑了半小时后推理延迟从20ms涨到50ms一查核心温度飙到90多度。后来加装了一个朝向PCIe槽位的机箱风扇才解决。第二CPU平台兼容性。Atlas 300V驱动对x86和鲲鹏平台都支持但不同服务器厂商的BIOS设置可能影响PCIe链路稳定性。我建议进BIOS确认PCIe链路速率不要强制到Gen4有些老主板的PCIe Gen4信号质量不过关会把卡的链路速率协商到Gen1性能直接崩盘。保守起见锁定Gen3。第三单机多卡。如果你打算插两张Atlas 300V注意PCIe槽位间距。两张卡厚度不薄间距太近会导致散热互相干扰。更关键的是多卡场景下驱动安装要确认每张卡的设备ID都正常识别不要一张卡装好了另一张在系统里看不到。2.2 驱动和固件安装CANN Toolkit版本匹配软件环境是整个Atlas生态里最容易出问题的地方因为它的组件太多版本之间的依赖关系又绑得很死。先说核心组件驱动Driver和固件Firmware底层支撑硬件运行必须配套安装。CANN Toolkit昇腾计算语言包包括ATC模型转换工具、推理运行时AscendCL等是开发推理应用的核心。MindX SDK封装了插件化推理流水线做视频分析用起来很方便但非必须。我第一次搭环境时照着官方文档一路“下一步”结果装到CANN Toolkit时提示找不到驱动。折腾半天发现是版本不匹配驱动升到了6.3版本但CANN Toolkit还是6.2接口对不上。后来养成习惯每装一个版本前先到官网查【版本配套表】把驱动、固件、CANN Toolkit、MindX SDK四个版本全部对齐一次装到位。具体安装步骤大概是这样的# 1. 以root用户安装驱动和固件安装包一般是 .run 文件 chmod x Ascend-hdk-*.run ./Ascend-hdk-*.run --full # 2. 安装CANN Toolkit同样以root执行 chmod x Ascend-cann-toolkit_*.run ./Ascend-cann-toolkit_*.run --install # 3. 设置环境变量 source /usr/local/Ascend/ascend-toolkit/set_env.sh一定要记得在/root/.bashrc里把环境变量固化不然重启终端后atc命令找不到。2.3 用npu-smi确认卡状态装完驱动后第一件事就是确认卡有没有被系统识别。Atlas生态里对应NVIDIA的nvidia-smi的工具叫npu-sminpu-smi info正常输出会列出卡槽位、芯片温度、HBM/LPDDR显存占用、AI Core利用率这些信息。看到类似下面的关键字段就说明卡已经就绪Chip: Ascend 310P或对应的处理器型号Memory Usage: xxx/24576 MBAI Core Usage: 0%Temperature: 40°C上下如果npu-smi命令找不到先确认环境变量有没有source。如果报“No device found”大概率是驱动没装好或者固件没刷进去回到第2.2节重新核对版本。这里提醒一句别把npu-smi的输出当成GPU显存那样去理解。Atlas卡的显存分配不仅看显存容量还要看AI Core的负载。有些模型转换后调度效率低AI Core利用率只有个位数显存虽然够但性能拉胯这种问题后面在推理调优部分细说。3. 把YOLO模型搬到Atlas上模型转换全流程3.1 为什么要转OM模型不直接用PyTorch我第一次用Atlas时也犯过懒心想PyTorch推理这么成熟能不能直接把权重文件丢上去跑。答案是不行。昇腾推理芯片不认识PyTorch的权重格式它只认识自己的模型格式叫OMOffline Model。OM模型是经过CANN工具链编译后的离线模型里面不仅包含网络结构还包含了算子在昇腾硬件上的调度方案、算子融合信息以及内存分配策略。也就是说你需要的所有东西在模型转换那一刻就已经定下来了推理时不需要再动态解析网络结构所以效率才高。这个思路跟TensorRT其实非常像TRT也是在推理前做engine编译把网络固化下来。习惯了“PyTorch加载权重直接跑”的人最开始都会觉得多一步转换很麻烦但理解了之后你会发现这一步其实帮你做了很多编译优化它换来的是推理性能的确定性。3.2 准备YOLOv5/YOLOv8模型导出ONNX目前YOLO两个主流分支YOLOv5和YOLOv8转换成OM的标准路径都是先导出ONNX再通过ATC工具转OM。不要尝试直接把.pt文件喂给ATCATC不认PyTorch格式除非你走MindSpore的转换链路但明显绕远了。YOLOv5导出ONNX的命令python export.py --weights yolov5s.pt --include onnx --opset 11 --simplifyYOLOv8导出ONNXyolo export modelyolov8s.pt formatonnx opset11 simplifyTrue这两个命令导出来的ONNX默认包含NMS后处理逻辑。这里有个重要选择你要不要保留ONNX里的NMS我的建议是第一次尝试时强烈建议导出不带NMS的版本也就是只保留模型的主干检测头输出。原因有两个一是ATIC转换时带NMS的ONNX经常出现算子不支持的情况非Max版本算子兼容性有限排查起来很费劲。 二是后处理放在模型外面做你自己控制非极大值抑制的参数比如IOU阈值、置信度阈值调试起来更灵活。模型里写死了NMS参数想调个阈值还得重新转模型太不划算。YOLOv5导出不带NMS的版本可以在export.py里加--nms参数控制不传就是不带YOLOv8稍微麻烦一点我一般用下面这种方式把它放到CPU上用ONNX Runtime跑一遍验证输出shape确认是(1, 8400, 85)这种就说明NMS确实在模型之外了。3.3 ATC工具转换关键参数详解ONNX有了接下来是关键一步用ATC转OM。命令看着不长但每个参数都值得认真抠我直接给出工作中验证可用的一条atc --modelyolov8s.onnx \ --framework5 \ --outputyolov8s_bs1 \ --input_shapeimages:1,3,640,640 \ --soc_versionAscend310P3 \ --insert_op_confaipp.cfg \ --output_typeFP32 \ --loginfo逐个说--framework5表示输入模型是ONNX。CANN里面1是Caffe、2是MindSpore、3是TensorFlow、5是ONNX别记混了。--input_shape固定输入尺寸。注意你导出的ONNX如果输入是动态shape比如batch-1转换时会报错除非加上--dynamic_batch_size之类的参数。我们的YOLO部署通常固定batch为1所以直接写死1,3,640,640最简单。--soc_version这是硬件型号参数要根据实际芯片型号填。Atlas 300V对应的soc型号通常是Ascend310P3。填错了转换能过但推理时可能会报算子不支持或性能诡异。--insert_op_confaipp.cfgAIPP是AI Preprocessing的缩写就是把图片缩放、归一化这些预处理操作从CPU搬进芯片的AI Core里去省掉主机端的开销。aipp.cfg的内容写法有讲究aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_h: 640 src_image_size_w: 640 csc_switch: true rbuv_swap_switch: false mean_chn_0: 0 mean_chn_1: 0 mean_chn_2: 0 min_chn_0: 255.0 min_chn_1: 255.0 min_chn_2: 255.0 }YOLOv5/YOLOv8在训练时输入图像是0到1的浮点数也就是要除以255。在AIPP这里是靠设置min_chn为255来实现的而不是写mean和std。这是最容易弄混的地方。3.4 常见坑动态shape、NMS位置、AIPP归一化模型转换这一环我见过太多人卡住总结下来就三个高频坑。第一个坑是动态shape。很多人用自己的推理脚本导出ONNX时没固定shape导出后输入维度是动态的ATC直接报错。解决办法要么导出时固定shape要么在ATC参数里增加--dynamic_batch_size1,2,4来支持可变batch但后者会牺牲一点性能因为芯片要预留多种shape的调度空间。我平时固定batch1跑单路视频需要多路并发时宁可多线程各跑一个batch1的模型也不开动态shape。第二个坑是NMS算子转换失败。如果坚持要保留ONNX里的NMS大概率在ATC阶段报Unsupport Op。这时候先查算子映射表看看这个NMS算子在当前CANN版本里有没有对应的融合实现。没有就去掉NMS改在推理代码里用torchvision.ops.nms或者OpenCV实现后处理。第三个坑是AIPP配置与训练预处理不一致导致的精度下降。YOLOv5默认训练会做mosaic增强、hsv变换推理时只做letterbox等比例缩放填充归一化。如果你AIPP里忘了做letterbox直接把原图resize成640x640小目标检测精度会明显变差。解决办法是推理侧用OpenCV先做letterbox保留下填充的信息再送入模型。AIPP只负责归一化不做letterbox这个职责一定要拎清楚。4. 推理部署用MindX SDK和pyACL跑起YOLO4.1 两种方式MindX SDK的pipeline还是pyACL手写模型转好了下一个问题是推理代码怎么组织。昇腾生态给了你两条路一条路是MindX SDK它把解码、缩放、推理、后处理这些常见步骤封装成了一个个可插拔的插件plugin你用配置文件把插件串成一条pipeline程序基本不用怎么写代码改改配置文件就能跑。适合视频流分析这种固定链路场景。另一条路是pyACLAscendCL的Python接口相当于昇腾的CUDA运行时API你可以直接控制模型加载、输入输出、内存拷贝。灵活度高适合定制化逻辑但代码量上来了。我的个人建议如果你跑的是YOLO检测且输入是视频流文件或RTSP流优先用MindX SDK因为它自带硬件解码插件省掉你用OpenCV软解的CPU开销如果你是做在线服务每来一帧图片调用一次或者你需要在推理前后插入大量业务逻辑用pyACL更顺手。4.2 MindX SDK流水线mxpi_rroialign、mxpi_tensorinferMindX SDK的pipeline配置是写在一个.pipeline文件里的类似下面这样{ mxsdk: { dir: { mxpi_rtspsrc0: { factory: mxpi_rtspsrc, props: { rtspUrl: rtsp://your-stream-url }, next: mxpi_videodecode0 }, mxpi_videodecode0: { factory: mxpi_videodecode, next: mxpi_imageresize0 }, mxpi_imageresize0: { factory: mxpi_imageresize, props: { resizeWidth: 640, resizeHeight: 640 }, next: mxpi_tensorinfer0 }, mxpi_tensorinfer0: { factory: mxpi_tensorinfer, props: { modelPath: ./yolov8s_bs1.om }, next: mxpi_objectpostprocess0 }, mxpi_objectpostprocess0: { factory: mxpi_objectpostprocess } } } }这一段看着简单但有几个点值得展开。mxpi_imageresize只做暴力resize不做letterbox这意味着如果你的模型输入要求640x640而源视频是1920x1080直接resize会让目标比例失真。MindX SDK里面有个插件叫mxpi_imageresize但没有现成的letterbox插件很多人的做法是在mxpi_imageresize前面挂一个Python插件mxpi_pythonplugin自己写letterbox逻辑或者干脆把letterbox的函数写进后处理前的Python脚本里。另一个容易踩坑的是mxpi_tensorinfer的输出名字和数据格式。MindX SDK里推理插件的输出默认是mxpi_tensorinfer0这个key下的tensor列表你需要用MxToolsGetImageData之类的接口去取取出来的数据是一维的得自己reshape成(1, 8400, 85)这种shape再做解码。很多人纠结“为什么我取出来的output是平的没有shape信息”原因是MindX SDK为了性能把shape信息跟数据分离了你要从tensor_desc里自己读shape。4.3 pyACL最小推理代码骨架如果你选择pyACL下面这个骨架足够你起步了。简化掉异常处理和内存释放核心逻辑就这几步初始化、加载模型、准备输入输出、执行推理、取结果。import acl import numpy as np # 1. 初始化 ret acl.init() ret acl.rt.set_device(0) # 2. 加载模型 model_path b./yolov8s_bs1.om model_id, ret acl.mdl.load_from_file(model_path) # 获取模型描述用于后续分配输入输出内存 model_desc acl.mdl.create_desc() ret acl.mdl.get_desc(model_desc, model_id) # 3. 获取输入输出尺寸 input_size acl.mdl.get_num_inputs(model_desc) output_size acl.mdl.get_num_outputs(model_desc) # 这里根据实际模型填通常输入是1x3x640x640 input_dims (1, 3, 640, 640) input_data np.random.rand(*input_dims).astype(np.float32) # 4. 申请device内存并拷贝数据 dev_buffer acl.rt.malloc(input_data.size * 4) ret acl.rt.memcpy(dev_buffer, input_data.size * 4, input_data.ctypes.data, input_data.size * 4, acl.rt.memcpy_kind.DEVICE_TO_DEVICE) # 5. 创建输出数据集 output_dataset acl.mdl.create_dataset() # 循环为每个输出创建acl.mdl.create_data_buffer这里省略具体细节 # exec ret acl.mdl.execute(model_id, input_dataset, output_dataset) # 6. 从输出数据集里取数据转numpy做后处理这段代码我特意没有写完整因为完整版会有大量内存管理的模板化代码博客篇幅有限你看明白数据流就行。但有几个点必须强调acl.mdl.execute是同步接口会阻塞到推理完成。异步版本是acl.mdl.execute_async做多路并发时有优势但需要你自己管理stream和同步事件。输入数据必须放在device内存里不能直接传numpy数组的指针这是新人最容易犯的错。输出数据取出来后先看shape再reshape。YOLOv8的输出shape一般是(1, 84, 8400)或者(1, 8400, 84)不同导出方式不一样别想当然。4.4 后处理从输出张量到目标框后处理这一步是部署YOLO系列模型的重头戏。不管你是用MindX SDK还是pyACL拿到模型的原始输出后都要自己做解码、过滤、NMS。YOLOv8的输出通常是(1, 84, 8400)其中第一个维度是batch84是4个bbox坐标加80个类别得分8400是不同尺度特征图上的候选框数量。你要做的把(1, 84, 8400)转置成(1, 8400, 84)方便按行处理。从84维里拆出前4维x_center, y_center, width, height注意这里的坐标是模型输入尺寸640x640上的相对坐标需要除以640才能映射回原图或者在做letterbox时记录了缩放比例ratio和填充偏移dw, dh按比例映射到原始分辨率。对每个候选框取80个类别得分里的最大值作为置信度记下类别ID。按置信度阈值比如0.25过滤掉低分框。类别内做NMSIOU阈值设0.45比较常用。每个类别分别做NMS不同类别之间的同类框不需要互相抑制。如果你是在MindX SDK的mxpi_objectpostprocess里配置官方插件已经包含了一部分后处理逻辑但它的输出格式是MxBase的ObjectInfo跟你想直接拿坐标画框的接口还不完全一致往往还需要再转换一层。我在实际项目里倾向于用pyACL手写后处理原因就是后处理逻辑跟业务强相关用官方插件反而要花大量时间去适配它的输出结构。5. 性能优化与多路并发5.1 影响性能的关键因素batch、多线程、设备利用率Atlas 300V跑YOLO性能能到什么水平很多人会很关心。但性能这个东西不单看卡更看你怎么用它。我总结下来影响最终吞吐的核心因素有三个第一个是batch大小。单batch推理一张640x640的图如果耗时10ms那么batch4推理4张图可能只要20ms上下这样单batch平均耗时就从10ms降到了5ms。推理卡和人一样干一件小事和干四件小事的启动成本差不了太多。所以你要是有请求攒批的条件一定要用上。第二个是线程数与stream。AscendCL推理默认同步执行时一个线程一次只能处理一个请求CPU和AI Core之间会有等待。异步执行acl.mdl.execute_async配合多线程CPU负责搬数据和后处理AI Core负责算两者才能重叠起来。我的经验是4到8个线程基本能把单卡的AI Core利用率吃到80%以上再多线程收益就开始递减了。第三个是预处理开销。很多人跑完发现AI Core利用率不高但整体延迟还是很长查了半天发现瓶颈在主机端OpenCV的resize和归一化上。这也是为什么我前面强调要学会用AIPP把归一化扔给芯片做。如果还用CPU做letterbox和resize一定要开多线程不能串行等。5.2 多路视频流场景怎么设计多路视频分析是Atlas 300V的看家本领。一般做16路或32路1080P视频流检测我的方案是设备端硬解码把软件解码的CPU成本降到零。MindX SDK的mxpi_videodecode底层走的是硬件视频解码模块效率远高于FFmpeg软解。如果用pyACL也有对应的VDEC接口写法复杂一些。推理侧采用线程池。每路视频流有独立的采集、推理队列但真正调用acl.mdl.execute的线程是共享的。比如你开一个8线程的线程池每个线程不停地从任务队列里取batch攒够4帧就执行一次batch推理这样既保证了实时性又用了batch的吞吐优势。后处理再扔回各自的线程队列里去画框、输出或推流。这里注意不要让后处理阻塞推理线程最好把后处理做成独立的消费者线程。5.3 实测数据几张卡跑YOLOv5s的吞吐参考我手里没有多卡环境就单卡Atlas 300V 24G给出一组供参考的数据。输入是1080P RTSP视频流用MindX SDK硬解码带AIPP预处理batch1做16路并发YOLOv5s模型。整体跑下来单路视频的推理延迟大概在10到20毫秒之间具体取决于画面中目标数量和后处理耗时。16路同时跑AI Core利用率能稳定在70%以上CPU占用率不到30%大部分开销还是在后处理和业务逻辑上。如果改用batch4并发推理同样16路视频整体吞吐还能再提升20%到30%。batch大了单帧平均延迟会略微上涨但每路视频的帧间隔变短了感官上画面更流畅。需要注意的是这些数据会随CANN版本、模型结构、后处理方式以及服务器CPU性能波动别把它当绝对值但量级上可以作为你评估资源的参考。6. 常见问题与排查技巧实录6.1 问题速查表我把这段时间带团队排查过的高频问题整理成一张表每一条都是真实踩过的不是从文档里抄的现象可能原因排查思路npu-smi info报 No device驱动未安装成功或固件未刷入重新安装对应版本的驱动和固件确认lspci能看到设备ATC转换时报 Unsupported OpONNX里的算子当前CANN版本不支持去掉NMS后处理或升级CANN把不支持算子替换成支持的组合加载OM模型报错提示版本不匹配转换时用的CANN版本和推理时用的CANN版本不一致保证转换和推理在同一版本或者用高版本重新转换OM推理结果全为0或置信度极低AIPP归一化配置错误或者输入图像letterbox没做检查mean_chn/min_chn设置确认输入图像长宽比和训练时一致推理延迟波动大显存碎片化、后台任务占CPU、散热降频查看AI Core利用率检查npu-smi里的温度必要时重启进程多路视频流CPU占用过高视频软解或预处理占用了大量CPU改用硬解码把归一化放到AIPP输出shape和期望不一致导出ONNX时后处理结构不同先打印导出模型的输出节点用ONNX Runtime验证再转换6.2 几个我踩过的坑和调试思路最后分享几个调试技巧这些是文档里不太会写但实战非常管用的。技巧一所有报错先看日志。Ascend生态的报错信息有时很抽象直接抛一个E19999错误码出来。这时候别百度先到/var/log/npu/和~/ascend/log/下翻日志重点看带ERROR的行。我排查过最诡异的一个多卡性能问题最后就是在日志里发现了PCIe链路降级到Gen1的记录才定位到是主板槽位的问题。技巧二ATC转换前养成用ONNX Runtime先验证模型的习惯。转换前在CPU上跑一遍ONNX确认输入输出shape和后处理逻辑都正确再开始转OM。否则你花半天时间转完推理后处理写错了只能回炉重做时间成本更高。技巧三调试后处理时不急着接视频流先从一张图片开始。我调试YOLOv8后处理时都是本地先取一帧JPEG图走一遍完整推理链路打印原始的bbox坐标和置信度用matplotlib画出来对比确认所有环节没问题后再换成视频流。这个习惯帮我避开了至少十次“看起来像硬件问题实际是后处理坐标映射错误”的坑。技巧四版本配套表要截图存档。昇腾的版本迭代很快半年不碰再回来新版本的安装方式可能就变了。每次搭建环境前把官网版本配套表截图保存到项目目录里后面排查问题时能快速定位是不是版本问题。以我个人的体会来说Atlas 300V 24G这卡只要你把环境搭顺了模型转换链路摸透了日常YOLO部署的稳定性一点都不差。很多人觉得昇腾生态“难用”其实难的不是卡本身而是环境版本管理的复杂性。一旦跨过那个坎你会发现它的推理性能、功耗表现尤其是硬件视频解码能力在很多视频分析场景里其实比同价位的GPU方案更实在。希望这篇东西能帮你少走一些我走过的弯路。
