标杆数据生成工具

查看源文件

概述

在对 MindSpore Lite 模型进行基准测试前,开发者可以按照约定格式生成标杆数据(Benchmark Data)。基于生成的标杆数据运用benchmark工具进行基准测试,能够对原始模型和转换后的模型精度进行定量分析。

mslite_gold标杆数据生成工具,可基于原始模型输入数据input.npz和推理得到的输出数据output.npz生成标杆数据,本文介绍该工具的用法。

mslite_gold工具使用说明

开发者首先需要将原始模型输入数据和推理得到的输出数据,通过numpy中的savez()命令保存为.npz格式的文件,再通过运行mslite_gold.py 分别将输入数据input.npz和输出数据output.npz转化为.bin.out的二进制格式文件。

环境要求

python依赖库

  • numpy >= 2.0.2

  • onnx >= 1.17.0

  • onnxruntime >= 1.19.2

  • ast >= 1.6.3

  • collection >= 0.1.6

使用示例

python mslite_gold.py --inputFile "/path/to/input.npz" --outputFile "/path/to/output.npz" --savePath "/path/to/save_data"

执行命令后,会在/path/to/save_data/目录中生成如下文件:

  • input.bin:输入数据,对每个输入Tensor的数据进行flatten一维化,单独保存到一个二进制文件input.bin,不含名称、dtype、shape等元信息。

  • output.out:输出数据,所有输出内容保存到一个文本文件,格式如下:

每个输出Tensor占用2行:

name dim shape1 [shape2 ...]
data0 data1 ...
  • 第一行:记录输出Tensor的元信息,依次为:名称、维度、形状

  • 第二行:记录输出Tensor的数据。

示例:

out_0 2 2 3
1.0 2.0 3.0 4.0 5.0 6.0

表示一个名称为out_0,维度是2维,形状是[2, 3],内容是[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]的Tensor。

下面以ONNX模型生成标杆数据为例,详细介绍工具的用法。

  1. 随机生成输入,进行模型推理,再将输入输出保存为.npz格式。

    onnx_demo.py示例代码 支持基于ONNX模型随机生成数据,或手动输入数据,并执行推理获得输出数据。手动输入数据时,可以通过参数--inDataFile来确定输入数据路径。如果模型是动态shape类型,需通过参数--inputShape来确定输入尺寸。参数--inDataFile--inputShape非必须,用户可以根据自身的使用场景来自由选用。下面是示例代码的基础使用示例:

     python onnx_demo.py --modelFile "/path/to/model_example.onnx" --savePath "/path/to/data_example"
    

    /path/to/data_example/目录中会生成input.npzoutput.npz文件。

  2. 将输入输出的npz文件转化成标杆数据文件。

    python mslite_gold.py --inputFile "/path/to/data_example/input.npz" --outputFile "/path/to/data_example/output.npz" --savePath "/path/to/save_data"
    

    最后,在/path/to/save_data目录中会生成上述的标杆数据文件。

mslite_gold工具代码细节

以下展示标杆数据生成的代码细节,先转换input,再转换output。

import os
import numpy as np
from collections import OrderedDict

def save_bin(args):
    try:
        input_dict = np.load(args.inputFile)
        print(f"Loaded inputs from {args.inputFile}: {list(input_dict.keys())}")
    except Exception as e:
        print(f"Error loading inputs: {e}")
        return
    i = 0
    input_dict=OrderedDict(input_dict)
    for key , input_data in input_dict.items():
        print(f"input {key}: shape={input_data.shape}, dtype={input_data.dtype}")
        if np.issubdtype(input_data.dtype, np.integer):
            input_data.astype(np.int32).flatten().tofile(os.path.join(args.savePath, f"input.bin{i}"))
        else:
            input_data.flatten().tofile(os.path.join(args.savePath, f"input.bin{i}"))
        i = i + 1

    try:
        output_dict = np.load(args.outputFile)
        print(f"Loaded outputs from {args.outputFile}: {list(output_dict.keys())}")
    except Exception as e:
        print(f"Error loading outputs: {e}")
        return

    opened = 0
    output_dict = OrderedDict(output_dict)
    output_file = os.path.join(args.savePath, 'model.out')
    for i , output_data in output_dict.items():
        print(f"output {i}: shape={output_data.shape}, dtype={output_data.dtype}")
        mode = 'w' if opened == 0 else 'a'
        if str(output_data.shape) == "[]":
            output_shape = [1]
        else:
            output_shape = output_data.shape

        with open(output_file, mode) as text_file:
            opened = 1
            if len(output_shape) == 0:
                output_shape.append(len(output_data))

            text_file.write(f"{i} {len(output_data.shape)} ")
            text_file.write(" ".join([str(s) for s in output_data.shape]))
            text_file.write('\n')
            print(f"result shape: {len(output_data.flatten())}")

            for k in output_data.flatten():
                text_file.write(f"{k} ")
            text_file.write('\n')