概要:
工作中遇到量化类型和反量化以及数据在二进制和文本形式之间的转换以及持久化操作比较多,核心是字符串类型和数值类型之间的互转,总结记录如下:
字符串转数值型
字符串转数值型分为两种情况:
字符串转整型:
头文件:stdlib.h
原型:
int atoi (const char *);
long atol (const char *);
long long atoll (const char *);
字符串转浮点型:
头文件:stdlib.h
double atof (const char *);
int scanf(const char *__restrict, ...);
int sscanf(const char *__restrict, const char *__restrict, ...);
int fscanf(FILE *__restrict, const char *__restrict, ...);
在musl libc中的声明:
数值类型转字符串:
头文件:stdlib.h
int sprintf(char *__restrict, const char *__restrict, ...);
int ptsname_r(int, char *, size_t);
char *ecvt(double, int, int *, int *);
char *fcvt(double, int, int *, int *);
char *gcvt(double, int, char *);
用例:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
double a = 123.45111111;
double b = -1234.5666666;
char ptr[20] = {0};
int decpt, sign;
char *str1 = gcvt(a, 20, ptr);
printf("a value=%s\n", str1);
char *str2 = gcvt(b, 20, ptr);
printf("b value=%s\n", str2);
return 0;
}
VIP模型的反量化操作中的应用如下,反量化公式为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(uint8_t *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
int main(int argc, char **argv)
{
FILE *file;
double scale;
int zeropoint;
DBG("in");
if(argc != 4)
{
DBG("input error, you should use this program like that: program xxxx.dat scale zeropoint.");
exit(-1);
}
scale = atof(argv[2]);
zeropoint = atoi(argv[3]);
DBG("scale %f, zeropoint %d.", scale, zeropoint);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
unsigned char *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
double res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
res = uint8_to_fp32(p[iter], zeropoint, scale);
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
str[len + 0] = '\r';
str[len + 1] = '\n';
str[len + 2] = '\0';
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
VIP中如果增加后处理节点,节点网络直接出的数据就是浮点类型,这个时候不需要做反量化,只需要文本化就可以了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(float *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("%f ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
int main(int argc, char **argv)
{
FILE *file;
//double scale;
//int zeropoint;
DBG("in");
if(argc != 2)
{
DBG("input error, you should use this program like that: program xxxx.dat.");
exit(-1);
}
//scale = atof(argv[2]);
//zeropoint = atoi(argv[3]);
//DBG("scale %f, zeropoint %d.", scale, zeropoint);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
float *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset((void*)p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen / 4 - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
float res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen / 4; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
//res = uint8_to_fp32(p[iter], zeropoint, scale);
res = p[iter];
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
str[len + 0] = '\r';
str[len + 1] = '\n';
str[len + 2] = '\0';
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
这个时候,浮点数的存储格式就是这样:
如果量化是INT8类型的,需要修改量化函数以和模型对应:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(uint8_t *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
static double int8_to_fp32(int8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - zeropoint) * scale;
return result;
}
int main(int argc, char **argv)
{
FILE *file;
double scale;
int zeropoint;
DBG("in");
if(argc != 4)
{
DBG("input error, you should use this program like that: program xxxx.dat scale zeropoint.");
exit(-1);
}
scale = atof(argv[2]);
zeropoint = atoi(argv[3]);
DBG("scale %f, zeropoint %d.", scale, zeropoint);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
unsigned char *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
double res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
#if 0
res = uint8_to_fp32(p[iter], zeropoint, scale);
#else
res = int8_to_fp32(p[iter], zeropoint, scale);
#endif
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
if(iter != filelen -1)
{
str[len ++] = '\r';
str[len ++] = '\n';
str[len ++] = '\0';
}
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
修改点:
INT16类型反量化
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(short *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
static double int8_to_fp32(int8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - zeropoint) * scale;
return result;
}
static float int16_to_fp32(int16_t val, int32_t fixed_point_pos)
{
float result = 0.0f;
if(fixed_point_pos > 0)
{
result = (float)val * (1.0f/((float)(1 << fixed_point_pos)));
}
else
{
result = (float)val * ((float)(1 << -fixed_point_pos));
}
return result;
}
int main(int argc, char **argv)
{
FILE *file;
int fixed_point_pos;
DBG("in");
if(argc != 3)
{
DBG("input error, you should use this program like that: program xxxx.dat fixed_point_pos.");
exit(-1);
}
fixed_point_pos = atof(argv[2]);
DBG("fixed_point_pos %d.", fixed_point_pos);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
short *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen/2 - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
double res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen/2; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
#if 0
res = uint8_to_fp32(p[iter], zeropoint, scale);
#else
//res = int8_to_fp32(p[iter], zeropoint, scale);
res = int16_to_fp32(p[iter], fixed_point_pos);
#endif
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
if(iter != filelen/2 -1)
{
str[len ++] = '\r';
str[len ++] = '\n';
str[len ++] = '\0';
}
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
UINT8的修复实现,末尾不添加空行:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(uint8_t *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
int main(int argc, char **argv)
{
FILE *file;
double scale;
int zeropoint;
DBG("in");
if(argc != 4)
{
DBG("input error, you should use this program like that: program xxxx.dat scale zeropoint.");
exit(-1);
}
scale = atof(argv[2]);
zeropoint = atoi(argv[3]);
DBG("scale %f, zeropoint %d.", scale, zeropoint);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
unsigned char *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
double res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
res = uint8_to_fp32(p[iter], zeropoint, scale);
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
if(iter != filelen -1)
{
str[len + 0] = '\r';
str[len + 1] = '\n';
str[len + 2] = '\0';
}
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
由于通常端侧设备不支持FP16浮点输梳理,必须要基于IEEE754标准进行FP16到FP32的转换,此过程不涉及反量化,但是涉及到浮点格式的转换:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(short *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
static double uint8_to_fp32(uint8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - (uint8_t)zeropoint) * scale;
return result;
}
static double int8_to_fp32(int8_t val, int32_t zeropoint, double scale)
{
double result = 0.0f;
result = (val - zeropoint) * scale;
return result;
}
static float int16_to_fp32(int16_t val, int32_t fixed_point_pos)
{
float result = 0.0f;
if(fixed_point_pos > 0)
{
result = (float)val * (1.0f/((float)(1 << fixed_point_pos)));
}
else
{
result = (float)val * ((float)(1 << -fixed_point_pos));
}
return result;
}
typedef union
{
unsigned int u;
float f;
} _fp32_t;
static float fp16_to_fp32(const short in)
{
const _fp32_t magic = { (254 - 15) << 23 };
const _fp32_t infnan = { (127 + 16) << 23 };
_fp32_t o;
// Non-sign bits
o.u = (in & 0x7fff ) << 13;
o.f *= magic.f;
if(o.f >= infnan.f)
{
o.u |= 255 << 23;
}
//Sign bit
o.u |= (in & 0x8000 ) << 16;
return o.f;
}
int main(int argc, char **argv)
{
FILE *file;
int fixed_point_pos;
DBG("in");
if(argc != 2)
{
DBG("input error, you should use this program like that: program xxxx.dat fixed_point_pos.");
exit(-1);
}
//fixed_point_pos = atof(argv[2]);
//DBG("fixed_point_pos %d.", fixed_point_pos);
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
short *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 32);
dump_memory(p + filelen/2 - 32, 32);
char outputname[255];
memset(outputname, 0x00, 255);
memcpy(outputname, argv[1], strlen(argv[1]));
memcpy(outputname+strlen(argv[1]), ".tensor", 7);
DBG("output tensor name %s", outputname);
FILE *outensor = fopen(outputname, "w+");
if(outensor == NULL)
{
DBG("fatal error, create output tensor file %s failure, please check the file status.", outputname);
exit(-1);
}
// anti-quanlization && convert to text and store.
#define BUF_SIZE 32
int iter;
float res;
char buf[BUF_SIZE];
int count;
for(iter = 0; iter < filelen/2; iter ++)
{
char *str;
memset(buf, 0x00, BUF_SIZE);
#if 0
res = uint8_to_fp32(p[iter], zeropoint, scale);
#else
//res = int8_to_fp32(p[iter], zeropoint, scale);
//res = int16_to_fp32(p[iter], fixed_point_pos);
res = fp16_to_fp32(p[iter]);
#endif
#if 0
sprintf(buf, "%f\r\n", res);
str = buf;
#else
str = gcvt(res, BUF_SIZE, buf);
int len = strlen(str);
if(iter != filelen/2 -1)
{
str[len ++] = '\r';
str[len ++] = '\n';
str[len ++] = '\0';
}
#endif
if((count = fwrite(str, 1, strlen(str), outensor))!= strlen(str))
{
DBG("write float to file error, count %d, strlen %ld.", count, strlen(str));
exit(-1);
}
}
fflush(outensor);
fsync(fileno(outensor));
fclose(outensor);
fclose(file);
free(p);
DBG("out");
return 0;
}
以LENET 模型为例,最后一层是softmax层,十分类,输出为FP16,则总共20个字节,将其FP16转为FP32输出的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define DBG(fmt, ...) do { printf("%s line %d, "fmt"\n", __func__, __LINE__, ##__VA_ARGS__); } while (0)
static void dump_memory(short *buf, int32_t len)
{
int i;
printf("\n\rdump file memory:");
for (i = 0; i < len; i ++)
{
if ((i % 16) == 0)
{
printf("\n\r%p: ", buf + i);
}
printf("0x%02x ", buf[i]);
}
printf("\n\r");
return;
}
typedef union
{
unsigned int u;
float f;
} _fp32_t;
static float fp16_to_fp32(const short in)
{
const _fp32_t magic = { (254 - 15) << 23 };
const _fp32_t infnan = { (127 + 16) << 23 };
_fp32_t o;
// Non-sign bits
o.u = (in & 0x7fff ) << 13;
o.f *= magic.f;
if(o.f >= infnan.f)
{
o.u |= 255 << 23;
}
//Sign bit
o.u |= (in & 0x8000 ) << 16;
return o.f;
}
int main(int argc, char **argv)
{
FILE *file;
int fixed_point_pos;
DBG("in");
if(argc != 2)
{
DBG("input error, you should use this program like that: program xxxx.dat fixed_point_pos.");
exit(-1);
}
file = fopen(argv[1], "rb");
if(file == NULL)
{
DBG("fatal error, open file %s failure, please check the file status.", argv[1]);
exit(-1);
}
fseek(file, 0, SEEK_END);
int filelen = ftell(file);
DBG("file %s len %d byets.", argv[1], filelen);
unsigned short *p = malloc(filelen);
if(p == NULL)
{
DBG("malloc buffer failure for %s len %d.", argv[1], filelen);
exit(-1);
}
memset(p, 0x00, filelen);
fseek(file, 0, SEEK_SET);
if(fread(p, 1, filelen, file) != filelen)
{
DBG("read file failure, size wrong.");
exit(-1);
}
dump_memory(p, 20);
int iter;
float res;
for(iter = 0; iter < filelen/2; iter ++)
{
res = fp16_to_fp32(p[iter]);
printf("class %d, prob %f.\n", iter, res);
}
fclose(file);
free(p);
DBG("out");
return 0;
}
验证: