根据src与dst tensor的类型进行精度转换。
在介绍不同的类型转换模式之前,先介绍下浮点数的表示方式:
i、float16共16 bit,包括1 bit符号位(S),5 bit指数位(E)和10 bit尾数位(M)。
当E不全为0或不全为1时,表示的结果为
当E全为0时,表示的结果为
当E全为1时,若M全为0,表示的结果为±inf(取决于符号位);若M不全为0,表示的结果为nan。
上图中S=0,E=15,M=2**(-1)+2**(-2),表示的结果为1.75。
ii、float32共32 bit,包括1 bit符号位(S),8 bit指数位(E)和23 bit尾数位(M)。
当E不全为0或不全为1时,表示的结果为
当E全为0时,表示的结果为
当E全为1时,若M全为0,表示的结果为±inf(取决于符号位);若M不全为0,表示的结果为nan。
上图中S=0,E=127,M=2**(-1)+2**(-2),最终表示的结果为1.75。
vec_conv所支持的类型转换模式如下:
1、f322f32:将src按照round_mode取整,仍以float32格式存入dst中;
示例:输入0.5
'round'模式输出0.0,'floor'模式输出0.0,'ceil'模式出1.0,'away-zero'模式输出1.0,'to-zero'模式输出0.0
2、f322f16:将src按照round_mode取到float16所能表示的数,以float16格式(溢出默认按照饱和处理)存入dst中;
示例:输入0.5+2**(-12),写成float32的表示形式:2**(-1) * (1+2**(-11)),因此E=-1+127=126,M=2**(-11):
float16的指数位可以表示的出2**(-1),有E=-1+15=14,
但float16只有10 bit尾数位,因此灰色部分要进行舍入。
'round'模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5;
'floor'模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5;
'ceil'模式舍入得尾数0000000001,E=14,M=2**(-10),最终表示的结果为0.5+2**(-11);
'away-zero'模式舍入得尾数0000000001,E=14,M=2**(-10),最终表示的结果为0.5+2**(-11);
'to-zero'模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5;
'odd'模式舍入得尾数0000000001,E=14,M=2**(-10),最终表示的结果为0.5+2**(-11)
3、f322s64:将src按照round_mode取整,以int64格式(溢出默认按照饱和处理)存入dst中;
示例:输入2**22+0.5
'round'模式输出2**22,'floor'模式输出2**22,'ceil'模式出2**22+1,'away-zero'模式输出2**22+1,'to-zero'模式输出2**22
4、f322s32:将src按照round_mode取整,以int32格式(溢出默认按照饱和处理)存入dst中;
示例:输入2**22+0.5
'round'模式输出2**22,'floor'模式输出2**22,'ceil'模式出2**22+1,'away-zero'模式输出2**22+1,'to-zero'模式输出2**22
5、f322s16:将src按照round_mode取整,以int16格式(溢出默认按照饱和处理)存入dst中;
示例:输入2**22+0.5
'round'模式输出2**15-1,'floor'模式输出2**15-1,'ceil'模式出2**15-1,'away-zero'模式输出2**15-1,'to-zero'模式输出2**15-1(溢出处理)
6、f162f32:将src以float32格式存入dst中,不存在精度转换问题,无舍入模式;
示例:输入1.5-2**(-10),输出1.5-2**(-10)
7、f162s32:将src按照round_mode取整,以int32格式存入dst中;
示例:输入-1.5
'round'模式输出-2,'floor'模式输出-2,'ceil'模式出-1,'away-zero'模式输出-2,'to-zero'模式输出-1
8、f162s16:将src按照round_mode取整,以int16格式(溢出默认按照饱和处理)存入dst中;
示例:输入2**7-0.5
'round'模式输出2**7,'floor'模式输出2**7-1,'ceil'模式出2**7,'away-zero'模式输出2**7,'to-zero'模式输出2**7-1
9、f162s8:将src按照round_mode取整,以int8格式(溢出默认按照饱和处理)存入dst中;
示例:输入2**7-0.5
'round'模式输出2**7-1,'floor'模式输出2**7-1,'ceil'模式出2**7-1,'away-zero'模式输出2**7-1,'to-zero'模式输出2**7-1(溢出处理)
10、f162u8:将src按照round_mode取整,以uint8格式(溢出默认按照饱和处理)存入dst中;
示例:输入1.75
'round'模式输出2,'floor'模式输出1,'ceil'模式出2,'away-zero'模式输出2,'to-zero'模式输出2
11、u82f16:将src以float16格式存入dst中,不存在精度转换问题,无舍入模式;
示例:输入1,输出1.0
12、s82f16:将src以float16格式存入dst中,不存在精度转换问题,无舍入模式;
示例:输入-1,输出-1.0
13、s162f16:将src按照round_mode取到float16所能表示的数,以float16格式存入dst中;
示例:输入2**12+2,写成float16的表示形式:2**12 * (1+2**(-11)),要求E=12+15=27,M=2**(-11):
由于float16只有10 bit尾数位,因此灰色部分要进行舍入。
'round'模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为2**12;
'floor'模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为2**12;
'ceil'模式舍入得尾数0000000001,E=27,M=2**(-10),最终表示的结果为2**12+4;
'away-zero'模式舍入得尾数0000000001,E=27,M=2**(-10),最终表示的结果为2**12+4;
'to-zero'模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为2**12
14、s162f32:将src以float32格式存入dst中,不存在精度转换问题,无舍入模式;
示例:输入2**15-1,输出2**15-1
15、s162s8:如果deqscale为Tensor类型,则取该Tensor的前16个元素,记为{deq_factor[i],i=0,1,2,...,15};如果deqscale为int、Scalar、Expr类型,则各个deq_factor[i]的值都等于该deqscale。要求deq_factor[i][46](第46比特位)=1,将deq_factor[i][31:13](第31到13比特位)看作float类型(1 bit符号位,8 bit指数位,10 bit尾数位),记作scale[i],将deq_factor[i][45:37](第45到37比特位)看作int9类型,记作offset[i];
deqscale也支持分开传入scale和offset,此时传入一个包含两个元素的list/tuple,其中第一个元素代表scale[i],要求是int/float类型,取值不能超过19bit浮点数(1 bit符号位,8 bit指数位,10 bit尾数位)的表示范围,如图,若scale输入0.5+2**(-12),10bit的尾数无法表示下该数,灰色部分会被舍弃(相当于全为0),最终真正生效的scale值为0.5。
第二个元素代表offset[i],要求是int类型,取值在[-256, 255]之间。
每次转换16个src元素{src[j*16+i],i=0,1,2,...,15,j=0,1,2,...},先计算src[j*16+i]*scale[i](float32类型),然后按'round'模式取整到int9(溢出按照饱和处理),然后将中间结果加上offset,再以int8格式(溢出按照饱和处理)存入dst[j*16+i]中;
示例:deqscale为Tensor,存储了16个uint64类型的数据:2**46+2**31+(127+i)*2**23(scale[i]=-2**i, offset[i]=0),
输入[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
输出[-1,-2,-4,-8,-16,-32,-64,-128,-128,-128,-128,-128,-128,-128,-128,-128](溢出处理)
16、s162u8:如果deqscale为Tensor类型,则取该Tensor的前16个元素,记为{deq_factor[i],i=0,1,2,...,15};如果deqscale为int、Scalar、Expr类型,则各个deq_factor[i]的值都等于该deqscale。要求deq_factor[i][46](第46比特位)=0,将deq_factor[i][31:13](第31到13比特位)看作float类型(1 bit符号位,8 bit指数位,10 bit尾数位),记作scale[i],将deq_factor[i][45:37](第45到37比特位)看作int9类型,记作offset[i];
deqscale也支持分开传入scale和offset,此时传入一个包含两个元素的list/tuple,其中第一个元素代表scale[i],要求是int/float类型,取值不能超过19bit浮点数(1 bit符号位,8 bit指数位,10 bit尾数位)的表示范围;第二个元素代表offset[i],要求是int类型,取值在[-256, 255]之间。
每次转换16个src元素{src[j*16+i],i=0,1,2,...,15,j=0,1,2,...},先计算src[j*16+i]*scale[i](float32类型),然后按'round'模式取整到int9(溢出按照饱和处理),然后将中间结果加上offset,再以uint8格式(溢出按照饱和处理)存入dst[j*16+i]中;
示例:deqscale为Tensor,存储了16个uint64类型的数据:i*2**37+127*2**23(scale[i]=1, offset[i]=i)
输入[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
输出[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
17、s322f32:将src按照round_mode取到float32所能表示的数,以float32格式存入dst中;
示例:输入2**25+3,写成float32的表示形式:2**25 * (1+2**(-24)+2**(-25)),要求E=25+127=152,M=2**(-24)+2**(-25):
由于float32只有23 bit尾数位,因此灰色部分要进行舍入。
'round'模式舍入得尾数00000000000000000000001,E=152,M=2**(-23),最终表示的结果为2**25+4;
'floor'模式舍入得尾数00000000000000000000000,E=152,M=0,最终表示的结果为2**25;
'ceil'模式舍入得尾数00000000000000000000001,E=152,M=2**(-23),最终表示的结果为2**25+4;
'away-zero'模式舍入得尾数00000000000000000000001,E=152,M=2**(-23),最终表示的结果为2**25+4;
'to-zero'模式舍入得尾数00000000000000000000000,E=152,M=0,最终表示的结果为2**25
18、s322f16:将src*deqscale按'round'模式取到float16能表示的数,以float16格式(溢出默认按照饱和处理)存入dst中;
示例:deqscale=3.0,输入2**10+1,乘积为2**11+2**10+3,按照'round'模式舍入得2**11+2**10+4(参考s162f16的转换)
19、s322s64:将src以int64格式存入dst中,不存在精度转换问题,无舍入模式;
示例:输入2**31-1,输出2**31-1
20、s322s16:将src以int16格式(溢出默认按照饱和处理)存入dst中,不存在精度转换问题,无舍入模式;
示例:输入2**31-1,输出2**15-1
21、s642s32:将src以int32格式(溢出默认按照饱和处理)存入dst中,不存在精度转换问题,无舍入模式;
示例:输入2**31,输出2**31-1
22、s642f32:将src按照round_mode取到float32所能表示的数,以float32格式存入dst中;
示例:输入2**35+2**12+2**11,写成float32的表示形式:2**35 * (1+2**(-23)+2**(-24)),要求E=35+127=162,M=2**(-23)+2**(-24):
由于float32只有23 bit尾数位,因此灰色部分要进行舍入。
'round'模式舍入得尾数00000000000000000000010,E=162,M=2**(-22),最终表示的结果为2**35+2**13;
'floor'模式舍入得尾数00000000000000000000001,E=162,M=2**(-23),最终表示的结果为2**25+2**12;
'ceil'模式舍入得尾数00000000000000000000010,E=162,M=2**(-22),最终表示的结果为2**25+2**13;
'away-zero'模式舍入得尾数00000000000000000000010,E=162,M=2**(-22),最终表示的结果为2**25+2**13;
'to-zero'模式舍入得尾数00000000000000000000001,E=162,M=2**(-23),最终表示的结果为2**25+2**12
vec_conv(mask, round_mode, dst, src, repeat_times, dst_rep_stride, src_rep_stride, deqscale=None, ldst_high_half=False)
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表1中mask参数描述。 |
round_mode |
输入 |
在转换过程中,最后一位转换处理模式,支持以下字符串配置:
|
dst |
输出 |
目的操作数。 Tensor的scope为Unified Buffer。 |
src |
输入 |
源操作数。 Tensor的scope为Unified Buffer。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。 |
deqscale |
输入 |
量化scale,辅助转换参数,默认值为None。 |
ldst_high_half |
输入 |
指定dst_list/src_list是存储/来自每个block的高半部或者低半部,默认值为False。 支持bool类型,True/False表示高半部/低半部; 注:该参数对于不同组合会分别表现为不同的功能定义,分别表示dst_list/src_list的存储/读取。 Atlas 200/300/500 推理产品,不支持该参数。 Atlas 训练系列产品,不支持该参数。 |
src.dtype |
dst.dtype |
round_mode supported |
deqscale |
---|---|---|---|
float16 |
int32 |
'round', 'floor', 'ceil', 'ceiling' |
None |
float16 |
float32 |
'', 'none' |
None |
float32 |
float16 |
'', 'none' |
None |
float16 |
int8 |
'', 'none' |
None |
float16 |
uint8 |
'', 'none' |
None |
int32 |
float16 |
'', 'none' |
Scalar(float16)/立即数(float) |
uint8 |
float16 |
'', 'none' |
None |
int8 |
float16 |
'', 'none' |
None |
src.dtype |
dst.dtype |
round_mode supported |
deqscale |
---|---|---|---|
float16 |
int32 |
'round', 'floor', 'ceil', 'ceiling', 'away-zero', 'to-zero' |
None |
float32 |
int32 |
'round', 'floor', 'ceil', 'ceiling', 'away-zero', 'to-zero' |
None |
int32 |
float32 |
'', 'none' |
None |
float16 |
float32 |
'', 'none' |
None |
float32 |
float16 |
'', 'none', 'odd' |
None |
float16 |
int8 |
'', 'none', 'floor', 'ceil', 'ceiling', 'away-zero', 'to-zero' |
None |
float16 |
uint8 |
'', 'none', 'floor', 'ceil', 'ceiling', 'away-zero', 'to-zero' |
None |
int32 |
float16 |
'', 'none' |
Scalar(float16)/立即数(float) |
uint8 |
float16 |
'', 'none' |
None |
int8 |
float16 |
'', 'none' |
None |
无
Atlas 200/300/500 推理产品
Atlas 训练系列产品
若第一位为1且后续位全为0,当M的最后一位为0则不进位,当M的最后一位为1则进位。
from tbe import tik tik_instance = tik.Tik() src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) dst_gm = tik_instance.Tensor("int32", (128,), name="dst_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("int32", (128,), name="dst_ub", scope=tik.scope_ubuf) # 将数据从gm搬到ub tik_instance.data_move(src0_ub, src0_gm, 0, 1, 128 * 2 // 32, 0, 0) # vec_conv精度转换 tik_instance.vec_conv(64, "round", dst_ub, src_ub, 2, 8, 4) # 将数据从ub搬到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128 * 4 // 32, 0, 0) tik_instance.BuildCCE(kernel_name="sample", inputs=[src_gm], outputs=[dst_gm])
结果示例:
输入数据: [0.5-2**(-11), 0.5, 0.5+2**(-11), -0.5-2**(-11), -0.5, -0.5-2**(-11), 0.0, 1.0, 2.0, 2**(-24), -2**(-24), 65504.0, -65504.0, 65472, -65472, ...] 输出数据: [0, 0, 1, 0, 0, -1, 0, 1, 2, 0, 0, 65504, -65504, 65472, -65472, ...]