news 2026/9/19 9:19:05

Atlas 300V 24G运算加速卡与NPU架构:YOLO模型部署与调优实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Atlas 300V 24G运算加速卡与NPU架构:YOLO模型部署与调优实践

很多人第一次接触 Atlas,都会带着一个特别朴素的问题:这卡能不能像游戏显卡那样插上就能跑?尤其当身边人聊起"Atlas 部署 YOLO"时,第一反应往往是"是不是又要配 CUDA、配 cuDNN、改一堆环境变量"。

先说结论:Atlas 300V 24G 属于 AI 加速卡阵营,它和普通显卡完全是两条技术路线。我在最初拿到这块卡的时候也犯过糊涂,以为它只是显存更大的"特供显卡",等到真把 YOLO 模型迁移上去,才发现从驱动到工具链再到算子支持,每一步都和 GPU 生态不太一样。这篇内容就围绕 Atlas 运算加速卡的定位、NPU 架构的特点,以及在 Atlas 上部署 YOLO 的完整实操路径展开,给正在观望或者已经踩坑的朋友一些参考。

1. Atlas 300V 24G 的真实定位:先搞清楚"运算加速卡"到底指什么

热搜词里有一条"atlas 300v 24g 是运算加速卡吗",这个问题背后其实藏着一个普遍的困惑:很多人分不清"显卡"“运算卡”“推理卡"这三者的边界。我在实际项目里也遇到过协作同事问"你们那卡能接显示器吗",可见这个概念确实容易被混淆。

1.1 与游戏显卡的本质差异

运算加速卡的核心任务是"算",不是"显示"。普通游戏显卡内部有完整的图形渲染管线,强调实时生成画面;而 Atlas 300V 24G 这类 AI 推理加速卡,强调的是在单位功耗、单位成本内完成尽可能多的矩阵运算和神经网络推理任务。它的设计目标决定了几个特征:

  • 没有面向消费者的显示输出主功能(部分型号保留视频分析输出能力,但用途完全不同)。
  • 驱动栈、开发库和运行生态自成一套,不支持 CUDA。
  • 算子针对性极强,对 CNN、Transformer 等常见结构做了大量硬件级优化。

从硬件规格看,Atlas 300V 24G 搭载昇腾 310P 系列芯片,24GB 显存主要服务于视频分析、目标检测、语义分割这类推理负载。一块 24G 显存的 300V 卡,在跑 YOLOv5s 或 YOLOv8s 这类轻量模型时,显存绰绰有余,真正的瓶颈往往在 NPU 算力和数据搬运带宽上,不在容量上。

1.2 Atlas 系列产品线的定位差异

Atlas 这个系列其实覆盖了从边缘到数据中心的多个档位,不提前搞清楚它们的区别,选型时容易张冠李戴:

产品型号芯片主要场景典型形态
Atlas 200/200I昇腾310边缘盒子、小型推理设备模组、开发板
Atlas 300I Pro昇腾310P数据中心推理卡PCIe 卡
Atlas 300V Pro昇腾310P视频分析、多路解码推理PCIe 卡,带视频处理能力
Atlas 500 Pro昇腾310P边缘服务器整机,支持多卡
Atlas 800T昇腾910AI 训练服务器训练集群

注意 300I 和 300V 的区别:300V 在推理之外强化了视频编解码和图像处理能力,对于"从 RTSP 流取视频 -> 解码 -> 缩放 -> NPU 推理 -> 结果叠加输出"这种链路有硬件加速优势。如果你只是拿一张卡跑普通图片推理,300I 和 300V 都能胜任;但要做大规模视频流分析,300V 的硬件解码优势就体现出来了。

1.3 24G 显存的实际意义

很多人被"24G"吸引,以为显存越大就能跑越大的模型。这个理解在 GPU 领域有一定道理,在 NPU 上要打个折扣。Atlas 300V 的 24G 主要是给"多路视频流 + 较大 batch"的场景准备的。比如单路 1080p YOLOv5s 推理,模型本身可能只占几百 MB 显存,但加上 DVPP 硬件解码缓冲、预处理 buffer、多路并发任务,24G 就能支撑几十路甚至上百路的并发分析。如果你只是单张图片跑一次推理,24G 和 8G 的体验差异并不明显。

这就要引入一个更关键的问题:Atlas 的 NPU 与常见 GPU 架构差异极大,部署 YOLO 时不能把 GPU 的整套方法论直接搬过来。

2. NPU 架构与软件栈:为什么不能照搬 GPU 的部署方式

昇腾 NPU 采用的是达芬奇架构,和 NVIDIA GPU 的 CUDA 核心 + Tensor Core 结构完全两码事。你没法像装 CUDA 那样,装上就有完整的生态;也没法指望 PyTorch 代码里一个.cuda()就万事大吉(虽然昇腾提供了 PyTorch Adapter,但工程落地建议和原生的 MindSpore、CANN 工具链配合)。

2.1 达芬奇架构的基本组成

达芬奇架构以 AI Core 为核心计算单元。每个 AI Core 内部包含三种基础计算资源:

  • 矩阵计算单元(Cube Unit):负责矩阵乘累加运算,这是卷积和全连接层的算力来源,单位时间吞吐量远高于普通 ALU。
  • 向量计算单元(Vector Unit):负责逐元素运算,比如激活函数、归一化、逐元素加乘等。
  • 标量计算单元(Scalar Unit):负责任务调度、地址计算、分支跳转等控制流,相当于一个小型 CPU 核心。

在实际运行中,一个卷积算子会被拆分成若干个矩阵乘任务,分发到 Cube Unit 执行;ReLU、Sigmoid 这类激活函数则由 Vector Unit 处理;整个执行过程需要标量单元做同步和调度。这就像一条现代化的流水生产线:Cube Unit 是冲压机,Vector Unit 是喷漆机器人,Scalar Unit 是调度员,三者配合才能完成一个工件的完整加工。如果模型里某个算子硬件不支持,就需要 CPU 兜底,甚至直接报错。

2.2 软件栈分层逻辑

Atlas 的软件栈从下往上大致是:Driver(驱动)-> Firmware(固件)-> CANN(华为 AI 计算架构)-> 推理引擎 / 深度学习框架。

CANN 是核心,它提供了:

  • AscendCL:统一编程接口,类似 CUDA Runtime,负责设备管理、内存管理、模型加载与执行。
  • ATC 模型转换工具:把训练好的 ONNX、TensorFlow、MindSpore 模型转换成昇腾专用的.om离线模型。
  • 图优化与算子融合:ATC 转换时会对计算图做融合和重排,把多个小算子合并成大算子,减少调度开销。
  • DVPP(数字视觉预处理):硬件加速的图片解码、缩放、色域转换、归一化等功能。

理解这套栈之后,部署 YOLO 的思路就清晰了:模型先做离线转换,生成 .om 文件,运行时用 AscendCL 或 MindSpore Lite 加载 .om 执行。整个过程和 GPU 的 "PyTorch 直接加载权重跑前向" 有显著差异,这也是很多人初次接触时觉得"绕"的原因。

2.3 推理引擎怎么选

昇腾目前的推理路径主要有两种:

  1. 用 MindSpore Lite,Python/C++ API 加载 .om 模型,代码清爽,适合快速验证和中小业务。
  2. 直接用 AscendCL API 写 C++ 推理代码,控制粒度更细,适合高并发、低延迟场景。

MindSpore Lite 在工程上更友好,Python 接口对算法工程师几乎是零门槛。AscendCL 更底层,适合做全链路性能调优。我在实际项目中通常先用 MindSpore Lite 跑通业务,再用 AscendCL 优化瓶颈,两条路线可以平滑切换。

3. 在 Atlas 上部署 YOLO 的完整实操路径

这部分直接给可落地的步骤。以 YOLOv5s 为例,讲清楚从权重准备到 NPU 推理跑通的完整链路。我默认读者已经有一台安装了 Atlas 300V 24G 的服务器(x86 架构),操作系统为 Ubuntu 20.04/22.04。

3.1 模型准备与材料核对

部署前要准备的东西有这几样:

  • 训练好的 YOLOv5 权重(.pt文件)或者直接导出的.onnx模型。
  • CANN 工具包(建议 6.x 以上版本,算子支持和优化更完善)。
  • 昇腾驱动和固件,版本要和 CANN 匹配。
  • MindSpore Lite 推理包(python 版即可)。

在导出 ONNX 时有一个重要细节:YOLOv5 原生的 ONNX 导出包含了大尺寸的检测头输出,后处理 NMS 并不在模型内部。因此导出时建议把模型的export参数按部署需求设置,必要时在导出脚本里去掉不必要的 decode 节点,或者让 ATC 转换时只保留主干 + 检测头输出,后处理放到推理代码中用 numpy/opencv 完成。这会直接影响后面转换是否顺利。

3.2 环境安装的顺序很关键

很多人上来就装 CANN,装完抱着一堆依赖错误在原地打转。正确的安装顺序是:

# 1. 先装驱动 ./Ascend-hdk-*.run --install # 2. 确认 NPU 设备可见 npu-smi info # 3. 安装 CANN 工具包 ./Ascend-cann-toolkit-*.run --install # 4. 安装 CANN 内核包(含推理引擎) ./Ascend-cann-kernels-*.run --install # 5. 设置环境变量 source /usr/local/Ascend/ascend-toolkit/set_env.sh

驱动和固件如果不匹配,npu-smi info能看到设备但无法初始化;CANN 和驱动版本差异过大,则会报"runtime 版本不一致"之类的错误。建议对照官方版本配套表,一次到位,不要各自拿最新版强行拼凑。

安装完成后用官方提供的小工具验证环境:

# 查看设备健康状态 npu-smi info # 跑一个简单的环境自检脚本 python -c "import mindspore_lite as mslite; print(mslite.__version__)"

这一步能过滤掉大部分环境问题。

3.3 用 ATC 工具把模型转换成 .om

环境就绪后,核心操作就是模型转换。这里以 YOLOv5s 导出的yolov5s.onnx为例:

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

参数说明:

  • --framework=5表示 ONNX。
  • --soc_version要跟芯片型号对应,310P 芯片一般填Ascend310P3,如果不确定可以用npu-smi info查型号。
  • --insert_op_conf=aipp.cfg用于把预处理"塞进"模型里,这样输入图片可以直接喂原始数据,由 NPU 硬件完成缩放和归一化。
  • 如果不想用 AIPP,可以不做预处理融合,而在推理代码里自己用 OpenCV 把图缩放到 640x640、转成 RGB、归一化,再构造 NCHW 张量。两种方式我都用过,建议正式项目用 AIPP,少一层 CPU 搬运开销。

aipp.cfg示例:

aipp_op { aipp_mode: static input_format: RGB888_U8 src_image_size_w: 640 src_image_size_h: 640 crop: false resize: true resize_w: 640 resize_h: 640 csc_switch: true rbuv_swap_switch: true 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 }

这里要注意:YOLOv5 官方预处理是 RGB、归一化到 0~1,所以把csc_switch打开(BGR 转 RGB),用var_reci_chn填 1/255 完成归一化。转换成功后会出现yolov5s_bs1.om文件,这就是离线模型。

3.4 用 MindSpore Lite 加载模型执行推理

转换成功后,推理代码比想象中简单。给出一个最简可运行的 Python 示例:

import numpy as np import cv2 import mindspore_lite as mslite # 初始化上下文 context = mslite.Context(device_target="Ascend") context.ascend.device_id = 0 # 加载 .om 模型 model = mslite.Model() model.build_from_file("yolov5s_bs1.om", mslite.ModelType.MINDIR, context) # 读取图片并做基础 resize(假设未使用 AIPP,需要手动预处理) img = cv2.imread("test.jpg") img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = cv2.resize(img, (640, 640)) img = img.astype(np.float32) / 255.0 # 构造 NCHW 输入 input_tensor = np.expand_dims(np.transpose(img, (2, 0, 1)), axis=0).copy() # 推理 inputs = mslite.Tensor(input_tensor) outputs = model.predict(inputs) # 拿到检测头输出 output = outputs[0].get_data_to_numpy() # 后续做 decode + NMS

这段代码跑通后,说明 Atlas 上的模型部署链路已经打通。后续要做的就是写后处理解析检测框:把模型输出的 85 维向量(cx, cy, w, h, obj_conf, 80 类 cls_conf)转换成 xywh 坐标,按置信度过滤,再做 NMS。

3.5 后处理放 CPU 还是 NPU?

一个典型的疑问是:NMS 能不能跑在 NPU 上?理论上 CANN 提供了部分算子可以辅助 NMS,但工程上我建议把 NMS 放在 CPU 上。原因很简单:NMS 本身是串行逻辑,且张量动态性很强,放在 NPU 上反而可能因为动态 shape 触发多次重编译,拖慢整体速度。YOLOv5 输出的 25200 个候选框在 CPU 上做一次 NMS 通常只需几毫秒,对端到端延迟影响很小。

Atlas 部署 YOLO 的本质是"模型算子在硬件上高效执行 + 调度逻辑合理落在合适的位置",不是把所有计算都塞给 NPU。

4. 实测中最容易踩的五个坑与完整排查链路

部署 Atlas 的过程中,我踩过的坑比写代码的时间还长。这里挑五个高发问题,每个都给出可复现的排查思路,而不是直接甩解决方案。

4.1 驱动与固件版本不匹配:npu-smi 可见但初始化失败

现象npu-smi info能看到卡,但一调用 CANN 接口就报 "runtime initialize failed: 100004"。

排查链路

# 1. 查看固件版本 npu-smi info -t board # 2. 查看驱动版本 npu-smi info -t driver # 3. 查看 CANN 版本 cat /usr/local/Ascend/ascend-toolkit/latest/version.cfg

对比三个版本的配套关系,检查是否在官方支持矩阵内。这类问题 90% 是"驱动太旧、CANN 太新"或反之。解决办法不是乱升级,而是找一个官方明确标注的配套组合,整体重装。我自己习惯先把旧的卸载干净(注意卸载顺序:CANN -> 固件 -> 驱动),再按配套表安装。

4.2 ATC 转换时报算子不支持

现象:转换中提示 "OP [Slice] does not support on Ascend310P" 或类似 "Unsupported Op"。

排查链路

# 1. 把 ONNX 模型里所有算子列出来,人工核对 python -c "import onnx; m=onnx.load('yolov5s.onnx'); print(set(n.op_type for n in m.graph.node))" # 2. 重点看动态算子 # Resize、Slice、Concat、Gather 这类算子在不同版本 CANN 上支持程度不同

遇到不支持的算子,最直接的解法是升级 CANN 版本(新版本持续补齐算子);如果升级后仍不支持,就得修改模型的表达方式。比如某些版本的 YOLOv5 导出 ONNX 时用了nn.Upsample,ATC 对它的支持比Resize更稳定,可以在导出代码里替换。

我还遇到过一种很隐蔽的情况:模型输入 shape 是动态的,导致 ATC 在推导 tensor shape 时失败。解决方式是把input_shape固定,比如--input_shape="images:1,3,640,640"。如果业务上必须支持多变分辨率,就转换多个不同分辨率的 .om 文件,运行时按需切换,而不是尝试跑动态 shape。

4.3 模型转换成功但推理结果全错

现象:.om 能加载能推理,但检测框乱飞,坐标和类别完全不对。

排查链路

1. 先用一张已知结果的图片,在 GPU 上用 PyTorch 跑出 detection 结果作为基准。 2. 在 Atlas 上推理同一张图,对比输出 tensor 的数值分布。 3. 若数值量级差 255 倍 -> 归一化处理不一致。 4. 若通道顺序错乱 -> BGR/RGB 不一致。 5. 若整体偏移 -> AIPP 里的 csc_switch 或 rbuv_swap_switch 配置问题。

这类问题 90% 出在预处理差异上。我的经验是:如果用了 AIPP,先别初始化归一化参数,直接用原始像素输入推理,看输出置信度是否能大致对上;对不上再检查色域转换,最后才查归一化。不要一步到位把所有预处理都塞进 AIPP,否则出问题时分不清是哪一步错了。

4.4 MindSpore Lite 推理时设备内存不足

现象:加载模型后调用predict报 "aclrtMalloc failed, error code: 205000" 之类。

排查链路

# 1. 看 NPU 内存占用 npu-smi info # 2. 看是不是显存泄漏 # 连续跑 100 次推理,观察内存是否持续增长

如果是某个线程里反复创建Model对象而不释放,跑几次就爆内存。MindSpore Lite 的 Model 用完后要调用model.free(),长期运行的推理服务应复用同一个 Model 实例,不要每次请求都重新加载模型。另外,多进程场景下每张卡绑定一个device_id,避免多个进程抢同一块卡导致内存碎片化。

4.5 推理性能远低于预期:CPU 利用率过高

现象:从日志看 NPU 的利用率只有 30%,但 CPU 被打满,整体推理延迟很高。

排查链路

1. 用 msprof 工具抓时间线,看耗时分布。 2. 如果大量耗时在 H2D(Host to Device)搬运,说明预处理在 CPU 上做太多了。 3. 如果耗时集中在模型执行阶段但 NPU 利用率不高,可能是算子没有融合,或者是 batch size 太小。

解决方向:

  • 把预处理尽量挪到 AIPP 里,让 NPU 硬件完成缩放归一化,减少 CPU 到设备的内存拷贝。
  • 对视频流场景启用 DVPP 硬件解码,而不是用 OpenCV 逐帧解。
  • 适当增大 batch size。在 300V 上跑 YOLOv5s,batch=4 通常比 batch=1 的吞吐高 2~3 倍,延迟却不会线性增加。

5. 性能调优:让 YOLO 在 Atlas 上跑得更快

部署跑通只是第一步,真正上线要考虑吞吐量和延迟。性能调优不是玄学,有清晰的优化路径。

5.1 用固定 shape 换速度

动态 shape 在 GPU 上可以通过 CUDA Graph 等方式优化,在 NPU 上更敏感。ATC 转换时如果允许动态 shape,每个新 shape 都可能触发运行时重编译,首次执行的延迟会显著上升。生产环境建议:

  • 固定输入分辨率(比如 640x640)。
  • 固定 batch size(比如 4),针对不同 batch 分别转换模型。
  • 如果输入视频宽高比不固定,在外部先统一做 letterbox,保证送入模型的始终是 640x640。

5.2 AIPP 融合预处理

把归一化、resize、色域转换全部写进aipp.cfg,运行时直接喂原始图像数据。这样可以避免在 CPU 上做cv2.resize + transpose + astype + 归一化的多次拷贝。注意 AIPP 的 resize 是硬件双线性插值,与 OpenCV 的INTER_LINEAR在边界算法上有细微差异,对检测精度的影响通常很小,但如果追求完全一致,也可以选择关闭 AIPP 的 resize,只做色域和归一化。

5.3 多路视频流并发

如果场景是"多路 RTSP 拉流 + 每路做检测",要尽量避免每路单独创建一个推理模型实例。更高效的做法是:

1. 一个模型实例,多线程共享。 2. 每路视频各自维护一个独立的任务队列。 3. 攒够 batch 大小后统一送一次推理(batch 化)。

这样能显著提升 NPU 利用率。300V 24G 在跑 YOLOv5s + batch=4 的情况下,处理几十路 1080p 视频流是可以做到的,关键是别在用户态频繁进行小批量推理。

5.4 合理设置 CPU 线程与亲和性

MindSpore Lite 和 AscendCL 都支持配置线程数。默认情况下可能不会占满所有 CPU 核心,但也可能因为线程过度创建导致上下文切换开销。实际调优时观察topnpu-smi info的数值,找到延迟和吞吐的平衡点。

调优时我有个习惯:先固定 batch,调线程数;再固定线程,调 batch;每次只改一个变量。同时改多个参数,出了问题根本没法定位。

6. 什么场景下值得用 Atlas,什么场景别碰

写到最后,聊聊选型。Atlas 不是万能的,我见过不少项目在 Atlas 上栽跟头,往往不是卡本身不行,而是场景没选对。

值得用 Atlas 的场景:

  • 视频分析、多路流推理:300V 的硬件解码能力在处理视频流时有明显优势,单卡多路并发能力强,单位路数成本低于通用 GPU 方案。
  • 大规模推理集群:Atlas 800T 系列面向训练和推理一体化集群,如果整个技术栈都基于昇腾生态(MindSpore + CANN),规模化之后维护成本更低。
  • 国产化、自主可控要求明确的场景:这是业务硬约束,不用讨论性价比。

不适合的场景:

  • 单次、零散、小规模推理:比如偶尔跑几张图,Atlas 的驱动环境配置成本远高于随便装个 GPU 跑 PyTorch。
  • 算法快速迭代阶段:模型天天改,算子天天换,每次都要重新转换 .om、排查算子兼容性,会拖慢节奏。建议先在 GPU 上把模型稳定下来,再迁移到 Atlas 做推理部署。
  • 强依赖 CUDA 生态的复杂模型:比如模型里有大量自定义 CUDA kernel,迁移成本会非常高。

Atlas 300V 24G 的定位不是替代所有 GPU,而是把"视频分析、批量推理、边缘部署"这类场景做深做透。它更像是一条专用车道,在合适的场景里效率极高,但硬要拿它当通用显卡用,体验当然不好。

从我个人的实际经验看,部署 Atlas 最大的门槛不是硬件,而是思维方式:从"训练生态思维"切换到"推理工程思维",把模型转换、算子支持、预处理融合这些环节当成一等公民对待。一旦迈过这道坎,你会发现 NPU 的推理性能其实相当扎实。

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

AI玩具通信链路:UART、SDK与云端三层协同设计

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

作者头像 李华
网站建设 2026/9/19 9:17:12

PV-RCNN实战解析:从KITTI数据准备到3D目标检测模型训练与部署

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

作者头像 李华
网站建设 2026/9/19 9:16:56

2026开放式运动耳机实测:十款热门型号佩戴、音质、漏音、续航全对比

1. 开放式运动耳机凭什么成了2026年的主流选择如果你最近半年逛过运动装备区或者刷过跑步装备的讨论帖,会发现一个明显的变化:开放式耳机不再是“小众玩物”,而是被大量跑者、骑行爱好者、健身房常客当成了日常主力。我身边至少有七八个每周跑…

作者头像 李华
网站建设 2026/9/19 9:14:30

AI对话流式输出实战:SSE断点续传与打字机渲染全解析

做AI对话类的前端,绕不开流式输出。用户敲完问题,大模型少说要算好几秒,长一点几十秒都有,你要是等全部生成完再把结果怼到页面上,用户早就跑了。所以现在几乎都是SSE(Server-Sent Events)来接大…

作者头像 李华
网站建设 2026/9/19 9:14:25

NIIT毕业生分享:从Java培训到职场实战的成长之路

1. 从NIIT毕业后的真实职场体验作为一名从NIIT毕业一年多的学员,我想分享这段从校园到职场的过渡经历。很多人对培训机构出来的学员存在偏见,认为我们只是"速成班"产品,但实际情况远比这复杂得多。记得刚入学时,我对编程…

作者头像 李华
网站建设 2026/9/19 9:14:20

七夕表白技术方案手册:可运行、可传播、可留存

1. 这不是代码合集,而是一份七夕表白技术方案手册“50款七夕表白代码大合集”——看到这个标题,你第一反应是不是立刻去搜压缩包、点开GitHub仓库、复制粘贴到编辑器里按F5?我做过三年前端开发、带过五届编程入门工作坊,也亲手调试…

作者头像 李华