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

Atlas 300V部署YOLO实战:推理加速卡选型、CANN环境搭建与模型转换全指南

发布时间:2026/9/25 9:03:40 来源:云帆数科 栏目:资讯中心
Atlas 300V部署YOLO实战:推理加速卡选型、CANN环境搭建与模型转换全指南
最近“atlas”这个关键词的热度又上来了热搜里最扎眼的就是两条“atlas部署yolo”和“atlas 300v 24g 是运算加速卡吗”。第一条说明不少人已经把手里的算法模型走到部署这步准备落到昇腾平台去跑第二条说明很多人在选型阶段就被这张卡的身份搞糊涂了。两个问题串起来看其实就是一条完整的踩坑路径。我在实际项目里用Atlas 300V跑通过YOLO目标检测从硬件选型、环境搭建、模型转换到推理调优前后折腾了小半个月。今天就把整个过程原原本本写下来给准备在这张卡上跑推理模型的朋友当一份参考。不管你是算法工程师、运维、还是实验室里搞部署的学生只要手里躺着一张Atlas 300V或者正在犹豫要不要买这篇文章应该能帮你少走不少弯路。1. Atlas 300V 24G到底是不是“运算加速卡”1.1 一张容易被误读的AI推理卡先说结论Atlas 300V 24G是运算加速卡但它不是像NVIDIA显卡那样通用的“计算卡”而是一张面向AI推理场景的专用加速卡。很多人看到“加速卡”三个字就以为是普通GPU的另一种说法这个认知偏差会在后面的部署里带来一串连锁反应。拿一些常见的NVIDIA显卡举例它们既能做训练也能做推理还能顺带跑CUDA通用计算本质上是比较通用的并行计算设备。Atlas 300V走的完全是另一条路它的核心设计目标是把训练好的神经网络模型高效地跑起来尤其是卷积神经网络这类结构化很强的模型。目标检测、图像分类、语义分割、OCR这些推理任务它很擅长但如果想拿它当普通显卡去跑一个大型蛋白质折叠模拟器那基本就是拧着干。这个区别直接决定了你该怎么用它不要指望把训练代码直接搬到Atlas上跑训练还是老实留在GPU或CPU集群上。Atlas 300V真正擅长的是“把模型变成线上服务”这最后一公里。1.2 为什么这个问题值得认真回答“Atlas 300V 24G是运算加速卡吗”这个问题能成为热搜背后是有原因的。产品命名上华为昇腾系列里有训练卡、推理卡、加速模块好几种形态Atlas 300V属于标准的PCIe形态推理卡但命名里没有“显卡”字样包装和产品页上写的是“AI加速卡”或“推理加速卡”不熟悉昇腾生态的人第一反应就是这到底是个啥能不能插服务器上能不能跑我的PyTorch YOLO再加上最近国产AI推理卡在边缘视频分析、智慧园区、工业质检这些场景里出现频率越来越高很多之前只用过GPU的工程师第一次接触昇腾设备自然会产生这些基础疑问。所以这个问题不是外行才问而是大量有真实部署需求的人在确认硬件边界。我的体会是搞清楚“它是什么”比“它能跑多快”更重要。因为一旦把场景弄错后面每一步都是错的。比如有人以为它是图像渲染卡装上后去跑三维建模软件结果指令集完全不支持折腾半天全是白费功夫。1.3 在部署YOLO之前先想清楚边界如果你确定要在一张Atlas 300V 24G上部署YOLO我建议先想清楚三件事。第一你手里已经有训练好的权重文件比如yolov5s.pt、yolov8n.pt或者导出的ONNX模型如果没有直接上硬件意义不大。第二你的目标场景是推理而不是训练Atlas 300V不是用来训练YOLO的。第三你需要接受一套新的软件栈也就是后面要详细讲的CANN生态。把这三点想明白你就知道这篇文章接下来做的事情是在什么前提下展开的了。如果只是好奇想跑个demo你也可以照着走一遍流程只是没有必要先买卡先在官方文档里找对应型号的模拟环境或者云资源了解一下会更稳妥。2. 核心硬件与软件栈拆解理解Atlas才能用好Atlas2.1 昇腾310P达芬奇架构怎么工作Atlas 300V 24G的算力核心是昇腾310P处理器采用的达芬奇架构和常用GPU的架构思路很不一样。GPU的设计思路是大量简单计算单元并行工作适合各种通用计算任务达芬奇架构则更强调“AI专用计算单元”的定制化设计。可以把达芬奇架构理解成一个高度专业化的加工车间。车间里有专门的Cube单元负责矩阵运算有Vector单元负责向量运算还有Scalar单元处理标量逻辑。跑YOLO这类卷积神经网络时绝大多数计算量集中在矩阵乘法和卷积上Cube单元能把这些操作效率拉满而激活函数、归一化这些操作交给Vector单元处理流程控制则由Scalar单元负责。三个单元分工明确、流水线协作这是它能在功耗不高的情况下跑出不错推理性能的关键。相比之下GPU虽然也用Tensor Core这类专用单元加速矩阵运算但它仍然保留了非常强大的通用计算能力代价就是架构复杂、功耗高、成本高。Atlas 300V的做法更“极简”非AI计算能力尽量压缩专门服务神经网络推理。这种偏向带来一个直接结果——在跑YOLO这类模型时它能用更低的功耗跑出可观的性能但你要是在上面跑非AI负载就会非常别扭。2.2 24G显存意味着什么24G显存放在今天的推理卡里算是一个很不错的配置。很多人对显存的理解停留在“越大越能装大模型”这个说法没错但还不够完整。在推理场景里显存大意味着三件事一是能直接装下更大体积的模型比如YOLO系列里参数量较大的版本或者带Transformer结构的目标检测模型不会因为显存不够而被迫做量化压缩二是能塞进更高分辨率的输入比如把输入从640x640提升到1280x1280检测小目标的能力会明显变好但中间特征图的内存占用会成倍增加三是能支撑多路视频流并行推理这是边缘视频分析最常见的需求。实际项目里我用的YOLOv5s模型输入分辨率640x640转换后模型文件只有几十MB推理过程中占用的显存也不大一秒钟几十帧完全没问题。但如果同时做多路视频流推理或者用YOLOv8m这类更大模型24G的余量就会体现出价值。顺带说一句Atlas 300V的显存是板载专用内存它不是像CPU内存那样可以被操作系统随意调度的。你无法像用普通显卡那样通过共享内存来扩展显存所以显存规划必须在部署之前做好预算别等跑起来才发现不够。2.3 软件栈里的三个关键角色CANN、ATC和AscendCL昇腾平台的软件栈和CUDA生态不是一个体系这一点必须接受。它有自己的一套工具链最核心的三个概念是CANN、ATC和AscendCL。CANN是华为的AI计算框架你可以把它类比成CUDA Toolkit。它包含了驱动、运行时、算子库、图优化引擎等一整套东西。没有CANNAtlas 300V就是一块没通电的高级电路板。安装CANN时要注意版本匹配问题不同型号的处理器对应不同版本的CANN装错了后面每一步都会出问题。ATC是模型转换工具全称叫Ascend Tensor Compiler。它的作用是把训练框架产出的模型文件转换成Atlas硬件能直接运行的om格式。整个过程就像把一份Python代码编译成二进制可执行文件。ATC支持的输入格式包括Caffe模型、TensorFlow的pb模型、ONNX模型和MindSpore模型。对YOLO来说最常用的路径是先导出ONNX再用ATC转成om。AscendCL是昇腾的编程接口类似CUDA Runtime API。你可以用C或Python调用它来加载模型、准备输入输出内存、执行推理。实际写代码时不需要每个人都从底层接口开始啃CANN官方提供了大量样例和封装好的模板YOLO这类常见模型基本都有现成参考。我得给一个很实际的建议刚开始接触Atlas平台时别一上来就尝试把整个项目从PyTorch代码里改出来。先跑通CANN自带的resnet50样例确认整个链路没问题再换上你的YOLO模型。这样排错范围小很多成功率会高很多。3. 在Atlas 300V上部署YOLO的完整实操记录3.1 环境准备硬件安装与系统检查这一节没有任何玄学就是动手前先确认硬件和系统都能正常工作。首先检查服务器是否识别到了Atlas 300V。安装好PCIe卡之后在Linux系统里执行lspci能看到类似“Huawei Technologies Co., Ltd. Intelligent Processing Accelerator”这样的设备信息说明系统已经能从硬件层面识别到这张卡。如果看不到先别急着装驱动检查卡是否插紧、PCIe插槽是否有足够带宽、服务器供电是否稳定。系统层面我建议用Ubuntu 20.04或22.04的x86_64版本内核版本不要太老也不要太新具体支持范围以CANN版本对应的兼容性列表为准。这里特别提醒一句Atlas的工具链对内核版本有要求新内核不一定好因为官方驱动可能还没适配。我曾经在一台新装的内核6.5的机器上折腾了好久最后换回5.15内核一次搞定。所以如果你装完驱动后系统不稳定先怀疑内核版本。另外确认系统时间是否准确。这个看上去无关紧要的小事在证书校验、日志分析里经常给人添乱建议在部署前用ntp同步一次。3.2 固件、驱动、CANN的安装顺序与版本匹配昇腾设备的安装顺序有讲究不能乱先装固件再装驱动最后装CANN Toolkit。固件是芯片底层的微码程序驱动是操作系统和硬件之间的桥梁CANN是上层的计算框架。乱序安装可能导致固件和驱动版本不匹配推理时出现莫名其妙的错误。具体步骤可以从昇腾社区官网下载对应的Ascend HDK和CANN Toolkit安装包。下载时注意匹配你的硬件形态Atlas 300V Pro、Atlas 300V标准版这些型号细节和操作系统版本。解压后运行安装脚本例如固件安装包里的Ascend-cann-kernels-版本号.run按提示确认即可。安装完成后有一个关键检查点执行npu-smi info命令。这个命令类似nvidia-smi能看到芯片编号、温度、显存使用率、算力状态等核心信息。如果npu-smi能正常输出说明驱动和固件这一层已经通了。到此环境底座的搭建就算完成了一大半。然后是安装CANN Toolkit。注意CANN对应有开发版和推理版NNRT开发板适合本地编译、跑样例、做推理开发生产环境如果只需要执行推理装NNRT就够。我个人就是先装完整版把流程跑通后面再整理部署镜像时换成精简的NNRT省空间也省心。安装结束后检查环境变量。CANN安装脚本默认会写入到/usr/local/Ascend/ascend-toolkit/set_env.sh这一步非常容易被忽略。如果你发现python里import acl失败先检查有没有source这个环境变量脚本。我在这一步吃过很多次亏后来干脆写进了服务器开机启动配置里。3.3 模型转换从PyTorch到.om的完整过程环境就绪后开始正式转换模型。我拿最有代表性的YOLOv5s为例官方权重yolov5s.pt输入分辨率设置成640x640。第一步用YOLOv5仓库自带的导出脚本导出ONNX。执行如下命令进行导出python export.py --weights yolov5s.pt --include onnx --img-size 640 640 --batch-size 1导出的onnx模型包含了从输入到输出的完整计算图接下来就要用ATC把它编译成Atlas硬件能执行的om模型。第二步准备AIPP配置文件。AIPP是昇腾平台用于图像预处理的组件可以在模型转换时把图像缩放、归一化、颜色空间转换这些操作固化到模型里这样推理时就不需要单独写预处理逻辑性能更好。对YOLOv5来说常用的AIPP配置如下aipp_op { aipp_mode: static input_format: RGB888_U8 mean: 0.0 0.0 0.0 min_chn_0: 0.0 min_chn_1: 0.0 min_chn_2: 0.0 var_reci_chn_0: 0.00392156862745098 var_reci_chn_1: 0.00392156862745098 var_reci_chn_2: 0.00392156862745098 }这里面核心是var_reci_chn数值等于1/255也就是把0到255的像素值归一化到0到1之间。如果你的训练代码里用了不同的均值方差归一化这里要改成和训练时一致否则精度会莫名其妙变差。第三步执行ATC转换。一条完整的转换命令长这样atc --modelyolov5s.onnx --framework5 --outputyolov5s_bs1 --input_shapeimages:1,3,640,640 --soc_versionAscend310P3 --insert_op_confaipp_yolov5.cfg注意几个参数的含义。framework5表示输入是ONNX模型output是输出om文件名input_shape需要和ONNX模型的输入名和维度保持一致YOLOv5导出的onnx输入名一般是imagessoc_version一定要写对它告诉ATC当前芯片是哪个型号写错了转换时会直接报错。Atlas 300V Pro对应的是Ascend310P系列具体到芯片小版本可以用npu-smi info里的芯片型号确认。转换完成后会生成yolov5s_bs1.om文件。此时可以再用ATC带一个--output_type参数指定输出精度比如FP32或FP16。如果追求性能FP16通常会更快但要注意精度变化是否能接受这个要结合你的实际测试结果决定。3.4 推理代码编写与性能验证om模型有了接下来就是用AscendCL在Python里跑推理。实际工程上不建议从零封装接口但为了讲清楚原理我用最简单的方式展示一次完整流程。初始化、加载模型、准备输入、执行推理、解析输出这五步是铁打不动的骨架。简化后的核心代码思路如下import acl import numpy as np # 初始化并设置计算设备 acl.init() ret acl.rt.set_device(0) context, ret acl.rt.create_context(0) # 加载om模型 model_id, ret acl.mdl.load_from_file(b./yolov5s_bs1.om) # 查询模型输入输出信息分配host侧和device侧内存 input_desc acl.mdl.create_desc() acl.mdl.get_input_desc(input_desc, model_id, 0) ... # 准备输入图像数据这里是numpy数组 input_data np.random.randn(1, 3, 640, 640).astype(np.float32) # 把数据从host拷贝到device ... # 执行推理 ret acl.mdl.execute(model_id, input_data_ptr, output_data_ptr) # 把输出数据从device拷回host ... # 解析输出对YOLOv5s来说shape是[1, 25200, 85] # 分别对应batch、预测框候选数、bbox(4) objectness(1) class scores(80) # 释放资源 acl.mdl.unload(model_id) acl.rt.destroy_context(context) acl.rt.reset_device(0) acl.finalize()这段代码只是为了把链路走通。真正工程化的时候我会用CANN官方提供的acllite封装库它对输入数据处理、内存管理做了一层友好的封装省掉大量重复代码。这里推荐一个做法在CANN安装目录的样例工程里找到InferObjectDetection这个示例它本身就带YOLO系列模型的推理模板先在这个模板上把流程跑通再替换成你自己的模型和业务逻辑上手速度会快得多。推理跑通之后性能验证也有固定套路。用npu-smi info监控推理时的芯片利用率、显存占用、温度和功耗。如果某个环节利用率上不去就需要检查是不是host和device之间的数据拷贝太多或者模型转换时的输入输出配置不合理。对视频流分析场景来说一条简单但重要的建议是尽量把图像预处理缩放、归一化、颜色转换全部交给AIPP不要留在host侧用CPU做避免CPU成为瓶颈。4. 常见问题与排查技巧实录4.1 环境类问题装完跑不起来怎么办最典型的问题是装完驱动后npu-smi info看不到设备。遇到这种情况我建议按顺序排查先看lspci有没有设备没有就是硬件识别问题检查插槽和供电lspci有但npu-smi没有多半是驱动和固件版本不匹配或者内核模块没有加载查看/var/log/npu下方的驱动日志找线索再不行就检查内核版本是否在官方兼容列表里。另一个高发问题是import acl时报错。这通常是环境变量没生效。执行source /usr/local/Ascend/ascend-toolkit/set_env.sh后再试如果好了记得把source写进~/.bashrc否则换个终端就找不到库。还有个很隐蔽的问题多卡环境下定了错误的device_id。如果服务器里插了多张Atlas卡npu-smi info会把它们都列出来代码里要显式设定设备号别默认等于0否则可能跑在别的卡上负担不均匀还排查半天。4.2 模型类问题转换报错与精度偏差ATC转换报错里最常见的几类一是soc_version写错二是ONNX模型里包含了当前CANN版本不支持的算子。解决思路是先用netron之类的工具打开onnx快速看一下模型结构确认输入输出节点的名字和shape再对照报错信息搜索解决。如果算子不支持优先考虑升级CANN版本其次看能否将模型导出的算子集版本调低因为新版算子有时候会带来兼容门槛。精度问题则要区分两种情况。一种是完全跑出垃圾结果比如所有框都是错的重点检查AIPP配置里的输入格式是否和训练数据一致尤其注意RGB和BGR的区别。另一种是检测率下降但不完全失活重点检查归一化参数是否和训练时一致以及模型转换时是否开了精度压缩选项。这里我踩过一个大坑YOLOv5导出onnx时输入名是images我在ATC命令里写成了input结果转换倒是成功但推理时数据没喂对输出全是乱框。后来养成习惯每次做模型转换前先打印一遍onnx graph graph.input和graph.output确认节点信息再也不在这上面浪费时间。4.3 性能类问题怎么从“能跑”到“跑得稳”“能跑”和“跑得稳”之间隔着好几个硬指标。性能不达标时我一般从三个方向找原因。第一模型输入分辨率。YOLOv5s在640x640和1280x1280两种输入下的推理耗时差距远不是两倍因为特征图呈平方级增加。如果业务场景允许先用小分辨率跑通再逐步提分辨率找到一个准确率和延迟的平衡点。第二AIPP到底做没做。这是很多人容易忽略的点。如果预处理全部在host侧的Python脚本里做不仅代码冗长效率也低。把图像缩放和归一化放进AIPP后我实测过的项目里有明显提速因为很多操作在硬件里直接完成了。第三批量推理的充分利用。如果你处理的是视频流或者大批量图片一次推理塞多个batch会比单张循环快很多因为减少了多次调用开销。当然要提前确认模型转换时open了多batch的input_shape比如image:4,3,640,640否则推理时会直接报shape不匹配。性能问题排查时还有一个好帮手CANN的profiler工具可以统计模型里每个算子耗时。我第一次用它定位到一个后处理算子耗时异常后来发现是输出节点配置不合理导致的调整后性能好了不少。关于版本配套和后续扩展的一点个人体会最后分享一下我的个人习惯。现在每次拿到一张昇腾卡我不会急着装最新版CANN而是先去官网确认硬件型号、操作系统、内核版本和CANN版本的配套矩阵把这四项钉死之后再动手。看起来多花二十分钟实际上能省后面好几天排错时间。项目里我也会把配套版本记录在部署文档里因为半年后你自己回头看也未必记得当初用的是哪一版。再补一个实用技巧跑通YOLO之后别急着撤。先用 profiler 留下性能基线数据再保存一个最小可运行的推理脚本和配套的转换命令放到项目仓库里。等以后需要换模型、调性能的时候你会发现当初顺手留下的这套“最小工程”才是真正的宝贝。Atlas平台的坑不算少但每踩一个都能学到一套自己的排查方法这种经验是拿多少钱都换不回来的。

相关推荐

LLM时代的信息自由:从RAG到Agent的落地实践与避坑指南
LLM时代的信息自由:从RAG到Agent的落地实践与避坑指南

1. 从“信息自由”说起:LLM到底改变了什么“信息自由”这个词,放在大语言模型(LLM)的语境下,其实有两层意思。第一层是获取信息的自由——过去你要查一个冷门知识点,得翻好几页搜索结果,还得自己… · 2026/9/25 9:03:40

zip、rar、7z、tgz 压缩格式选型指南:压缩率、兼容性与加密实战对比
zip、rar、7z、tgz 压缩格式选型指南:压缩率、兼容性与加密实战对比

/* 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 9:03:34

GAS框架落地ARPG战斗系统:核心模块与实战避坑指南
GAS框架落地ARPG战斗系统:核心模块与实战避坑指南

1. 为什么ARPG战斗系统最终选了GAS做ARPG战斗系统,最绕不开的一个选择题就是:战斗逻辑到底自己手写,还是直接用现成的框架?说实话,在接触GAS(Gameplay Ability System)之前,我也走过… · 2026/9/25 9:03:34

程序员用AI写AI代码:TaoToken统一Key接入Copilot的settings.json配置与验证
程序员用AI写AI代码:TaoToken统一Key接入Copilot的settings.json配置与验证

/* 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 9:43:30

网络安全应急演练实战:从ATTCK场景设计到自动化处置剧本
网络安全应急演练实战:从ATTCK场景设计到自动化处置剧本

简介:这份文档资料面向政府机构、企事业单位的安全管理人员及专业应急处理人员,系统讲解网络安全应急响应预案的培训与演练方法,帮助组织在遭遇网络攻击、数据泄露等突发事件时做到临危不乱、快速处置。内容围绕演练目的、预案培训、实战演练… · 2026/9/25 9:43:24

系统安全与网络安全:双线防御的落地实践与衔接技巧
系统安全与网络安全:双线防御的落地实践与衔接技巧

简介:《计算机系统安全与计算机网络安全》是一份PDF格式的学习参考资料,定位面向计算机专业学生、网络管理员及网络安全入门者,用于建立计算机系统安全与网络安全的基础知识框架。资源包仅包含1个PDF文件,大小约1.07MB&#xff0c… · 2026/9/25 9:43:24

红蜘蛛管控系统深度卸载与网络无感禁用指南
红蜘蛛管控系统深度卸载与网络无感禁用指南

1. 红蜘蛛不是“普通软件”,而是一套深度驻留的教室管控系统很多人第一次面对红蜘蛛(3000soft Red Spider)时,下意识把它当成一个双击就能关掉的普通教学软件——点右上角、任务栏右键退出、甚至进任务管理器结束进程,… · 2026/9/25 9:43:24

CTMS系统架构设计:从状态机到合规审计的落地指南
CTMS系统架构设计:从状态机到合规审计的落地指南

简介:CTMS 系统架构说明是一份面向客户与开发者的技术文档,旨在解决 CTMS 系统部署前的容量规划、性能评估与数据安全等关键问题。内容覆盖系统架构(一般型与扩充型)与软件架构分层,说明两种架构的适用场景——一般型适… · 2026/9/25 9:43:24

别把 CTF-All-In-One 当书读:它的正确用法是索引加训练闭环
别把 CTF-All-In-One 当书读:它的正确用法是索引加训练闭环

简介:《ctf-all-in-one.pdf》是一份面向CTF与网络安全学习者的系统化知识手册,覆盖从基础入门到高阶实战的完整链条。文档从CTF赛事形式与规则讲起,依次深入Linux/Web基础、逆向工程、密码学和Android安全等知识模块,并重点拆解Pw… · 2026/9/25 9:43:18

数值优化(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

了解更多?预约专属演示

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

企业微信二维码