paramdict、modelbin加载模型并存储模型形式:字典及binary。
参数字典私有类ParamDictPrivate
class ParamDictPrivate
{
public:
struct
{
// 0 = null
// 1 = int/float
// 2 = int
// 3 = float
// 4 = array of int/float
// 5 = array of int
// 6 = array of float
int type;//参数类型存放
union
{
int i;
float f;
};
Mat v;//参数值存放
} params[NCNN_MAX_PARAM_COUNT];//32
};
union用法:C++中union的使用方法_棉猴的博客-CSDN博客_c++ union
ParamDictPrivate类中公有结构体内部再有联合体。
结构体嵌套联合体-字节对齐
联合体字节对齐:取内部类型字节数最大的(因其内部所有的变量共用初始地址且每次只能对其中一个变量赋值起作用,多个变量同时赋值,只有最后被赋值的变量有效,其余为0)
结构体字节对齐:需要考虑内部变量类型字节数累加与当前变量类型字节数对齐以及整体字节数对齐。
参数字典类ParamDict
class NCNN_EXPORT ParamDict
{
public:
// empty
ParamDict();
virtual ~ParamDict();
// copy
ParamDict(const ParamDict&);
// assign
ParamDict& operator=(const ParamDict&);
// get type
int type(int id) const;
// get int
int get(int id, int def) const;
// get float
float get(int id, float def) const;
// get array
Mat get(int id, const Mat& def) const;
// set int
void set(int id, int i);
// set float
void set(int id, float f);
// set array
void set(int id, const Mat& v);
protected:
friend class Net;
void clear();
int load_param(const DataReader& dr);
int load_param_bin(const DataReader& dr);
private:
ParamDictPrivate* const d;
};
加载模型,解析模型文件将值及类型分别存储到mat和type中。
int ParamDict::load_param(const DataReader& dr)
{
clear();
// 0=100 1=1.250000 -23303=5,0.1,0.2,0.4,0.8,1.0
// parse each key=value pair
int id = 0;
while (dr.scan("%d=", &id) == 1)
{
bool is_array = id <= -23300;
if (is_array)
{
id = -id - 23300;
}
if (id >= NCNN_MAX_PARAM_COUNT)
{
NCNN_LOGE("id < NCNN_MAX_PARAM_COUNT failed (id=%d, NCNN_MAX_PARAM_COUNT=%d)", id, NCNN_MAX_PARAM_COUNT);
return -1;
}
if (is_array)
{
int len = 0;
int nscan = dr.scan("%d", &len);
if (nscan != 1)
{
NCNN_LOGE("ParamDict read array length failed");
return -1;
}
d->params[id].v.create(len);
for (int j = 0; j < len; j++)
{
char vstr[16];
nscan = dr.scan(",%15[^,\n ]", vstr);
if (nscan != 1)
{
NCNN_LOGE("ParamDict read array element failed");
return -1;
}
bool is_float = vstr_is_float(vstr);
if (is_float)
{
float* ptr = d->params[id].v;
ptr[j] = vstr_to_float(vstr);
}
else
{
int* ptr = d->params[id].v;
nscan = sscanf(vstr, "%d", &ptr[j]);
if (nscan != 1)
{
NCNN_LOGE("ParamDict parse array element failed");
return -1;
}
}
d->params[id].type = is_float ? 6 : 5;
}
}
else
{
char vstr[16];
int nscan = dr.scan("%15s", vstr);
if (nscan != 1)
{
NCNN_LOGE("ParamDict read value failed");
return -1;
}
bool is_float = vstr_is_float(vstr);
if (is_float)
{
d->params[id].f = vstr_to_float(vstr);
}
else
{
nscan = sscanf(vstr, "%d", &d->params[id].i);
if (nscan != 1)
{
NCNN_LOGE("ParamDict parse value failed");
return -1;
}
}
d->params[id].type = is_float ? 3 : 2;
}
}
return 0;
}
ModelBin抽象类
由ModelBinFromDataReader 和ModelBinFromMatArray 派生类分别实现。
ModelBinFromDataReader 直接读取模型文件存储bin形式
ModelBinFromMatArray 从Mat类型转存bin形式。
class NCNN_EXPORT ModelBin
{
public:
ModelBin();
virtual ~ModelBin();
// element type
// 0 = auto
// 1 = float32
// 2 = float16
// 3 = int8
// load vec
virtual Mat load(int w, int type) const = 0;
// load image
virtual Mat load(int w, int h, int type) const;
// load dim
virtual Mat load(int w, int h, int c, int type) const;
};
class ModelBinFromDataReaderPrivate;
class NCNN_EXPORT ModelBinFromDataReader : public ModelBin
{
public:
explicit ModelBinFromDataReader(const DataReader& dr);
virtual ~ModelBinFromDataReader();
virtual Mat load(int w, int type) const;
private:
ModelBinFromDataReader(const ModelBinFromDataReader&);
ModelBinFromDataReader& operator=(const ModelBinFromDataReader&);
private:
ModelBinFromDataReaderPrivate* const d;
};
class ModelBinFromMatArrayPrivate;
class NCNN_EXPORT ModelBinFromMatArray : public ModelBin
{
public:
// construct from weight blob array
explicit ModelBinFromMatArray(const Mat* weights);
virtual ~ModelBinFromMatArray();
virtual Mat load(int w, int type) const;
private:
ModelBinFromMatArray(const ModelBinFromMatArray&);
ModelBinFromMatArray& operator=(const ModelBinFromMatArray&);
private:
ModelBinFromMatArrayPrivate* const d;
};
} // namespace ncnn