根据源操作数和目的操作数Tensor的数据类型进行精度转换。
在介绍不同的类型转换模式之前,先介绍下浮点数的表示方式:
(-1)S * 2E - 15 * (1 + M)
当E全为0时,表示的结果为:
(-1)S * 2-14 * M
当E全为1时,若M全为0,表示的结果为±inf(取决于符号位);若M不全为0,表示的结果为nan。
上图中S=0,E=15,M = 2-1 + 2-2,表示的结果为1.75。
(-1)S * 2E - 127 * (1 + M)
当E全为0时,表示的结果为:
(-1)S * 2-126 * M
当E全为1时,若M全为0,表示的结果为±inf(取决于符号位);若M不全为0,表示的结果为nan。
上图中S = 0,E = 127,M=2-1 + 2-2,最终表示的结果为1.75 。
src类型 |
dst类型 |
类型转换模式介绍 |
---|---|---|
float |
float |
将src 按照round_mode 取整,仍以float 格式存入dst 中。 示例:输入0.5 CAST_RINT 模式输出0.0,CAST_FLOOR 模式输出0.0,CAST_CEIL 模式出1.0,CAST_ROUND 模式输出1.0,CAST_TRUNC 模式输出0.0。 |
half |
将src 按照round_mode 取到half所能表示的数,以half格式(溢出默认按照饱和处理)存入dst中。 示例:输入0.5+2-12,写成float的表示形式:2-1 * (1+2-11),因此E=-1+127=126,M=2-11: half的指数位可以表示的出2-1,有E=-1+15=14,但half只有10 bit尾数位,因此灰色部分要进行舍入。 CAST_RINT 模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5; CAST_FLOOR 模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5; CAST_CEIL 模式舍入得尾数0000000001,E=14,M=2-10,最终表示的结果为0.5+2-11; CAST_ROUND 模式舍入得尾数0000000001,E=14,M=2-10,最终表示的结果为0.5+2-11; CAST_TRUNC 模式舍入得尾数0000000000,E=14,M=0,最终表示的结果为0.5; CAST_ODD 模式舍入得尾数0000000001,E=14,M=2-10,最终表示的结果为0.5+2-11 。 |
|
int64_t |
将src按照round_mode取整,以int64_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入222+0.5 CAST_RINT 模式输出222,CAST_FLOOR 模式输出222,CAST_CEIL 模式出222 + 1,CAST_ROUND 模式输出222+1,CAST_TRUNC 模式输出222。 |
|
int32_t |
将src按照round_mode取整,以int32_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入222 + 0.5 CAST_RINT 模式输出222,CAST_FLOOR 模式输出222 ,CAST_CEIL 模式出222+1,CAST_ROUND 模式输出222+1,CAST_TRUNC 模式输出222。 |
|
int16_t |
将src按照round_mode取整,以int16_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入222+0.5 CAST_RINT 模式输出215-1,CAST_FLOOR 模式输出215-1,CAST_CEIL 模式出215-1,CAST_ROUND 模式输出215-1,CAST_TRUNC 模式输出215-1(溢出处理)。 |
|
half |
float |
将src以float格式存入dst中,不存在精度转换问题,无舍入模式。 示例:输入1.5-2-10,输出1.5-2-10 |
int32_t |
将src按照round_mode取整,以int32_t格式存入dst中。 示例:输入-1.5 CAST_RINT 模式输出-2,CAST_FLOOR 模式输出-2,CAST_CEIL 模式出-1,CAST_ROUND 模式输出-2,CAST_TRUNC 模式输出-1。 |
|
int16_t |
将src按照round_mode取整,以int16_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入27-0.5 CAST_RINT 模式输出27,CAST_FLOOR 模式输出27-1,CAST_CEIL 模式出27,CAST_ROUND 模式输出27,CAST_TRUNC 模式输出27-1。 |
|
int8_t |
将src按照round_mode取整,以int8_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入27-0.5 CAST_RINT 模式输出27-1,CAST_FLOOR 模式输出27-1,CAST_CEIL 模式出27-1,CAST_ROUND 模式输出27-1,CAST_TRUNC 模式输出27-1(溢出处理)。 |
|
uint8_t |
将src按照round_mode取整,以uint8_t格式(溢出默认按照饱和处理)存入dst中。 示例:输入1.75 CAST_RINT 模式输出2,CAST_FLOOR 模式输出1,CAST_CEIL 模式出2,CAST_ROUND 模式输出2,CAST_TRUNC 模式输出1。 |
|
uint8_t |
half |
将src以half格式存入dst中,不存在精度转换问题,无舍入模式。; 示例:输入1,输出1.0 |
int8_t |
half |
将src以half格式存入dst中,不存在精度转换问题,无舍入模式。 示例:输入-1,输出-1.0 |
int16_t |
half |
将src按照round_mode取到half所能表示的数,以half格式存入dst中。 示例:输入212+2,写成half的表示形式:212 * (1+2-11),要求E=12+15=27,M=2-11: 由于half只有10 bit尾数位,因此灰色部分要进行舍入。 CAST_RINT 模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为212; CAST_FLOOR 模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为212; CAST_CEIL 模式舍入得尾数0000000001,E=27,M=2-10,最终表示的结果为212+4; CAST_ROUND 模式舍入得尾数0000000001,E=27,M=2-10,最终表示的结果为212+4; CAST_TRUNC 模式舍入得尾数0000000000,E=27,M=0,最终表示的结果为212。 |
float |
将src以float格式存入dst中,不存在精度转换问题,无舍入模式。 示例:输入215-1,输出215-1 |
|
int32_t |
float |
将src按照round_mode取到float所能表示的数,以float格式存入dst中。 示例:输入225+3,写成float的表示形式:225 * (1+2-24+2-25),要求E=25+127=152, M=2-24+2-25: 由于float只有23 bit尾数位,因此灰色部分要进行舍入。 CAST_RINT 模式舍入得尾数00000000000000000000001,E=152,M=2-23,最终表示的结果为225+4; CAST_FLOOR 模式舍入得尾数00000000000000000000000,E=152,M=0,最终表示的结果为225; CAST_CEIL 模式舍入得尾数00000000000000000000001,E=152,M=2-23,最终表示的结果为225+4; CAST_ROUND 模式舍入得尾数00000000000000000000001,E=152,M=2-23,最终表示的结果为225+4; CAST_TRUNC 模式舍入得尾数00000000000000000000000,E=152,M=0,最终表示的结果为225 。 |
int64_t |
将src以int64_t格式存入dst中,不存在精度转换问题,无舍入模式。 示例:输入231-1,输出231-1 |
|
int16_t |
将src以int16_t格式(溢出默认按照饱和处理)存入dst中,不存在精度转换问题,无舍入模式。 示例:输入231-1,输出215-1 |
|
int64_t |
int32_t |
将src以int32_t格式(溢出默认按照饱和处理)存入dst中,不存在精度转换问题,无舍入模式。 示例:输入231,输出231-1 |
float |
将src按照round_mode取到float所能表示的数,以float格式存入dst中。 示例:输入235+212+211,写成float的表示形式:235 * (1+2-23+2-24),要求E=35+127=162,M=2-23+2-24: 由于float只有23 bit尾数位,因此灰色部分要进行舍入。 CAST_RINT 模式舍入得尾数00000000000000000000010,E=162,M=2-22,最终表示的结果为235+213; CAST_FLOOR 模式舍入得尾数00000000000000000000001,E=162,M=2-23,最终表示的结果为225+212; CAST_CEIL模式舍入得尾数00000000000000000000010,E=162,M=2-22,最终表示的结果为225+213; CAST_ROUND模式舍入得尾数00000000000000000000010,E=162,M=2-22,最终表示的结果为225+213; CAST_TRUNC模式舍入得尾数00000000000000000000001,E=162,M=2-23,最终表示的结果为225+212。 |
接口级别 |
原型定义 |
---|---|
0级接口 |
|
2级接口 |
template <typename T1, typename T2> __aicore__ inline void Cast(const LocalTensor<T1>& dstLocal, const LocalTensor<T2>& srcLocal, const RoundMode& round_mode, uint32_t calCount); |
参数名 |
输入/输出 |
描述 |
---|---|---|
dstLocal |
输出 |
目的操作数。 类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 Atlas 训练系列产品,支持的数据类型见表5 Atlas推理系列产品AI Core,支持的数据类型见表6 Atlas A2训练系列产品,支持的数据类型见表7 |
srcLocal |
输入 |
源操作数。 类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 Atlas 训练系列产品,支持的数据类型见表5 Atlas推理系列产品AI Core,支持的数据类型见表6 Atlas A2训练系列产品,支持的数据类型见表7 |
round_mode |
输入 |
精度转换处理模式,类型是RoundMode。 RoundMode为枚举类型,用以控制精度转换处理模式,具体定义为: enum class RoundMode { CAST_NONE = 0, // 在转换有精度损失时表示CAST_RINT模式,不涉及精度损失时表示不取整 CAST_RINT, // rint,四舍六入五成双取整 CAST_FLOOR, // floor,向负无穷取整 CAST_CEIL, // ceil,向正无穷取整 CAST_ROUND, // round,四舍五入取整 CAST_TRUNC, // trunc,向零取整 CAST_ODD, // Von Neumann rounding,最近邻奇数取整 }; 对于Atlas 训练系列产品,CAST_ROUND表示反向0取整,远离0,对正数 x.y 变成(x+1),对负数 -x.y,变成 -(x+1)。 |
mask |
输入 |
mask用于控制每次迭代内参与计算的元素。
|
repeatTimes |
输入 |
重复迭代次数。矢量计算单元,每次读取连续的256 Bytes数据进行计算,为完成对输入数据的处理,必须通过多次迭代(repeat)才能完成所有数据的读取与计算。repeatTimes表示迭代的次数。关于该参数的具体描述请参考重复迭代次数-Repeat times。 |
UnaryRepeatParams |
输入 |
控制操作数地址步长的数据结构。结构体内包含操作数相邻迭代间相同block的地址步长,操作数同一迭代内不同block的地址步长等参数。 该数据结构的定义请参考UnaryRepeatParams。 相邻迭代间相同block的地址步长参数的详细说明请参考相邻迭代间相同block的地址步长;同一迭代内不同block的地址步长参数请参考同一迭代内不同block的地址步长。 |
参数名 |
输入/输出 |
描述 |
---|---|---|
dstLocal |
输出 |
目的操作数。 类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 Atlas 训练系列产品,支持的数据类型见表5 Atlas推理系列产品AI Core,支持的数据类型见表6 Atlas A2训练系列产品,支持的数据类型见表7 |
srcLocal |
输入 |
源操作数。 类型为LocalTensor,支持的TPosition为VECIN/VECCALC/VECOUT。 Atlas 训练系列产品,支持的数据类型见表5 Atlas推理系列产品AI Core,支持的数据类型见表6 Atlas A2训练系列产品,支持的数据类型见表7 |
round_mode |
输入 |
精度转换处理模式,类型是RoundMode。 RoundMode为枚举类型,用以控制精度转换处理模式,具体定义为: enum class RoundMode { CAST_NONE = 0, // 在转换有精度损失时表示CAST_RINT模式,不涉及精度损失时表示不取整 CAST_RINT, // rint,四舍六入五成双取整 CAST_FLOOR, // floor,向负无穷取整 CAST_CEIL, // ceil,向正无穷取整(C语言ceil) CAST_ROUND, // round,四舍五入取整 CAST_TRUNC, // trunc,向零取整 CAST_ODD, // Von Neumann rounding,最近邻奇数取整 }; |
calCount |
输入 |
输入数据元素个数。 |
src 数据类型 |
dst 数据类型 |
roundMode supported |
---|---|---|
half |
float |
CAST_NONE |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
|
int8_t |
CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
|
uint8_t |
CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
|
float |
half |
CAST_NONE, CAST_ODD |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
|
uint8_t |
half |
CAST_NONE |
int8_t |
half |
CAST_NONE |
int32_t |
float |
CAST_NONE |
src数据类型 |
dst数据类型 |
roundMode supported |
halfBlock |
---|---|---|---|
half |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
int16_t |
CAST_RINT |
None |
|
float |
CAST_NONE |
None |
|
int8_t |
CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
|
uint8_t |
CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
|
float |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
half |
CAST_NONE, CAST_ODD |
None |
|
uint8_t |
half |
CAST_NONE |
None |
int8_t |
half |
CAST_NONE |
None |
int16_t |
half |
CAST_NONE |
None |
int32_t |
float |
CAST_NONE |
None |
src数据类型 |
dst数据类型 |
roundMode supported |
halfBlock |
---|---|---|---|
half |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
int16_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
|
float |
CAST_NONE |
None |
|
int8_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
|
uint8_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
|
float |
float |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
|
half |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_ODD, CAST_NONE |
None |
|
int64_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
|
int16_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
|
float |
bfloat16_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
bfloat16_t |
float |
CAST_NONE |
None |
int32_t |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
|
uint8_t |
half |
CAST_NONE |
None |
int8_t |
half |
CAST_NONE |
None |
int16_t |
half |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
float |
CAST_NONE |
None |
|
int32_t |
float |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC, CAST_NONE |
None |
int16_t |
CAST_NONE |
None |
|
int64_t |
CAST_NONE |
None |
|
int64_t |
int32_t |
CAST_NONE |
None |
float |
CAST_RINT, CAST_FLOOR, CAST_CEIL, CAST_ROUND, CAST_TRUNC |
None |
无
Atlas 训练系列产品
Atlas推理系列产品AI Core
Atlas A2训练系列产品
本样例中只展示Compute流程中的部分代码。本样例的srcLocal为half类型,dstLocal为int32_t类型,计算mask时以int32_t为准。
如果您需要运行样例代码,请将该代码段拷贝并替换样例模板中Compute函数的部分代码即可。
uint64_t mask = 256 / sizeof(int32_t); // repeatTimes = 8, 64 elements one repeat, 512 elements total // dstBlkStride, srcBlkStride = 1, no gap between blocks in one repeat // dstRepStride, srcRepStride = 8, no gap between repeats Cast(dstLocal, srcLocal, RoundMode::CAST_CEIL, mask, 8, { 1, 1, 8, 8 });
uint64_t mask[2] = { 0, UINT64_MAX }; // repeatTimes = 8, 64 elements one repeat, 512 elements total // dstBlkStride, srcBlkStride = 1, no gap between blocks in one repeat // dstRepStride, srcRepStride = 8, no gap between repeats Cast(dstLocal, srcLocal, RoundMode::CAST_CEIL, mask, 8, { 1, 1, 8, 8 });
Cast(dstLocal, srcLocal, RoundMode::CAST_CEIL, 512);
结果示例如下:
输入数据(srcLocal): [6.938 -8.86 -0.2263 ... 1.971 1.778] 输出数据(dstLocal): [7 -8 0 ... 2 2]
为了方便您快速运行指令中的参考样例,本章节提供样例模板。
#include "kernel_operator.h" namespace AscendC { class KernelCast { public: __aicore__ inline KernelCast() {} __aicore__ inline void Init(__gm__ uint8_t* srcGm, __gm__ uint8_t* dstGm) { srcGlobal.SetGlobalBuffer((__gm__ half*)srcGm); dstGlobal.SetGlobalBuffer((__gm__ int32_t*)dstGm); pipe.InitBuffer(inQueueSrc, 1, 512 * sizeof(half)); pipe.InitBuffer(outQueueDst, 1, 512 * sizeof(int32_t)); } __aicore__ inline void Process() { CopyIn(); Compute(); CopyOut(); } private: __aicore__ inline void CopyIn() { LocalTensor<half> srcLocal = inQueueSrc.AllocTensor<half>(); DataCopy(srcLocal, srcGlobal, 512); inQueueSrc.EnQue(srcLocal); } __aicore__ inline void Compute() { LocalTensor<half> srcLocal = inQueueSrc.DeQue<half>(); LocalTensor<int32_t> dstLocal = outQueueDst.AllocTensor<int32_t>(); Cast(dstLocal, srcLocal, RoundMode::CAST_CEIL, 512); outQueueDst.EnQue<int32_t>(dstLocal); inQueueSrc.FreeTensor(srcLocal); } __aicore__ inline void CopyOut() { LocalTensor<int32_t> dstLocal = outQueueDst.DeQue<int32_t>(); DataCopy(dstGlobal, dstLocal, 512); outQueueDst.FreeTensor(dstLocal); } private: TPipe pipe; TQue<QuePosition::VECIN, 1> inQueueSrc; TQue<QuePosition::VECOUT, 1> outQueueDst; GlobalTensor<half> srcGlobal; GlobalTensor<int32_t> dstGlobal; }; } // namespace AscendC extern "C" __global__ __aicore__ void cast_simple_kernel(__gm__ uint8_t* srcGm, __gm__ uint8_t* dstGm) { AscendC::KernelCast op; op.Init(srcGm, dstGm); op.Process(); }
更多地,您可以参考以下样例,了解如何使用Cast指令的0级接口,进行更灵活的操作、实现更高级的功能。
如果您需要运行样例代码,请将代码段拷贝并替换单目指令样例模板中Compute函数的加粗部分代码即可。
uint64_t mask = 32; // 每个迭代内只计算前32个数 Cast(dstLocal, srcLocal, mask, 8, { 1, 1, 8, 8 });
结果示例如下:
输入数据(srcLocal): [1.0 2.0 3.0 ... 512.0] 输出数据(dstLocal): [1 2 3 ... 32 undefined ... undefined 65 66 67 ... 96 undefined ... undefined 129 130 131 ... 160 undefined ... undefined 193 194 195 ... 224 undefined ... undefined 257 258 259 ... 288 undefined ... undefined 321 322 323 ... 352 undefined ... undefined 385 386 387 ... 416 undefined ... undefined 449 450 451 ... 480 undefined ... undefined]