vec_conv

功能说明

根据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)

参数说明

表1 参数说明

参数名称

输入/输出

含义

mask

输入

请参考表1中mask参数描述。

round_mode

输入

在转换过程中,最后一位转换处理模式,支持以下字符串配置:

  • ‘‘ 或‘none’:在转换有精度损失时表示'round'模式,不涉及精度损失时表示不取整 ;
  • ‘round’四舍六入五成双(C语言rint);
  • ‘floor’:向负无穷舍入(C语言floor);
  • ‘ceil’或‘ceiling’:向正无穷舍入(C语言ceil)
  • ‘away-zero’:四舍五入(C语言round);
  • ‘to-zero’:向零舍入(C语言trunc)
  • ‘odd’:最近邻奇数舍入(Von Neumann rounding)

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 训练系列产品,不支持该参数。

表2 Atlas 200/300/500 推理产品round mode说明

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

表3 Atlas 训练系列产品round mode说明

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 训练系列产品

注意事项

调用示例

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, ...]