昇腾社区首页
中文
注册

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

注意事项

  • repeat_times∈[0,255]。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。当repeat_times为立即数时,不支持0。
  • 每个repeat的并行度取决于数据精度、芯片版本,如f32->f16转换每次迭代操作64个源/目的element。
  • 指令dst_rep_stride/src_rep_stride;单位为32B,支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
  • dst/src所支持的数据类型与芯片版本有关,如果不支持,工具会报错。
  • dst与src的应为不同tensor,或同一tensor的同一element,不支持同一tensor的不同element。
  • src为float32,dst为float32时,取整模式表示向整数取整(仍为float32类型),其他情况表示向dst dtype所能表示的数字取整。
  • 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
    • 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
    • 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
  • 操作数地址偏移对齐要求请见通用约束
  • 二进制下的舍入和十进制类似,具体如下:
    • 'round'模式下,若待舍入部分的第一位为0,则不进位;若第一位为1且后续位不全为0,则进位;

    若第一位为1且后续位全为0,当M的最后一位为0则不进位,当M的最后一位为1则进位。

    • 'floor'模式下,若S为0,则不进位;若S为1,当待舍入部分全为0则不进位,否则,进位。
    • 'ceil'/'ceiling'模式下,若S为1,则不进位;若S为0,当待舍入部分全为0则不进位;否则,进位。
    • 'away-zero'模式下,若待舍入部分的第一位为0,则不进位;否则,进位。
    • 'to-zero'模式下,总是不进位。
    • 'odd'模式下,若待舍入部分全为0,则不进位;

      若待舍入部分不全为0,当M的最后一位为1则不进位,当M的最后一位为0则进位。

调用示例

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