基于C语言库进行tensor反量化和文本化几例

概要:

工作中遇到量化类型和反量化以及数据在二进制和文本形式之间的转换以及持久化操作比较多,核心是字符串类型和数值类型之间的互转,总结记录如下:

字符串转数值型

字符串转数值型分为两种情况:

字符串转整型:

头文件: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模型的反量化操作中的应用如下,反量化公式为:

\\ FP = (Q-ZP)*Scale = Q*Scale +(-ZP)*Scale = Qantum * Scale + FP_{bias}

#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;
}

验证:

关于各类浮点表示转换的ONNX代码实现:

交叉参考相关博文:

根据欧式距离和余弦相似度来计算tensor之间的相似度的代码实现_tugouxp的专栏-CSDN博客通常情况下,在端侧的模型推理过程中,使用的是量化后的数据来参与各层计算的,而并非原始的float数据类型,通常的量化数据类型有UINT8/INT8/INT16等等,由于数据表示范围的差异,在量化过程中,必然涉及到精度损失,这种同一个模型相同层之间使用量化推理计算得到的数据经过反量化之后和原始goden版的float数据的差异,我们用相似度表示,用图形化描述如下:...https://blog.csdn.net/tugouxp/article/details/122266262?spm=1001.2014.3001.5501


结束! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

papaofdoudou

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值