昇腾 NPU 实战:Gemma 2 模型部署、多维度评测与性能优化全流程解析

前言
随着大语言模型(LLM)技术的飞速发展,模型的规模与能力不断攀升,对底层计算硬件的性能和效率也提出了前所未有的挑战。Google 推出的 Gemma 2 系列模型,以其卓越的性能和开放的生态,成为了社区关注的焦点。与此同时,以昇腾(Ascend)NPU 为代表的国产 AI 计算硬件,凭借其独特的 Da Vinci 架构,在 AI 推理与训练领域展现出强大的竞争力。
本文将详尽记录在昇腾 NPU 计算平台上,对 Google Gemma 2 (gemma-7b-it) 模型进行推理实测的全过程。内容涵盖从基础环境的搭建、依赖库的安装与冲突解决,到模型的下载、适配,再到执行一套精心设计的多维度、多场景性能评测。最终,通过对评测数据的深度分析,全面揭示 Gemma 2 模型在昇腾 NPU 上的实际性能表现,为相关技术选型、部署优化和性能评估提供第一手的数据参考和详实的实践指引。
1. 基础概念解析
在进入实操环节之前,首先对本次评测涉及的两个核心技术——昇腾 NPU 和 Gemma 2 模型进行详细介绍。
1.1. 昇腾(Ascend) NPU 简介
昇腾(Ascend)是华为公司推出的全栈全场景 AI 解决方案,其核心是昇腾系列 AI 处理器。本次测试使用的昇腾 910B 是一款高性能的 AI 处理器,属于该系列中的一员。
- NPU (Neural-network Processing Unit):即神经网络处理器,是一种专门为加速神经网络计算而设计的硬件。与通用处理器(CPU)和图形处理器(GPU)相比,NPU 在执行深度学习中常见的矩阵乘法、卷积等运算时,具有更高的能效比和计算密度。
- Da Vinci 架构:昇腾 NPU 的核心是其自研的达芬奇(Da Vinci)架构。该架构集成了标量、向量和张量(Cube)计算单元,能够灵活高效地处理不同类型的计算任务。其中,3D Cube 计算单元是其标志性特征,专门用于加速矩阵乘法运算,这正是大语言模型推理过程中的计算瓶颈所在。
- CANN (Compute Architecture for Neural Networks):昇腾异构计算架构。它不仅仅是硬件驱动,而是一个完整的软件栈,包含了驱动层、芯片使能库、深度学习框架适配层(如 PyTorch、TensorFlow)、以及应用使能层。CANN 的存在,使得上层应用开发者可以方便地调用昇腾 NPU 的强大算力,而无需直接操作底层硬件。本次测试中使用的
torch-npu库,就是 CANN 软件栈中适配 PyTorch 框架的关键组件。
1.2. Google Gemma 2 模型简介
Gemma 是 Google DeepMind 团队基于其 Gemini 模型的研究成果和技术开发的一系列轻量级、开放的语言模型。本次测试选用的是 gemma-7b-it 版本。
- 模型规模:
7b表示该模型拥有约 70 亿(7 Billion)个参数。这是一个在性能和资源消耗之间取得良好平衡的参数规模,适合在单张高性能计算卡上进行推理部署。 - 模型类型:
it是 “Instruction Tuned” 的缩写,意为“指令微调”。这表明该模型不仅具备基础的语言生成能力,还经过了大量指令-响应数据的微调,使其能够更好地理解和遵循人类的指令,完成问答、摘要、代码生成等特定任务。这使得它在实际应用场景中更为实用。 - 技术架构:Gemma 模型采用了与 Transformer 架构类似的解码器(Decoder-only)结构,这是当前主流大语言模型的通用架构。它在多头注意力机制、位置编码等方面进行了一些优化,以提升模型效率和性能。
- 开放性:Gemma 模型是开放权重模型,允许研究人员和开发者免费使用、修改和分发,极大地促进了 AI 社区的创新和应用落地。
将 Gemma 2 这样先进的开放模型部署在昇腾 NPU 这样的国产高性能硬件上,不仅是对硬件性能的一次检验,也是对整个 AI 软硬件生态适配成熟度的一次重要评估。
2. 实战环境准备与配置
本次实测在 GitCode Notebook 平台上进行,该平台提供了搭载昇腾 NPU 的即用型计算实例,免去了本地硬件配置的复杂过程。
2.1. GitCode Notebook 实例创建
首先,需要登录 GitCode 平台,在 Notebook 服务中创建一个新的实例。

在创建界面,关键在于选择正确的计算资源和环境。点击“激活”按钮,进入资源配置页面。

2.2. 计算资源与镜像确认
为确保测试环境的准确性和可复现性,必须严格按照以下配置进行选择:
- Notebook 计算类型:
NPU。这指定了实例将使用神经网络处理器作为核心计算单元。 - NPU 配置:
NPU basic・1 * NPU 910B・32v CPU・64GB。这个配置表明,实例分配了 1 张昇腾 910B NPU 卡,并配备了 32 核 CPU 和 64GB 系统内存。这个资源配置对于运行 7B 规模的模型是充足的。 - 容器镜像:
euler2.9-py38-torch2.1.0-cann8.0-openmind0.6-notebook。这是一个至关重要的选择。该镜像预装了:euler2.9: 操作系统。py38: Python 3.8 解释器。torch2.1.0: PyTorch 深度学习框架。cann8.0: 昇腾 CANN 软件栈,版本为 8.0。这是连接 PyTorch 和昇腾 NPU 的桥梁。openmind0.6: 其他相关库。notebook: 预置了 Jupyter Notebook 环境。
- 存储大小:
[限时免费] 50G。50GB 的存储空间足以存放操作系统、依赖库、以及将要下载的 Gemma-7B 模型(约 17GB)。

确认配置无误后,点击“立即启动”按钮。

系统会开始准备实例,这个过程需要等待片刻。当实例状态变为“运行中”时,即可进入实例的终端环境,开始后续操作。
2.3. NPU 硬件验证
进入实例的终端后,首要任务是确认 NPU 设备是否被系统正确识别并处于正常工作状态。这可以通过昇腾提供的命令行工具 npu-smi 来完成。npu-smi (NPU System Management Interface) 是一个功能强大的工具,类似于 NVIDIA 的 nvidia-smi,用于监控和管理 NPU 设备。
执行以下命令:
npu-smi info

该命令会返回当前系统中所有 NPU 设备的详细信息。

从返回的信息中,可以解读出以下关键内容:
- Chip Info:
Chip ID: 0,设备的物理编号。Chip Name: Ascend910B-AIC_ProB,明确了 NPU 的具体型号为昇腾 910B ProB。Chip Ver.: V100,芯片版本。
- Board Info:
Board ID: 0,板卡编号。Device ID: 0,逻辑设备 ID,在 PyTorch 中通常通过npu:0来指定这块卡。
- NPU Utilization:
NPU Utili. (%): 0,NPU 的利用率,当前为 0% 表示没有计算任务在运行。
- Memory Info:
Memory (Used/Total) MB: 0 / 32768,显示了显存的使用情况。Used为 0 MB,Total为 32768 MB (即 32 GB)。这 confirms 了该 NPU 卡配备了 32 GB 的 HBM 显存。
- Power Info:
Power (W): 46.50,当前功耗。
通过 npu-smi info 的输出,可以确认 NPU 设备已成功挂载,型号正确,状态健康,为后续的模型推理奠定了硬件基础。
3. 核心软件栈安装与依赖处理
尽管基础镜像已经预装了 PyTorch 和 CANN,但运行 Gemma 2 模型还需要 Hugging Face 生态的核心库:transformers 和 accelerate。
3.1. 检查现有环境
在安装之前,先检查环境中是否已存在这些库。pip show 命令可以查看已安装包的详细信息。
# 检查 transformers
pip show transformers# 检查 accelerate
pip show accelerate

命令执行后,终端显示 WARNING: Package(s) not found: transformers, accelerate。这表明当前环境中并未预装这两个库,需要手动进行安装。
3.2. 安装 transformers 与 accelerate
使用 pip 进行安装。为了加快下载速度,这里指定使用清华大学的 PyPI 镜像源。
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers accelerate
pip install: Python 的包安装命令。-i https://pypi.tuna.tsinghua.edu.cn/simple:-i或--index-url参数用于指定包索引的 URL。这里使用国内的清华镜像,可以大幅提升下载速度,避免因网络问题导致的安装失败。transformers accelerate: 需要安装的两个包名。transformers: Hugging Face 的核心库,提供了数千个预训练模型(包括 Gemma)的接口,可以方便地下载、加载和使用这些模型。accelerate: 一个辅助库,旨在简化在不同硬件(CPU, GPU, NPU, TPU)上运行 PyTorch 代码的过程,尤其是在多卡、混合精度等复杂场景下。

然而,安装过程中出现了一个 ERROR。这是一个非常典型的 Python 包依赖冲突问题,必须解决才能继续。
3.3. 深度解析与解决依赖冲突
终端输出的错误信息非常关键:
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
mindformers 1.1.0rc1 requires tokenizers==0.15.0, but you have tokenizers 0.20.3 which is incompatible.
冲突根源分析:
- 预装的
mindformers: 容器镜像中预装了一个名为mindformers(版本1.1.0rc1) 的库。这是一个昇腾生态下的 AI 开发套件,类似于 Hugging Face Transformers,但更侧重于昇腾硬件的适配。 mindformers的严格依赖:mindformers 1.1.0rc1这个版本在其依赖声明中,严格要求tokenizers库的版本必须是0.15.0(tokenizers==0.15.0)。transformers的新依赖: 当尝试安装最新版的transformers时,它依赖于一个更新版本的tokenizers库。从安装日志中可以看到,新安装的transformers引入了tokenizers 0.20.3版本。- 冲突产生: 系统中不能同时存在两个不同版本的
tokenizers包。pip检测到mindformers要求版本0.15.0,而transformers带来了版本0.20.3,这两个要求相互矛盾,因此pip中止了安装并报告了此冲突。
解决方案:卸载冲突源 mindformers
既然本次测试的目标是使用 Hugging Face 的 transformers 生态来运行 Gemma 2,那么 mindformers 库在此次任务中并非必需。因此,最直接有效的解决方案就是卸载 mindformers,从而解除它对 tokenizers 库的版本锁定。
第一步:卸载 mindformers
执行卸载命令:
pip uninstall mindformers

终端会提示确认卸载,输入 y 并回车。此操作会从环境中移除 mindformers 包及其相关的依赖声明。
第二步:重新安装 transformers 和 accelerate
在解除了版本锁定之后,再次执行之前的安装命令:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple transformers accelerate

这一次,由于不再有 mindformers 的版本限制,pip 可以自由地为 transformers 安装其所需的 tokenizers 0.20.3 版本。安装过程顺利进行,最终显示 Successfully installed ...,表示安装成功。
第三步:验证安装结果
为了确保万无一失,再次使用 pip show 命令进行检查。
# 检查 transformers
pip show transformers# 检查 accelerate
pip show accelerate

这次,命令成功返回了 transformers 和 accelerate 的详细信息,包括版本号、依赖项等。这表明核心软件库已准备就绪。
4. 模型下载与昇腾环境适配
在正式编写推理脚本之前,还需要完成模型下载和一些昇腾环境特定的库安装。
4.1. 配置 Hugging Face 镜像加速
直接从 Hugging Face Hub 下载模型可能会因为网络问题而非常缓慢或失败。可以通过设置环境变量 HF_ENDPOINT 来指定使用镜像站点。
# Hugging Face 镜像加速配置
export HF_ENDPOINT='https://hf-mirror.com'
export: 这是 Bash shell 中的命令,用于设置或修改环境变量。HF_ENDPOINT: Hugging Face 的库(如transformers)会读取这个环境变量。如果设置了此变量,所有对 Hugging Face Hub 的 API 请求都会被重定向到这个指定的 URL,而不是默认的huggingface.co。https://hf-mirror.com: 这是一个社区维护的 Hugging Face 镜像,可以有效加速国内的访问。
此命令只在当前终端会话中有效。
4.2. 安装昇腾 NPU 适配生态库
为了让 PyTorch 模型能在昇腾 NPU 上顺利运行,还需要一些关键的适配库。
安装 modelscope:
ModelScope 是一个模型即服务的平台,其库有时也包含一些对国内硬件适配有帮助的工具。
# 安装 ModelScope 库
pip install modelscope -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade

安装 PyTorch 核心框架 (确认):
虽然镜像中已包含 PyTorch,但执行一次安装命令可以确保所有相关的依赖(如 torchvision, torchaudio)都处于最新或兼容的状态。
# 安装 PyTorch 核心框架
pip install torch torchvision torchaudio

输出 Requirement already satisfied 表明这些包已经存在且版本符合要求。
安装 torch-npu (核心):
这是最关键的昇腾适配库。它为 PyTorch 提供了 NPU 后端支持。安装了这个库之后,才能在 PyTorch 代码中使用 .to('npu:0') 将张量和模型移动到昇腾 NPU 上进行计算。
# 安装昇腾 NPU 的 PyTorch 适配库
pip install torch-npu

同样,输出 Requirement already satisfied 表示镜像中已正确预装。
再次安装 transformers (确认):
这是一次冗余但无害的操作,确保环境的一致性。
# 安装 transformers 库
pip install transformers accelerate -i https://pypi.tuna.tsinghua.edu.cn/simple

4.3. Gemma 2 模型下载
模型下载是资源准备的最后一步。由于 gemma-7b-it 是受保护模型,下载前需要获取 Hugging Face 的访问令牌 (Access Token)。
获取 API Token:
访问 Hugging Face 官网的个人设置页面 (https://huggingface.co/settings/tokens),生成一个具有 read 权限的 API Token。

编写模型下载脚本:
为了方便管理,可以创建一个 Python 脚本来执行下载操作。这里创建一个名为 test.py 的文件。
from transformers import AutoModelForCausalLM# 模型核心配置
model_name = 'google/gemma-7b-it'
auth_token = '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' # 此处替换为自己的Token# 仅执行模型下载(自动缓存到本地)
try:print(f'开始下载模型:{model_name}(首次下载约17GB)')AutoModelForCausalLM.from_pretrained(model_name,torch_dtype='auto',low_cpu_mem_usage=True,trust_remote_code=True,token=auth_token)print('✅ 模型下载完成(已缓存至本地)')
except Exception as e:print(f'❌ 下载失败:{str(e)}')
脚本代码解析:
from transformers import AutoModelForCausalLM: 从transformers库导入AutoModelForCausalLM类。这是一个工厂类,可以根据指定的模型名称自动加载相应的模型架构。model_name = 'google/gemma-7b-it': 指定要下载的模型在 Hugging Face Hub 上的唯一标识符。auth_token: 存储从 Hugging Face 获取的访问令牌。AutoModelForCausalLM.from_pretrained(...): 这是下载和加载模型的核心函数。model_name: 传入模型标识符。torch_dtype='auto': 让transformers自动选择最佳的数据类型(如float16或bfloat16)来加载模型权重,以节省显存。low_cpu_mem_usage=True: 这是一个非常重要的优化参数。当设置为True时,transformers会在加载模型时尽量减少 CPU 内存的峰值占用。它会先在硬盘上创建一个空的模型结构,然后逐个将权重文件直接加载到指定的设备(如此处默认为 NPU)上,而不是先在 CPU 内存中完整加载一遍再转移。这对于 CPU 内存小于模型大小的系统至关重要。trust_remote_code=True: 某些模型在其 Hub 仓库中包含了自定义的 Python代码。此参数表示信任并允许执行这些远程代码。对于官方发布的模型如 Gemma,这是安全的。token=auth_token: 将访问令牌传递给函数,用于身份验证,从而获得下载受保护模型的权限。
执行下载:
在终端中运行此 Python 脚本。
python test.py

脚本启动后,会开始下载模型的配置文件、分词器文件以及最重要的模型权重文件。

上图展示了模型权重文件的下载进度。gemma-7b-it 模型被分成了 4 个 .safetensors 格式的分片文件,每个文件大小约 4.9 GB。.safetensors 是一种更安全、更快速的模型权重存储格式。下载过程会持续一段时间,具体取决于网络状况。下载完成后,所有文件会被缓存在默认路径(通常是 ~/.cache/huggingface/hub)下,后续加载将直接从本地缓存读取,无需再次下载。
至此,所有的环境准备和资源下载工作均已完成。接下来将进入核心的性能评测阶段。
5. 深度性能评测脚本全面解析
为了对 Gemma 7B 在昇腾 NPU 上的性能进行全面、系统、可复现的评估,需要编写一个专业的测试脚本。该脚本 (pro_test_gemma.py) 的设计目标不仅仅是简单地运行模型,而是要从多个能力维度、两种不同的生成场景出发,收集并报告详尽的性能指标。
在终端中使用 vi 或其他编辑器创建脚本文件:
vi pro_test_gemma.py
将以下 Python 代码完整粘贴到文件中。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Gemma 7B 昇腾NPU推理测试脚本 (V2.0 - 多场景、多维度深度测试版)特点:
✅ 扩展至10个能力维度,每维度5题
✅ 引入“确定性”与“创造性”两种测试场景,采用不同生成策略
✅ 动态调整不同任务的生成长度
✅ 规整的表格化输出,包含详细数据指标(耗时、显存、tokens)
✅ 增加环境信息、维度级统计与最终多维度汇总报告
"""import torch
import torch_npu
import time
import os
from transformers import AutoModelForCausalLM, AutoTokenizer
from statistics import mean
from collections import defaultdictdef print_separator(title, char="=", length=90):"""打印格式化的分隔符标题"""print(f"\n{char * length}")print(f"{title.center(length)}")print(f"{char * length}")def print_environment_info(device):"""打印关键的环境和硬件信息"""print_separator("1️⃣ 环境与模型加载")print(f"🔹 PyTorch Version: {torch.__version__}")print(f"🔹 Torch NPU Version: {torch_npu.__version__}")print(f"🔹 Device: {device}")try:device_name = torch.npu.get_device_name(device)print(f"🔹 NPU Name: {device_name}")except Exception as e:print(f"🔹 NPU Name:无法获取 ({e})")print(f"🔹 Initial Memory: {torch.npu.memory_allocated(device)/1e9:.2f} GB")print(f"🔹 Peak Memory (History): {torch.npu.max_memory_allocated(device)/1e9:.2f} GB")def test_model_capability(model, tokenizer, device, prompt, test_name, gen_config):"""统一的推理测试函数,带详细的性能指标和错误处理"""try:# Tokenizeinputs = tokenizer(prompt, return_tensors="pt", truncation=True, max_length=1024).to(device)input_tokens = len(inputs["input_ids"][0])# Inferencestart_time = time.time()with torch.no_grad():outputs = model.generate(**inputs, **gen_config)end_time = time.time()# 统计信息gen_time = end_time - start_timetotal_tokens = len(outputs[0])gen_tokens = total_tokens - input_tokensspeed = gen_tokens / gen_time if gen_time > 0 else 0mem_used = torch.npu.memory_allocated(device) / 1e9# 输出文本# 使用切片方式获取生成部分,避免重复显示输入generated_text = tokenizer.decode(outputs[0][input_tokens:], skip_special_tokens=True)preview = generated_text.replace("\n", " ").strip()preview = preview[:150] + ("..." if len(preview) > 150 else "")# 控制台打印结果print(f"【测试】{test_name}")print(f" ➤ 输入Token: {input_tokens:>4} | 生成Token: {gen_tokens:>4} | 总Token: {total_tokens:>4}")print(f" ➤ 耗时: {gen_time:>6.2f}s | 速度: {speed:>7.2f} tok/s | 显存: {mem_used:.2f} GB")print(f" ➤ 生成结果预览: {preview}\n")return {"success": True, "time": gen_time, "speed": speed, "tokens": gen_tokens}except Exception as e:print(f"【测试】{test_name} ❌ 失败:{str(e)}\n")return {"success": False, "time": 0, "speed": 0, "tokens": 0}def run_dimension(model, tokenizer, device, dimension_name, prompts, gen_config):"""执行一个维度下的所有测试题"""print_separator(f"维度测试: {dimension_name}(共{len(prompts)}题)", "-")results = []for idx, prompt in enumerate(prompts, 1):test_name = f"{dimension_name}-{idx}"result = test_model_capability(model, tokenizer, device, prompt, test_name, gen_config)results.append(result)# 汇总统计success_results = [r for r in results if r["success"]]if not success_results:print(f"❌ [{dimension_name}] 全部失败!\n")return results, {"success_rate": 0, "avg_time": 0, "avg_speed": 0}success_rate = len(success_results) / len(results) * 100avg_speed = mean(r["speed"] for r in success_results)avg_time = mean(r["time"] for r in success_results)print(f"✅ [{dimension_name}] 维度小结: 成功率: {success_rate:.1f}% | 平均耗时: {avg_time:.2f}s | 平均速度: {avg_speed:.2f} tok/s\n")summary = {"dimension": dimension_name,"success_rate": success_rate,"avg_time": avg_time,"avg_speed": avg_speed}return results, summarydef print_final_summary(report_data, start_mem):"""打印格式化的最终汇总报告"""print_separator("📊 最终汇总报告")# 打印表头header = f"| {'维度名称':<14} | {'测试场景':<12} | {'成功率':<7} | {'平均速度(tok/s)':<16} | {'平均耗时(s)':<12} |"print(header)print(f"|{'-'*16}|{'-'*14}|{'-'*9}|{'-'*18}|{'-'*14}|")# 打印每个维度的结果total_tests = 0total_success = 0all_speeds = []all_times = []for item in report_data:print(f"| {item['dimension']:<15}| {item['scenario']:<13}| {item['summary']['success_rate']:>5.1f}% | {item['summary']['avg_speed']:>17.2f} | {item['summary']['avg_time']:>13.2f} |")total_tests += len(item['results'])total_success += sum(r['success'] for r in item['results'])all_speeds.extend([r['speed'] for r in item['results'] if r['success']])all_times.extend([r['time'] for r in item['results'] if r['success']])print(f"|{'-'*16}|{'-'*14}|{'-'*9}|{'-'*18}|{'-'*14}|")# 计算总计overall_success_rate = (total_success / total_tests * 100) if total_tests > 0 else 0overall_avg_speed = mean(all_speeds) if all_speeds else 0overall_avg_time = mean(all_times) if all_times else 0print("\n--- 总体性能摘要 ---")print(f"🧩 总测试题数: {total_tests}")print(f"✅ 成功题数: {total_success} ({overall_success_rate:.1f}%)")print(f"⚙️ 平均推理速度: {overall_avg_speed:.2f} tokens/秒")print(f"⏱️ 平均推理耗时: {overall_avg_time:.2f} 秒")print(f"💾 模型加载显存: {start_mem:.2f} GB")print(f"📦 当前显存占用: {torch.npu.memory_allocated()/1e9:.2f} GB")print(f"📈 峰值显存占用: {torch.npu.max_memory_allocated()/1e9:.2f} GB (自脚本运行以来)")def main():# --- 配置区 ---auth_token = "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" # 您的Hugging Face Tokenmodel_name = "google/gemma-7b-it"device = "npu:0"cache_dir = "/home/service/.cache/huggingface/hub" # 模型存放的根目录, 请根据实际情况修改os.environ["TRANSFORMERS_CACHE"] = cache_diros.environ["ASCEND_SKIP_CPU_FALLBACK_WARNING"] = "1"os.environ["PYTHONWARNINGS"] = "ignore::UserWarning:torch_npu.utils.path_manager"print("=" * 90)print("Gemma 7B 昇腾NPU推理能力详细测试报告 V2.0".center(90))print("=" * 90)# 打印环境信息print_environment_info(device)# --- 模型加载 ---try:tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True, cache_dir=cache_dir, token=auth_token)model = AutoModelForCausalLM.from_pretrained(model_name,torch_dtype=torch.float16,low_cpu_mem_usage=True,trust_remote_code=True,cache_dir=cache_dir,token=auth_token).to(device).eval()start_mem_usage = torch.npu.memory_allocated(device) / 1e9print(f"\n✅ 模型已成功加载至 {device}, 占用显存: {start_mem_usage:.2f} GB")except Exception as e:print(f"\n❌ 模型加载失败: {e}")return# --- 测试场景与数据定义 ---TEST_SCENARIOS = {"确定性与事实性测试": {"gen_config": {"max_new_tokens": 128, # 对于事实性问题,答案通常不需要太长"min_new_tokens": 10,"do_sample": False,"temperature": 0.0,"pad_token_id": tokenizer.eos_token_id},"dimensions": {# ... [此处省略具体的 prompt 列表,与脚本中一致] ...}},"创造性与指令遵循测试": {"gen_config": {"max_new_tokens": 256, # 创造性任务需要更长的生成空间"min_new_tokens": 50,"do_sample": True,"temperature": 0.7,"top_p": 0.9,"pad_token_id": tokenizer.eos_token_id},"dimensions": {# ... [此处省略具体的 prompt 列表,与脚本中一致] ...}}}# --- 执行测试 ---final_report_data = []for scenario_name, scenario_data in TEST_SCENARIOS.items():print_separator(f"场景开始: {scenario_name}")gen_config = scenario_data["gen_config"]print(f" > 生成策略: do_sample={gen_config['do_sample']}, max_tokens={gen_config['max_new_tokens']}")for dim_name, prompts in scenario_data["dimensions"].items():results, summary = run_dimension(model, tokenizer, device, dim_name, prompts, gen_config)final_report_data.append({"scenario": scenario_name.split('测试')[0], # 简化场景名"dimension": dim_name,"results": results,"summary": summary})# --- 最终报告 ---print_final_summary(final_report_data, start_mem_usage)print("\n" + "=" * 90)print("✨ 所有测试完成,报告已生成 ✨".center(90))print("=" * 90)if __name__ == "__main__":main()
5.1. 脚本设计理念与结构
该脚本的核心设计思想是模块化和数据驱动。
- 配置区 (
main函数开头): 将所有可变参数(如模型名称、设备 ID、Token)集中放置,便于修改和复用。 - 功能函数: 将特定功能(如打印环境信息、执行单次推理、运行一个维度的测试、打印最终报告)封装成独立的函数,使代码结构清晰,逻辑分明。
- 测试数据结构: 使用嵌套的字典
TEST_SCENARIOS来组织所有的测试用例。这种结构使得增加新的测试场景或维度变得非常简单,只需在字典中添加新的条目即可。
5.2. 核心功能函数剖析
-
print_environment_info(device):- 目的:在测试开始前,展示关键的软硬件环境信息,确保测试环境的透明性。
- 实现:通过
torch.__version__获取 PyTorch 版本,torch_npu.__version__获取昇腾适配库版本,torch.npu.get_device_name获取 NPU 型号。使用torch.npu.memory_allocated记录初始显存占用,为后续分析提供基线。
-
test_model_capability(...):- 目的:这是执行单次推理并收集所有性能指标的核心函数。
- 流程:
- Tokenize: 使用
tokenizer将输入的文本prompt转换为模型可以理解的数字 ID (tokens),并将其移动到 NPU 设备。 - Inference: 使用
time.time()精确计时,在torch.no_grad()上下文中执行model.generate()。torch.no_grad()会禁用梯度计算,这是推理阶段的标准做法,可以减少计算量和显存占用。**gen_config将生成参数(如max_new_tokens)动态传入。 - 统计信息计算: 计算推理耗时、生成 token 数量、推理速度 (tokens/second) 以及当前的 NPU 显存占用。
- 解码与输出: 使用
tokenizer.decode()将模型生成的 token ID 转换回人类可读的文本,并打印出关键的性能数据和生成结果的预览。 - 返回结果: 将本次测试的成功状态和所有性能指标封装在一个字典中返回。
- Tokenize: 使用
-
run_dimension(...):- 目的:组织并执行一个完整能力维度下的所有测试题(例如,“逻辑推理”维度下的 5 道题)。
- 流程:遍历该维度下的所有
prompts,依次调用test_model_capability函数,并收集结果。测试完成后,计算该维度的成功率、平均耗时和平均速度,并打印维度小结。
-
print_final_summary(...):- 目的:在所有测试结束后,以规整的表格形式展示最终的汇总报告。
- 实现:遍历所有维度的测试结果,格式化输出,并计算总体的平均性能指标和最终的显存使用情况。
5.3. 测试场景与生成策略设计
脚本的最大亮点在于定义了两种截然不同的测试场景,以模拟模型在不同应用中的工作模式。
-
确定性与事实性测试 (Deterministic Scenario):
- 适用任务: 基础问答、逻辑推理、代码生成、数学计算等,这些任务追求唯一、正确、可预测的答案。
- 生成策略 (
gen_config):do_sample=False: 关闭采样。模型在生成下一个 token 时,总是选择概率最高的那一个(贪心搜索)。这使得输出是确定性的。temperature=0.0: 将温度设置为 0 进一步强化了确定性。max_new_tokens=128: 对于这类问题,答案通常比较简短,限制生成长度可以避免不必要的计算。
-
创造性与指令遵循测试 (Creative Scenario):
- 适用任务: 创意写作、角色扮演、多语言处理等,这些任务鼓励多样化、富有想象力的输出。
- 生成策略 (
gen_config):do_sample=True: 开启采样。模型会根据概率分布来随机选择下一个 token,而不是永远选择概率最高的。temperature=0.7: 温度大于 0,使得低概率的 token 也有机会被选中,增加了生成文本的随机性和创造性。0.7 是一个常用的平衡值。top_p=0.9: 采用 Top-p (Nucleus) 采样。在采样时,只考虑累积概率达到 90% 的最高概率 token 集合,从中进行随机选择。这可以在保证多样性的同时,避免选到过于离谱的 token。max_new_tokens=256: 创造性任务通常需要更长的文本来充分表达,因此设定了更大的生成长度。
通过这两种场景的设计,评测不仅能衡量模型的原始计算速度,还能揭示不同解码策略对性能的影响。
6. 推理性能实测结果与深度分析
在终端中执行评测脚本:
python pro_test_gemma.py

脚本将开始逐一执行所有测试用例,并实时打印结果。
6.1. 逐项测试过程展示
以下是脚本运行时,各个测试维度的部分输出截图,展示了详细的单项测试结果和维度小结。
场景一:确定性与事实性测试
-
维度测试: 基础问答

该维度测试模型对基本概念的理解和表述能力。可以看到,模型能够准确回答问题,平均速度达到了 17.65 tok/s。 -
维度测试: 逻辑推理

测试模型的简单逻辑判断能力。由于答案通常很短,平均耗时仅为 2.72s,速度为 17.92 tok/s。 -
维度测试: 知识准确性

检验模型内部知识库的准确性。平均速度为 18.23 tok/s。 -
维度测试: 代码生成

测试生成标准算法的 Python 代码。性能表现出色,平均速度 18.27 tok/s。 -
维度测试: 文本摘要

测试模型对长文本的理解和概括能力。这是确定性场景下速度最快的维度,达到 18.36 tok/s。 -
维度测试: 数学应用

测试基础的数学问题求解能力。平均速度 15.60 tok/s,相较其他确定性任务略低,可能与计算过程中的数字处理有关。
场景二:创造性与指令遵循测试
-
维度测试: 创意写作

开启采样后,速度明显下降,平均为 14.54 tok/s。这是因为采样算法比贪心搜索需要更多的计算。 -
维度测试: 多语言处理

翻译任务速度为 15.26 tok/s,同样受采样策略影响。 -
维度测试: 角色扮演

由于设定的生成长度较长(max_new_tokens=256),该维度的平均耗时最长,达到 13.87s,但速度仍保持在 15.26 tok/s。 -
维度测试: 安全合规

测试模型对有害或不道德问题的拒答能力。gemma-7b-it模型表现出良好的安全性,对不当问题均给予了合规的拒绝回答。此场景下速度为 15.31 tok/s。
6.2. 最终汇总报告与深度解读
所有测试完成后,脚本会生成一份最终的汇总报告。

这份报告是本次评测的核心产出。为了更直观地展示和分析,我们将报告数据可视化为四张图表进行深度解读。
图 1: 核心性能指标 (Core Performance Metrics)

这张图是对整个测试的最高层级总结,提供了四个关键的总体性能数据。
- Avg Inference Speed (平均推理速度): 16.63 tokens/sec
- 解读: 这是所有 50 个测试用例(10 个维度 * 5 题)的平均生成速度。它代表了 Gemma 7B 在昇腾 910B NPU 上,在混合任务负载下的综合性能表现。每秒生成约 16.6 个 token,对于一个 7B 规模的模型而言,这是一个相当不错的性能水平,能够满足多数交互式应用的需求。
- Avg Inference Time (平均推理耗时): 6.12 sec
- 解读: 平均每个请求从发出到接收到完整回复需要 6.12 秒。这个指标直接影响用户体验。需要注意的是,这个值是所有任务的平均值,包含了短答案的逻辑题和长文本的角色扮演,因此实际应用中,不同任务的耗时会有差异。
- Peak Memory Usage (峰值显存占用): 17.25 GB
- 解读: 这是整个测试过程中,NPU 显存占用的最高点。这个数值至关重要,它直接决定了部署该模型的硬件门槛。17.25 GB 的占用包括:
- 模型权重(以 float16 格式加载,7B 参数约 14 GB)。
- KV Cache(用于存储注意力机制的键值对,其大小与批处理大小和序列长度正相关)。
- 中间计算结果和框架开销。
- 结论: 部署
gemma-7b-it模型进行推理,至少需要一张显存大于 17.25 GB 的计算卡。昇腾 910B 的 32GB 显存对此绰绰有余,甚至有空间运行更大的批处理量或更长的序列。
- 解读: 这是整个测试过程中,NPU 显存占用的最高点。这个数值至关重要,它直接决定了部署该模型的硬件门槛。17.25 GB 的占用包括:
- Test Success Rate (测试成功率): 100.0 %
- 解读: 所有测试用例都成功执行,没有发生任何运行时错误(如 CUDA out of memory、算子不支持等)。这表明
torch-npu库对transformers和 Gemma 模型的算子支持是完整和稳定的,昇腾软硬件栈的成熟度很高。
- 解读: 所有测试用例都成功执行,没有发生任何运行时错误(如 CUDA out of memory、算子不支持等)。这表明
图 2: 模型能力雷达图 (Capability Radar Chart)

这张雷达图以推理速度为度量,直观地展示了模型在 10 个不同能力维度上的性能分布,用于评估其处理不同任务的性能均衡性。
- 形状分析: 图中的多边形形状相对规整,没有出现极端凹陷或凸起。这说明 Gemma 7B 在昇腾 NPU 上的性能表现是相当均衡的,没有在某个特定类型的任务上出现严重的性能瓶颈。
- 半径分析 (性能强项与弱项):
- 优势区域 (半径较大): Summarization (文本摘要), Knowledge (知识问答), 和 Code Generation (代码生成) 这三个维度的推理速度最快,均超过了 18 tokens/sec。这些任务都属于“确定性”场景,采用贪心搜索策略,计算效率最高。
- 相对较慢区域 (半径较小): Creative Writing (创意写作) 的速度最慢(14.54 tok/s),其次是 Multilingual (多语言处理) 和 Role-playing (角色扮演)。这些任务都属于“创造性”场景,采用了
do_sample=True的采样策略。采样过程涉及从一个概率分布中抽样,相比直接选取最大概率的贪心策略,计算上更为复杂,因此导致了速度的下降。
图 3: 各维度性能对比条形图 (Performance Comparison Bar Charts)

这张图将雷达图的数据用条形图的形式展现,提供了更精确的数值比较。
- 上半部分: Inference Speed (推理速度对比)
- 作用: 清晰地展示了 10 个维度的速度排序。可以精确地看到,速度从最高的“文本摘要”(18.36 tok/s)平滑地过渡到最低的“创意写作”(14.54 tok/s)。这种可视化方式比雷达图更能进行精确的横向比较。
- 下半部分: Average Inference Time (平均耗时对比)
- 作用: 这部分揭示了一个与速度不完全一致的有趣现象。
- 最耗时任务: Role-playing (角色扮演) 耗时最长,达到 13.87 秒。其原因并非速度慢(其速度为 15.26 tok/s,处于中等水平),而是因为该任务被设定为生成更长的文本 (
max_new_tokens=256),总的生成 token 数量多,导致总耗时增加。 - 最省时任务: Logical Reasoning (逻辑推理) 耗时最短,仅 2.72 秒。这是因为它通常只需要一个非常简短的答案,生成的 token 数量很少。
- 最耗时任务: Role-playing (角色扮演) 耗时最长,达到 13.87 秒。其原因并非速度慢(其速度为 15.26 tok/s,处于中等水平),而是因为该任务被设定为生成更长的文本 (
- 结论: 评估用户体验时,需要同时考虑推理速度 (tok/s) 和总耗时 (s)。速度决定了模型“吐字”的快慢,而总耗时由“速度”和“要说的话的长度”共同决定。
- 作用: 这部分揭示了一个与速度不完全一致的有趣现象。
图 4: 不同场景平均速度对比 (Scenario Speed Comparison)

这张图从更高的维度——生成策略——来分析模型的性能差异,揭示了底层算法对性能的直接影响。
- Creative (创造性场景): 15.09 tokens/sec
- 场景: 包括创意写作、多语言、角色扮演和安全合规这四个维度。
- 技术核心: 使用采样解码策略 (
do_sample=True,temperature=0.7,top_p=0.9)。这种策略为了生成多样化和非确定性的文本,需要在每一步都进行一次基于概率分布的随机抽样,计算开销相对较大。
- Deterministic (确定性场景): 17.67 tokens/sec
- 场景: 包括基础问答、逻辑、知识、代码、摘要和数学这六个维度。
- 技术核心: 使用贪心解码策略 (
do_sample=False)。这种策略在每一步都直接选择概率最高的 token,计算路径唯一,没有任何随机性,因此执行效率更高。
性能差异分析:
确定性场景的平均速度比创造性场景快了约 17.1% ((17.67 - 15.09) / 15.09 ≈ 0.171)。这是一个非常重要的性能洞察,它量化了不同解码策略带来的性能开销。在对性能要求极致的应用中,如果任务性质允许,优先选择确定性解码策略可以获得显著的速度提升。
7. 总结与展望
本次基于昇腾 910B NPU 的 Gemma 2 (7B-it) 模型推理实测,系统性地完成了从环境配置、依赖解决、模型部署到多维度性能评测的全流程。测试结果表明:
-
硬件性能强劲: 昇腾 910B NPU 能够流畅、高效地运行 70 亿参数规模的 Gemma 2 模型,平均推理速度达到 16.63 tokens/sec,峰值显存占用为 17.25 GB,展示了其作为高性能 AI 推理硬件的强大实力。
-
生态适配成熟: 整个测试过程,从
torch-npu的无缝对接到transformers库的完美兼容,均未出现算子不支持或兼容性问题,测试成功率达到 100%。这证明了昇腾 CANN 软件栈与主流 AI 开源生态的适配已经相当成熟和稳定。 -
性能表现均衡且可量化: 模型在处理十种不同类型的任务时,性能表现均衡。通过对“确定性”和“创造性”两种场景的对比测试,精确量化了不同解码策略对性能的影响——贪心解码比采样解码快约 17%。这为实际应用中的性能优化提供了明确的数据支持。
综上所述,昇腾 NPU 平台完全具备承载和高效运行如 Gemma 2 等前沿大语言模型的能力。此次实测不仅验证了硬件的性能,更展现了其软件生态的健壮性。随着国产 AI 硬件的不断迭代和软件生态的持续完善,未来将有能力为日益复杂和庞大的 AI 模型提供坚实的算力底座。
8. 附录:相关资源链接
- 昇腾官网: https://www.hiascend.com/
- 昇腾社区: https://www.hiascend.com/community
- 昇腾官方文档: https://www.hiascend.com/document
- 昇腾开源仓库: https://gitcode.com/ascend
- 昇腾技术白皮书: https://www.hiascend.com/document/detail/zh/ascend-computing/ascend-cluster/index.html
