数据结构

以下数据结构用于ONNX模型的操作:

OnnxTypeInfo #

该结构描述了ONNX模型的输入输出参数的类型

struct OnnxTypeInfo
 {
  ENUM_ONNX_TYPE        type;          // 参数类型
  OnnxTensorTypeInfo    tensor;        // 张量描述
  OnnxMapTypeInfo       map;           // 映射描述
  OnnxSequenceTypeInfo  sequence;      // 序列描述
 };

只有张量(ONNX_TYPE_TENSOR)可以作为输入使用。在这种情况下,只有OnnxTypeInfo::tensor字段被填充值,而其他字段(映射和序列)没有定义。

三种OnnxTypeInfo类型(ONNX_TYPE_TENSOR、ONNX_TYPE_MAP或ONNX_TYPE_SEQUENCE)中只有一种可以作为输入使用。相对应的子结构(OnnxTypeInfo::tensor、OnnxTypeInfo::map或OnnxTypeInfo::sequence)根据类型来填充。

 

OnnxTensorTypeInfo

该结构描述了ONNX模型的输入输出参数中的张量

struct OnnxTensorTypeInfo
 {
  const ENUM_ONNX_DATA_TYPE  data_type;      // 张量中的数据类型
  const long                 dimensions[];   // 张量中的元素数
 };

OnnxMapTypeInfo #

该结构描述了ONNX模型的输出参数中获得的映射

struct OnnxMapTypeInfo
 {
  const ENUM_ONNX_DATA_TYPE  key_type;      //密钥类型
  const OnnxTypeInfo&        value_type;    // 值类型
 };

OnnxSequenceTypeInfo #

该结构描述了ONNX模型的输出参数中获得的序列

struct OnnxSequenceTypeInfo
 {
  const OnnxTypeInfo&        value_type;     // 序列中的数据类型
 };

 

 

ENUM_ONNX_TYPE #

ENUM_ONNX_TYPE枚举描述了模型参数的类型

ID

描述

ONNX_TYPE_UNKNOWN

未知

ONNX_TYPE_TENSOR

Tensor

ONNX_TYPE_SEQUENCE

Sequence

ONNX_TYPE_MAP

Map

ONNX_TYPE_OPAQUE

Abstract (opaque)

ONNX_TYPE_SPARSETENSOR

Sparse tensor

ENUM_ONNX_DATA_TYPE #

ENUM_ONNX_DATA_TYPE枚举描述了所用数据的类型

ID

描述

ONNX_DATA_TYPE_UNDEFINED

未定义

ONNX_DATA_TYPE_FLOAT

浮点型

ONNX_DATA_TYPE_INT8

8位整型

ONNX_DATA_TYPE_UINT16

16位无符号整型

ONNX_DATA_TYPE_INT16

16位整型

ONNX_DATA_TYPE_INT32

32位整型

ONNX_DATA_TYPE_INT64

64位整型

ONNX_DATA_TYPE_STRING

字符串

ONNX_DATA_TYPE_BOOL

布尔型

ONNX_DATA_TYPE_FLOAT16

16位浮点型

ONNX_DATA_TYPE_DOUBLE

双精度

ONNX_DATA_TYPE_UINT32

32位无符号整型

ONNX_DATA_TYPE_UINT64

64位无符号整型

ONNX_DATA_TYPE_COMPLEX64

64位复数

ONNX_DATA_TYPE_COMPLEX128

128位复数

ONNX_DATA_TYPE_BFLOAT16

16位bfloat(大脑浮点)

 

ENUM_ONNX_FLAGS #

ENUM_ONNX_FLAGS枚举描述了模型的运行模式

ID

描述

ONNX_LOGLEVEL_VERBOSE

记录所有消息

ONNX_LOGLEVEL_INFO

记录信息消息、警告和错误(此标志替换 ONNX_DEBUG_LOGS)

ONNX_LOGLEVEL_WARNING

记录警告和错误(默认)

ONNX_LOGLEVEL_ERROR

仅记录错误

ONNX_NO_CONVERSION

禁用自动转换,按原样使用用户数据

ONNX_COMMON_FOLDER  

从 Common\Files 文件夹载入一个模型文件; 该值等于FILE_COMMON标志

ONNX_USE_CPU_ONLY

仅使用 CPU 执行 ONNX 模型

ONNX_GPU_DEVICE_0

索引为 0 的 CUDA 设备(默认)

ONNX_GPU_DEVICE_1

索引为 1 的 CUDA 设备 *

ONNX_GPU_DEVICE_2

索引为 2 的 CUDA 设备 *

ONNX_GPU_DEVICE_3

索引为 3 的 CUDA 设备 *

ONNX_GPU_DEVICE_4

索引为 4 的 CUDA 设备 *

ONNX_GPU_DEVICE_5

索引为 5 的 CUDA 设备 *

ONNX_GPU_DEVICE_6

索引为 6 的 CUDA 设备 *

ONNX_GPU_DEVICE_7

索引为 7 的 CUDA 设备 *

ONNX_ENABLE_PROFILING

启用 ONNX 模型分析

* ONNX_GPUD_N 形式的标志应在具有两个或多个 CUDA 功能 GPU 的系统上使用。如果指定了多个 GPU 选择标志,则将使用索引最低的设备。

如果指定了不存在的设备索引,则 GPU 将被自动选择。

 

ONNX 分析

ONNX_ENABLE_PROFILING 标志允许对 ONNX 模型执行进行分析。当设置了此标志设置时,会在以下目录创建分析报告文件:<data_folder>/MQL5/Files/OnnxProfileReports, 文件名的格式如下: <module_name>_date_time.json.

此处的 <module_name> 是 MQL 程序 EX5 文件的名称。

该文件包含 JSON 格式的详细 ONNX 模型执行分析报告,包括:

  • 会话加载和初始化时间;
  • 单个图节点(Conv、Relu、MaxPool、Gemm 等)的执行时间;
  • 使用的执行提供程序(例如 CUDAExecutionProvider);
  • 输入和输出张量大小信息;
  • 线程调度统计。

 

分析报告数据的示例:

{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :698,"ts" :11,"ph" : "X","name" :"model_loading_array","args" : {}},
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :15496,"ts" :869,"ph" : "X","name" :"session_initialization","args" : {}},
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :66055,"ts" :16800,"ph" : "X","name" :"Convolution28_kernel_time","args" : {"parameter_size" : "832","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,1,28,28]},{"float
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :775,"ts" :82867,"ph" : "X","name" :"ReLU32_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,8,28,28]}],"node_index" : "3
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :8818,"ts" :83647,"ph" : "X","name" :"Pooling66_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,8,28,28]}],"node_inde
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :1120,"ts" :92476,"ph" : "X","name" :"Convolution110_kernel_time","args" : {"parameter_size" : "12864","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,8,14,14]},{"flo
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :23,"ts" :93603,"ph" : "X","name" :"ReLU114_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,16,14,14]}],"node_index" : "
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :21,"ts" :93629,"ph" : "X","name" :"Pooling160_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,16,14,14]}],"node_inde
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :16,"ts" :93654,"ph" : "X","name" :"Times212_reshape0_kernel_time","args" : {"parameter_size" : "16","provider" : "CUDAExecutionProvider","op_name" : "Reshape","input_type_shape" : [{"float":[1,16,4,4]},{"int
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :32264,"ts" :93673,"ph" : "X","name" :"Times212/MatMulAddFusion_kernel_time","args" : {"parameter_size" : "10280","provider" : "CUDAExecutionProvider","op_name" : "Gemm","input_type_shape" : [{"float":[1,256]
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :109165,"ts" :16794,"ph" : "X","name" :"SequentialExecutor::Execute","args" : {}},
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :109600,"ts" :16433,"ph" : "X","name" :"model_run","args" : {}},
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :87,"ts" :126313,"ph" : "X","name" :"Convolution28_kernel_time","args" : {"parameter_size" : "832","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,1,28,28]},{"float":
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :23,"ts" :126403,"ph" : "X","name" :"ReLU32_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,8,28,28]}],"node_index" : "3
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :31,"ts" :126431,"ph" : "X","name" :"Pooling66_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,8,28,28]}],"node_index
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :35,"ts" :126466,"ph" : "X","name" :"Convolution110_kernel_time","args" : {"parameter_size" : "12864","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,8,14,14]},{"floa
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :15,"ts" :126505,"ph" : "X","name" :"ReLU114_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,16,14,14]}],"node_index" : 
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :22,"ts" :126523,"ph" : "X","name" :"Pooling160_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,16,14,14]}],"node_ind
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :12,"ts" :126548,"ph" : "X","name" :"Times212_reshape0_kernel_time","args" : {"parameter_size" : "16","provider" : "CUDAExecutionProvider","op_name" : "Reshape","input_type_shape" : [{"float":[1,16,4,4]},{"in
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :40,"ts" :126562,"ph" : "X","name" :"Times212/MatMulAddFusion_kernel_time","args" : {"parameter_size" : "10280","provider" : "CUDAExecutionProvider","op_name" : "Gemm","input_type_shape" : [{"float":[1,256]},

 

有关 ONNX 分析的其他信息: https://onnxruntime.ai/docs/performance/tune-performance/profiling-tools.html

 

ONNX-Profilierung

Das Flag ONNX_ENABLE_PROFILING aktiviert das Profiling der ONNX-Modellausführung. Wenn dieses Flag in <data_folder>/MQL5/Files/OnnxProfileReports gesetzt ist, wird die folgende Datei erstellt: <module_name>_date_time.json.

Hier ist <module_name> der Name der EX5-Datei des MQL-Programms.

Die Datei enthält einen detaillierten Profiling-Bericht zur Ausführung des ONNX-Modells im JSON-Format, einschließlich:

  • Lade- und Initialisierungszeit der Sitzung;
  • Ausführungszeit einzelner graphischer Knoten (Conv, Relu, MaxPool, Gemm usw.);
  • verwendeter Ausführungsanbieter (z. B. CUDAExecutionProvider);
  • Informationen zur Größe des Eingabe- und Ausgabetensors;
  • Statistiken zur Thread-Planung.

 

Ein Beispiel für Daten aus einem Profiling-Bericht:

{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :698,"ts" :11,"ph" : "X","name" :"model_loading_array","args" : {}},
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :15496,"ts" :869,"ph" : "X","name" :"session_initialization","args" : {}},
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :66055,"ts" :16800,"ph" : "X","name" :"Convolution28_kernel_time","args" : {"parameter_size" : "832","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,1,28,28]},{"float
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :775,"ts" :82867,"ph" : "X","name" :"ReLU32_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,8,28,28]}],"node_index" : "3
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :8818,"ts" :83647,"ph" : "X","name" :"Pooling66_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,8,28,28]}],"node_inde
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :1120,"ts" :92476,"ph" : "X","name" :"Convolution110_kernel_time","args" : {"parameter_size" : "12864","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,8,14,14]},{"flo
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :23,"ts" :93603,"ph" : "X","name" :"ReLU114_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,16,14,14]}],"node_index" : "
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :21,"ts" :93629,"ph" : "X","name" :"Pooling160_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,16,14,14]}],"node_inde
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :16,"ts" :93654,"ph" : "X","name" :"Times212_reshape0_kernel_time","args" : {"parameter_size" : "16","provider" : "CUDAExecutionProvider","op_name" : "Reshape","input_type_shape" : [{"float":[1,16,4,4]},{"int
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :32264,"ts" :93673,"ph" : "X","name" :"Times212/MatMulAddFusion_kernel_time","args" : {"parameter_size" : "10280","provider" : "CUDAExecutionProvider","op_name" : "Gemm","input_type_shape" : [{"float":[1,256]
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :109165,"ts" :16794,"ph" : "X","name" :"SequentialExecutor::Execute","args" : {}},
{"cat" : "Session","pid" :34368,"tid" :39520,"dur" :109600,"ts" :16433,"ph" : "X","name" :"model_run","args" : {}},
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :87,"ts" :126313,"ph" : "X","name" :"Convolution28_kernel_time","args" : {"parameter_size" : "832","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,1,28,28]},{"float":
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :23,"ts" :126403,"ph" : "X","name" :"ReLU32_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,8,28,28]}],"node_index" : "3
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :31,"ts" :126431,"ph" : "X","name" :"Pooling66_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,8,28,28]}],"node_index
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :35,"ts" :126466,"ph" : "X","name" :"Convolution110_kernel_time","args" : {"parameter_size" : "12864","provider" : "CUDAExecutionProvider","op_name" : "Conv","input_type_shape" : [{"float":[1,8,14,14]},{"floa
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :15,"ts" :126505,"ph" : "X","name" :"ReLU114_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "Relu","input_type_shape" : [{"float":[1,16,14,14]}],"node_index" : 
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :22,"ts" :126523,"ph" : "X","name" :"Pooling160_kernel_time","args" : {"parameter_size" : "0","provider" : "CUDAExecutionProvider","op_name" : "MaxPool","input_type_shape" : [{"float":[1,16,14,14]}],"node_ind
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :12,"ts" :126548,"ph" : "X","name" :"Times212_reshape0_kernel_time","args" : {"parameter_size" : "16","provider" : "CUDAExecutionProvider","op_name" : "Reshape","input_type_shape" : [{"float":[1,16,4,4]},{"in
{"cat" : "Node","pid" :34368,"tid" :39520,"dur" :40,"ts" :126562,"ph" : "X","name" :"Times212/MatMulAddFusion_kernel_time","args" : {"parameter_size" : "10280","provider" : "CUDAExecutionProvider","op_name" : "Gemm","input_type_shape" : [{"float":[1,256]},

 

Additional information about ONNX profiling: https://onnxruntime.ai/docs/performance/tune-performance/profiling-tools.html

使用ONNX模型时的数组转换

机器学习任务并不总是需要更高的计算精度。为了加快计算速度,一些模型使用较低精度的数据类型,例如Float16甚至Float8。为了允许用户将相关数据输入到模型中,MQL5提供了四个特殊函数,可将标准MQL5类型转换为特殊的FP16和FP8类型。

函数

操作

ArrayToFP16

将float或double类型数组复制到给定格式的ushort类型的数组中

ArrayToFP8

将float或double类型数组复制到给定格式的uchar类型的数组中

ArrayFromFP16

ushort类型数组复制到给定格式的float或double类型的数组中

ArrayFromFP8

uchar类型数组复制到给定格式的float或double类型的数组中

这些数组转换函数使用以下枚举中指定的特殊格式。

ENUM_FLOAT16_FORMAT #

ENUM_FLOAT16_FORMAT枚举描述了两种FP16类型格式。

ID

描述

FLOAT_FP16

标准16位格式,也称为half

FLOAT_BFP16

特殊的brain float point(大脑浮点)格式

这些格式中的每一种都有其优点和局限性。FLOAT16提供更高的精度,但需要更多的存储和计算资源。另一方面,BFLOAT16在数据处理方面提供了更高的性能和效率,但可能不太准确。

ENUM_FLOAT8_FORMAT #

ENUM_FLOAT8_FORMAT枚举描述了四种FP8类型格式。

FP8(8位浮点)是用于表示浮点数的数据类型之一。在FP8中,每个数字由8个数据位表示,通常分为三个部分:符号、指数和尾数。这种格式提供了准确性和存储效率之间的平衡,使其对于需要内存和计算效率的应用程序具有吸引力。  

ID

描述

FLOAT_FP8_E4M3FN

8位浮点数,4位指数,3位尾数。通常用作系数。

FLOAT_FP8_E4M3FNUZ

8位浮点数,4位指数,3位尾数。支持NaN,不支持负零和Inf。通常用作系数。

FLOAT_FP8_E5M2FN

8位浮点数,5位指数,2位尾数。支持NaN和Inf。通常用于渐变。

FLOAT_FP8_E5M2FNUZ

8位浮点数,5位指数,2位尾数。支持NaN,不支持负零和Inf。也用于渐变。

FP8的主要优势之一是其处理大型数据集的效率。通过采用紧凑型数字表示法,FP8减少了内存需求并加速了计算。这对于经常处理大型数据集的机器学习和人工智能应用程序尤其重要。