MNN实践GammaPerf

做个游戏吧?玩儿转Mnn模型存储结构!

2019-08-01  本文已影响0人  Chriszzzz

1 倡导

我们来做个游戏吧,游戏内容是:
MNN二进制模型文件 中找到我们想要的 目标数据

游戏的部分基础信息可以在 这篇文章 中找到一二。

2 游戏说明

2.1 我们有 mnn模型文件 的信息

一个简单的 Conv + Conv + Relu 三层网络,其全部内容如下图:

游戏模型文件 json信息

2.2 我们有 mnn模型文件 的二进制信息

左边第一列为我加的索引列,二进制信息统一使用16进制打印,即一个数字是8位即一个字节

游戏模型文件 二进制信息

2.3 游戏目标

2.2 的 二进制信息 中找到 2.1 中json信息 目标字段的存储位置。

举例:
2.1 图中倒数第二行的 "0",在 2.2 图中对应 02行的 第6组 开始的五个字节 : 01 00 00 00 30
2.1 图中倒数第二行的 "5",在 2.2 图中对应 02行的 第4组 开始的五个字节 : 01 00 00 00 35

举例说明

有趣么?马上开始我们的游戏

3 带你玩

3.1 Mission 1 : 找到 tensorName "0"、"5"、"6"

056

3.1.1 找到MNN:Net 的数据起点

MNN 的二进制模型文件 的前四个字节是 根节点的偏移,它指向一个 继承于 flatbuffers::Table 名为 MNN::Net 数据结构

寻找MNN::Net结构内存起点

0x0000001C = 28
为什么是 0x0000001C,而不是0x1C000000呢?因为 小端模式
28位置 即 MNN::Net 结构的数据内存数据起点位置

3.1.2 寻找 字符串指针数组 的数据起点

MNN::Net 有一个tensorName的属性,即为我们的目标,
它是一个 字符串指针的数组(Vector<flatbuffers::Offset<flatbuffers::String>>)
让我们找打它!

寻找 字符串指针数组 的数据起点

3.1.1 节我们得到了位置28,那么:

3.1.3 寻找 字符串的数据起点

3.1.1 节我们得到了位置52,并且知道,这个位置是一个 字符串的指针数组,那么

3.1.4 解析字符串

字符串的 前四个字节 描述 字符串的长度

3.2 Mission2:找到Conv0 的 bias

再来个稍微复杂点的任务练练手!找到Conv0 的 bias

任务2目标

3.2.1 确认分析思路

看下MNN的数据结构,确认下任务完成思路

MNN模型数据结构

如图,我们要先找到oplists,然后找到 第二个op(第一个是Input),然后找到 Convolution2D 的数据,找到我们要的 bias

3.2.2 寻找 oplists 数据起点

oplists的数据结构是Vector<flatbuffers::Offset<Op>>,即一个Op指针的数组

找到 oplists

3.2.3 寻找 第二个Op 数据起点

第一个Op为Input,我们找第二个Op

3.2.4 寻找 Convolution2D 数据起点

寻找 Op & Convolution2D

3.2.5 分析Convolution2D

3.2.6 解析float

0x3f000000 转为二进制为:0011 1111 0000 0000 0000 0000 0000 0000
使用 Float结构拆解 为1 + 8 + 23,即 : 0 01111110 00000000000000000000000
得到:
符号位:0,正数
指数:01111110 : 126 -> 正负指数表示 -> 126 - 127 = -1,即 指数 -1
底数:00000000000000000000000,补1后为:1.0,即 底数 1.0

计算值:底数1.0 小数点 左移1位(-1) 得到:0.1,为二进制小数,转换为10进制即0.5

任务2完成!

结语

感兴趣的小伙伴也可以尝试在 2.2的二进制文件 中寻找下 2.1Json文件 的其他信息哦,或许还会有新的发现[坏笑]。
比如试试找一下:Conv1 的 weight 数据

资源
文中使用的MNN模型
MNN GitHub 地址
FlatBuffers MNN模型存储结构基础
FlatBuffers GitHub 地址

鸡汤
对任何事物追根究底的研究会找到意想不到的乐趣!
将那份复杂用最容易理解的方式讲出来!
自我学习后是 , 有效表达后为 ~

上一篇 下一篇

猜你喜欢

热点阅读