Cast
产品支持情况
功能说明
数据类型精度转换,将U类型的源操作数根据指定的转换模式,转换成T类型的目的操作数类型。
函数原型
template <typename T = DefaultType, typename U = DefaultType, const CastTrait& trait = castTrait, typename S, typename V>
__simd_callee__ inline void Cast(S& dstReg, V& srcReg, MaskReg& mask)
参数说明
表 1 模板参数说明
|
包括RegLayout、SatMode、MaskMergeMode、RoundMode。 使能SatMode生效需与SetCtrlSpr(ISASI)配合使用。 |
|
表 2 参数说明
|
类型为RegTensor。 |
||
|
类型为RegTensor。 |
||
源操作数元素操作的有效指示,详细说明请参考MaskReg。 |
表 3 浮点转整数
RegLayout::ZERO, RegLayout::ONE, RegLayout::TWO, RegLayout::THREE |
|||||
表 4 浮点转浮点
RegLayout::ZERO, RegLayout::ONE, RegLayout::TWO, RegLayout::THREE |
|||||
表 5 整数转浮点
RegLayout::ZERO, RegLayout::ONE, RegLayout::TWO, RegLayout::THREE |
||||
表 6 整数转整数
RegLayout::ZERO, RegLayout::ONE, RegLayout::TWO, RegLayout::THREE |
||||
RegLayout::ZERO, RegLayout::ONE, RegLayout::TWO, RegLayout::THREE |
||||
表 7 浮点转整数转换规则
表 8 浮点转浮点转换规则
|
half有尾数位10bit,float有尾数位23bit,float转half舍弃精度13bit,float16最低位标记为黄色y,float舍弃精度标记为红色 float +/-a.xxxxxxxxx00000100000000,如果y bit位为0偶数,则进位,得到half a.xxxxxxxxx1 float +/-a.xxxxxxxxx11000100000000,如果y bit位为1奇数,则不进位,得到half a.xxxxxxxxx1 sign:0, exponent:10000101, mantissa:11101100111011101110111 float_exponet = 0b10000101 = 133 float_mantissa 第14位为1奇数,所以不进位,舍弃后面13位 |
||
|
sign:1bit,exponent:8bit mantissa:23bit sign:1bit,exponent:8bit,mantissa:7bit 1、float32_mantissa:00100000010000010000000 舍弃精度小于0b1000000000000000,等效于[0, 0.5),则不进位 2、float32_mantissa:00110001000000000000000 舍弃精度等于0b1000000000000000,bf16最低位为偶数时不进位 3、float32_mantissa:00110011000000000000000 舍弃精度等于0b1000000000000000,bf16最低位为奇数时进位 4、float32_mantissa:00100001010000010000000 舍弃精度大于0b1000000000000000,等效于(0.5, 1),则进位 1、float32_mantissa:00100000010000010000000 舍弃精度小于0b1000000000000000,等效于[0, 0.5),则不进位 2、float32_mantissa:00110001000000000000000 舍弃精度等于0b1000000000000000,进位后离0越远,所以进位 3、float32_mantissa:00100001010000010000000 舍弃精度大于0b1000000000000000,等效于(0.5, 1),则进位 1、float32_mantissa:00100000010000010000000,float32值正数时不进位,得到bfloat16_mantissa:0010000 2、float32_mantissa:00110001000000000000000 float32 值负数时进位,得到bfloat16_mantissa:0011001 1、float32_mantissa:00100000010000010000000,float32值正数时进位,得到bfloat16_mantissa:0010001 2、float32_mantissa:00110001000000000000000 float32 值负数时不进位,得到bfloat16_mantissa:0011000 1、float32_mantissa:00100000010000010000000,都不进位,直接舍弃红色精度,得到bfloat16_mantissa:001000 sign:0, exponent:10000110, mantissa:10011011100000000000000 float32_mantissa = 0b10011011100000000000000 舍弃精度大于0b1000000000000000,等效于(0.5, 1),则进位 得到bfloat16_mantinssa = 0b1001110 |
||
|
sign:1bit,exponent:8bit,mantissa:7bit sign:1bit,exponent:5bit,mantissa:10bit 当bfloat16_exponent = exponent-127 >= -14时 因为bfloat16精度低,float16精度高,所以bfloat16到float16精度不变 例1:bfloat16_mantissa = 0b1011000 -> float16_maintissa = 0b1011000000, 二进制位不发生进位,只需要再低位补3个0 当bfloat16_exponent = exponent-127 < -14时 例2:当exponent = 108, bfloat16_exponent = exponent-127 = -19< -14时,因为float16_exponent = exponent - 14 最小为-14,无法表示,所以指数需要+5保持和float16_exponent相等,同时尾数位需要除以2的5次方,因为bf16计算公式 = s * (2^(e-127))*(man) = s * (2^(e-127+5))*(man*2^(-5)),指数位乘以一个数,尾数位需要除以相同大小的数,保证最终值不变。假设bfloat16_mantissa = 0b1011011 bfloat16 mantissa计算公式为 1+ man/128, 用例二进制表示为 0b1.1011011,指数位乘以2的5次方时,尾数要除以2的5次,小数点向左移动5位,所以bfloat16_mantissa = 0b0.000011011011,尾数为12位,因为float16只有10bit尾数位,所以在以下CAST模式中需要舍弃最低2位,并根据舍入模式决定是否舍入,当前例子的舍弃精度中间值为0b10 当bfloat16_mantissa尾数小于等于10位时,不需要舍入; 当bfloat16_mantissa尾数大于10位时,类似例2的例子 例bfloat16_mantissa = 0b0.00001101100xxx 0xxx < 1000 输出float16_mantissa = 0b0.0000110110 例bfloat16_mantissa = 0b0.00001101100xxx 1x1x > 1000 输出float16_mantissa = 0b0.0000110111 3) 被舍弃的精度等于舍弃精度中间值时,第10位为偶数时不进位 例bfloat16_mantissa = 0b0.00001101100xxx 0 % 2 == 0 输出float16_mantissa = 0b0.0000110110 4) 被舍弃的精度等于舍弃精度中间值时,第10位为奇数时进位 例bfloat16_mantissa = 0b0.00001100010xxx 1 % 2 == 1 输出float16_mantissa = 0b0.0000110001 当bfloat16_mantissa尾数小于等于10位时,不需要进位; 当bfloat16_mantissa尾数大于10位时,类似例2的例子 例bfloat16_mantissa = 0b0.00001101100xxx 0xxx < 1000 输出float16_mantissa = 0b0.0000110110 例bfloat16_mantissa = 0b0.00001101100xxx 1x1x > 1000 输出float16_mantissa = 0b0.0000110111 3) 被舍弃的精度等于舍弃精度中间值时,进位远离0,所以进位 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110111 当bfloat16_mantissa尾数小于等于10位时,不需要进位; 当bfloat16_mantissa尾数大于10位时,类似例2的例子 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110110 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110111 当bfloat16_mantissa尾数小于等于10位时,不需要舍入; 当bfloat16_mantissa尾数大于10位时,类似例2的例子 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110111 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110110 当bfloat16_mantissa尾数小于等于10位时,不需要舍入; 当bfloat16_mantissa尾数大于10位时,类似例2的例子 例bfloat16_mantissa = 0b0.00001101100xxx 输出float16_mantissa = 0b0.0000110110 sign:0, exponent:01101100, mantissa:1000011 bfloat16_exponent = 108-127 = -19 < -14,float16_exponent最小为-14,所以bfloat16_exponent += 5,bfloat16_mantissa 小数点左移 5位,1.1000011 -> 0.000011000011 bfloat16_mantissa = 0.0000110001 |
||
|
sign:1bit,exponent:5bit,mantissa:10bit sign:1bit,exponent:8bit,mantissa:7bit 3)当舍入精度等于舍弃精度中间值100时,bfloat16最低位为偶数,不舍入 4)当舍入精度等于舍弃精度中间值100时,bfloat16最低位为奇数, 3)当舍入精度等于舍弃精度中间值100时,进位远离0,所以舍入 二进制为sign:0, exponent:01100, mantissa:0000110001 half_exponent = 12-15 = bfloat16_exp - 127 bfloat16_exp = 124 = 0b1111100 |
||
|
sign:1bit,exponent:8bit mantissa:23bit sign:1bit,exponent:4bit,mantissa:3bit 需要舍弃20bit,舍弃精度中间值为0b10000000000000000000 例float_mantinssa = 01100100110000000000000 例float_mantinssa= 01110100110000000000000 3)当舍入精度等于舍弃精度中间值时,fp8_e4m3fn_t最低位为偶数,不舍入 例float_mantinssa= 01010000000000000000000 4)当舍入精度等于舍弃精度中间值时,fp8_e4m3fn_t最低位为奇数, 例float_mantinssa= 01110000000000000000000 sign:0, exponent:01111111, mantissa:00111011101001011110010 float_exponent = 127-127 = fp8_e4m3fn_t_exp - 7 float_mantissa = 00111011101001011110010 |
||
|
sign:1bit,exponent:8bit mantissa:23bit sign:1bit,exponent:5bit,mantissa:2bit 需要舍弃21bit,舍弃精度中间值为0b100000000000000000000 例float_mantinssa = 01000100110000000000000 例float_mantinssa= 01101001100000000000000 3)当舍入精度等于舍弃精度中间值时,fp8_e5m2_t最低位为偶数,不舍入 例float_mantinssa= 00100000000000000000000 4)当舍入精度等于舍弃精度中间值时,fp8_e5m2_t最低位为奇数, 例float_mantinssa= 0110000000000000000000 sign:0, exponent:01111111, mantissa:00111011101001011110010 float_exponent = 127-127 = fp8_e5m2_t_exp - 15 float_mantissa = 00111011101001011110010 |
||
|
sign:1bit,exponent:8bit,mantissa:7bit sign:1bit,exponent:2bit,mantissa:1bit 当bfloat16_exponent = exponent-127 < 0时 例1:当exponent = 124, bfloat16_exponent = exponent-127 = -3 < 0时,因为float4_e2m1_exponent = exponent - 1 最小为0,无法表示,所以指数需要+3保持和float4_e2m1_exponent相等,同时尾数位需要除以2的3次方,因为bf16计算公式 = s * (2^(e-127))*(man) = s * (2^(e-127+3))*(man*2^(-3)),指数位乘以一个数,尾数位需要除以相同大小的数,保证最终值不变。假设bfloat16_mantissa = 0b1011011 bfloat16 mantissa计算公式为 1+ man/128, 用例二进制表示为 0b1.1011011,指数位乘以2的3次方时,尾数要除以2的3次,小数点向左移动3位,所以bfloat16_mantissa = 0b0.0011011011,因为float4_e2m1只有1bit尾数位,所以在以下CAST模式中需要舍弃最低9位,并根据舍入模式决定是否舍入,当前例子的舍弃精度中间值为0b100000000 例bfloat16_mantissa = 0b0.0000110xxx 000110xxx < 舍弃精度中间值 输出float4_e2m1_mantissa = 0b0.0 例bfloat16_mantissa = 0b0.0100110xxx 100110xxx > 舍弃精度中间值 输出float4_e2m1_mantissa = 0b0.1 3) 被舍弃的精度等于舍弃精度中间值时,第1位为偶数时不进位 例bfloat16_mantissa = 0b0.0100000xxx 0 % 2 == 0 输出float4_e2m1_mantissa = 0b0.0 例bfloat16_mantissa = 0b0.1100000xxx 1 % 2 == 1 输出float4_e2m1_mantissa = 0b0.1 例bfloat16_mantissa = 0b0.0000110xxx 000110xxx < 舍弃精度中间值 输出float4_e2m1_mantissa = 0b0.0 例bfloat16_mantissa = 0b0.0100110xxx 100110xxx > 舍弃精度中间值 输出float4_e2m1_mantissa = 0b0.1 3) 被舍弃的精度等于舍弃精度中间值时,进位远离0,所以进位 例bfloat16_mantissa = 0b0.0100000xxx 输出float4_e2m1_mantissa = 0b0.1 例bfloat16_mantissa = 0b0.0000110xxx 输出float4_e2m1_mantissa = 0b0.0 例bfloat16_mantissa = 0b0.0100110xxx 输出float4_e2m1_mantissa = 0b0.1 例bfloat16_mantissa = 0b0.0000110xxx 输出float4_e2m1_mantissa = 0b0.1 例bfloat16_mantissa = 0b0.0100110xxx 输出float4_e2m1_mantissa = 0b0.0 例bfloat16_mantissa = 0b0.0100110xxx 输出float4_e2m1_mantissa = 0b0.0 sign:0, exponent:01111110, mantissa:1000011 bfloat16_exponent = 126-127 = -1 < 0,float16_exponent最小为0,所以bfloat16_exponent += 1,bfloat16_mantissa 小数点左移 舍弃精度1000011大于舍弃精度中间值1000000,所以进位 |
||
|
sign:1bit,exponent:8bit,mantissa:7bit sign:1bit,exponent:1bit,mantissa:2bit 当bfloat16_exponent = exponent-127 < 0时,bfloat16_mantissa需要发生位移 例1:当exponent = 124, bfloat16_exponent = exponent-127 = -3 < 0时,因为float4_e1m2_exponent = exponent - 1 最小为0,无法表示,所以指数需要+3保持和float4_e2m1_exponent相等,同时尾数位需要除以2的3次方,因为bf16计算公式 = s * (2^(e-127))*(man) = s * (2^(e-127+3))*(man*2^(-3)),指数位乘以一个数,尾数位需要除以相同大小的数,保证最终值不变。假设bfloat16_mantissa = 0b1011011 bfloat16 mantissa计算公式为 1+ man/128, 用例二进制表示为 0b1.1011011,指数位乘以2的3次方时,尾数要除以2的3次,小数点向左移动3位,所以bfloat16_mantissa = 0b0.0011011011,因为float4_e2m1只有2bit尾数位,所以在以下CAST模式中需要舍弃最低8位,并根据舍入模式决定是否舍入,当前例子的舍弃精度中间值为0b10000000 例bfloat16_mantissa = 0b0.0000011xxx 00011xxx < 舍弃精度中间值 输出float4_e1m2_mantissa = 0b0.00 例bfloat16_mantissa = 0b0.0010011xxx 10011xxx > 舍弃精度中间值 输出float4_e1m2_mantissa = 0b0.01 3) 被舍弃的精度等于舍弃精度中间值时,第2位为偶数时不进位 例bfloat16_mantissa = 0b0.0010000xxx 0 % 2 == 0 输出float4_e1m2_mantissa = 0b0.00 例bfloat16_mantissa = 0b0.0110000xxx 1 % 2 == 1 输出float4_e1m2_mantissa = 0b0.10 例bfloat16_mantissa = 0b0.0000110xxx 00110xxx < 舍弃精度中间值 输出float4_e1m2_mantissa = 0b0.00 例bfloat16_mantissa = 0b0.0010110xxx 10110xxx > 舍弃精度中间值 输出float4_e1m2_mantissa = 0b0.01 3) 被舍弃的精度等于舍弃精度中间值时,进位远离0,所以进位 例bfloat16_mantissa = 0b0.0010000xxx 输出float4_e1m2_mantissa = 0b0.01 例bfloat16_mantissa = 0b0.0000110xxx 输出float4_e1m2_mantissa = 0b0.00 例bfloat16_mantissa = 0b0.00100110xxx 输出float4_e1m2_mantissa = 0b0.01 例bfloat16_mantissa = 0b0.0000110xxx 输出float4_e1m2_mantissa = 0b0.01 例bfloat16_mantissa = 0b0.0010110xxx 输出float4_e1m2_mantissa = 0b0.00 例bfloat16_mantissa = 0b0.0010110xxx 输出float4_e1m2_mantissa = 0b0.00 sign:0, exponent:01111110, mantissa:1000011 bfloat16_exponent = 126-127 = -1 < 0,float16_exponent最小为0,所以bfloat16_exponent += 1,bfloat16_mantissa 小数点左移 舍弃精度000011小于舍弃精度中间值100000,所以不进位 |
||
参考图1。 |
返回值说明
无
约束说明
-
该指令需配合SetCtrlSpr(ISASI) 指令使用,通过设置寄存器的值控制Cast的饱和和非饱和模式。
-
浮点数转整数:
- 非饱和模式:输入数据超过输出类型最值时,结果被截断为目标格式的数据宽度,例如输入half值为257, 输出uint8_t值为1,输入为+/-inf,则返回输出类型的对应最值,输入nan时,返回0。
- 饱和模式:输入数据超过输出类型最值时,返回输出类型的对应最值,例如输入half值为257, 输出uint8值为255,输入half值为-inf,输出uint8_t值为0,输入nan时,返回0。
-
浮点数转浮点数:
-
当前浮点数转浮点数支持饱和模式和非饱和模式,非饱和模式下,输入数据为nan时,输出为nan,输入+/-inf时,输出为+/-inf;饱和模式下,输入为nan时,输出为0,输入数据超过输出类型最值时,返回输出类型的对应最值。
-
当输出类型float32时,只支持不饱和模式。
-
当输出类型为fp8_e4m3fn_t时,由于fp8_e4m3fn_t没有inf表示格式,所以输出为nan。
-
当输出类型为fp8_e5m2_t/fp8_e4m3fn_t时,输入nan,默认输出为0。
-
对于bfloat16 to float4类型,输入bfloat16 inf或超出fp4x2_e2m1_t/fp4x2_e1m2_t数据最值范围时,会返回对应符号的fp4x2_e2m1_t/fp4x2_e1m2_t最值;输入nan时,fp4x2_e2m1_t/fp4x2_e1m2_t输出0。
-
对于fp4x2_e2m1_t/fp4x2_e1m2_t类型,cast读写会每2个元素为一对进行读写,mask b16有效位以偶数位为准,例如
256bit 01 01 00 00 01 00 00 01 等效于 01 01 00 00 01 01 00 00

-
对于fp8_e8m0_t类型:
输入bfloat16_t +/-inf或绝对值超出fp8_e8m0_t类型最值,则返回fp8_e8m0_t最大值0b11111110;
输入bfloat16_t nan 输出fp8_e8m0_t nan = 0b11111111。
-
-
整数转整数
不饱和模式:输入数据会截断为目标数据格式,例如,输入int32_t值为256, 输出uint8_t值为0
饱和模式:输入数据超出目标数据范围,会饱和为目标数据最值
对于窄数据类型例如int16_t(2Byte)转宽数据类型uint32_t(4Byte),只支持饱和模式,输入负数会被饱和成0
调用示例
__simd_vf__ inline void CastVF(__ubuf__ int16_t* dstAddr, __ubuf__ float* srcAddr, uint32_t count, uint32_t srcRepeatSize, uint32_t dstRepeatSize, uint16_t repeatTimes)
{
// castTrait 类变量时需要加static
static constexpr AscendC::Reg::CastTrait castTrait =
{AscendC::Reg::RegLayout::ZERO, AscendC::Reg::SatMode::NO_SAT,AscendC::Reg::MaskMergeMode::ZEROING,AscendC::RoundMode::CAST_RINT};
AscendC::Reg::RegTensor<float> srcReg;
AscendC::Reg::RegTensor<int16_t> dstReg;
AscendC::Reg::MaskReg mask;
for (uint16_t i = 0; i < repeatTimes; i++) {
AscendC::Reg::LoadAlign(srcReg, srcAddr + i * srcRepeatSize);
mask = AscendC::Reg::UpdateMask<float>(count);
AscendC::Reg::Cast<int16_t, float, castTrait>(dstReg, srcReg, mask);
AscendC::Reg::StoreAlign(dstAddr + i * dstRepeatSize, dstReg, mask);
}
}

