矢量计算
SIMD指令执行模型
单指令多数据流指令,指单条指令可以完成多个数据操作。昇腾AI处理器的SIMD指令的基本操作单位分布在空间和时间两个维度,其中空间上会进行分组(以block为单位),时间上会进行迭代(迭代单位为repeat)。一般1个block为32B,包括16个float16/uint16/int16、8个float32/uint32/int32或32个int8/uint8的elements。
相邻repeat内的相同block的偏移只支持线性模式,即用户需要指定下次repeat每个block的地址偏移。
TIK的SIMD指令主要的操作数为Tensor,少量操作数为标量(Scalar/立即数)。按照数据流,可分为按element操作与归约(以下称为Reduce)操作,前者根据源操作数的数目(计入标量操作数)可分为单目、双目与三目指令。
单目(Gather模式)
通用定义
功能说明
此为仅有一个源操作数时指令的通用格式。注:这不是真正的指令。
函数原型
instruction (mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
PIPE: VECTOR
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,TIK DSL中为全小写字符串。 |
mask |
输入 |
element操作有效指示,共128bits,每一个bit位用来表示vector的每个元素是否参与操作,bit位的值为1表示参与计算,0表示不参与计算。 支持的模式分为连续、逐bits两种。
注:mask应用于每个迭代的源操作数。 |
dst |
输出 |
目的操作数,tensor起始element,支持数据精度见具体指令。 |
src |
输入 |
源操作数,tensor起始element,支持数据精度见具体指令。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。 |
注意事项
- repeat_times∈[0,255]。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64),当repeat_times为立即数时,不支持0。
- 每个repeat的并行度取决于数据类型、芯片版本,以下以PAR代表并行度。
- dst_rep_stride/src_rep_stride
;单位为32B;支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst/src应声明在scope_ubuf中,且所支持的数据类型与芯片版本有关,如果不支持,工具会报错。
- dst和src的数据类型应一致。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),各指令通用约束如下,具体以各指令约束为准。
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
vec_relu
功能说明
按element做线性整流Relu:。
线性整流函数(Rectified Linear Unit, ReLU激活函数),又称修正线性单元,是一种人工神经网络中常用的激活函数。
函数原型
vec_relu(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_relu(128, dst_ub, src_ub, 1, 8, 8)
vec_abs
功能说明
按element取绝对值:
函数原型
vec_abs(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_abs(128, dst_ub, src_ub, 1, 8, 8)
vec_not
功能说明
每个element按位取反:
函数原型
vec_not(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("uint16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("uint16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_not(128, dst_ub, src_ub, 1, 8, 8)
vec_exp
功能说明
按element取自然指数:。
函数原型
vec_exp(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
- 对于昇腾310 AI处理器,如果ex满足精度要求,但使用该接口计算ex - 1时,当输入float16类型的数据时,计算精度可能不满足双千分之一(这是因为减法有误差),如果对ex - 1精度有更高要求,建议使用vec_expm1_high_preci接口。
- 其他注意事项请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_gm = tik_instance.Tensor("float16", (128,), name="dst_gm", scope=tik.scope_gm) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.data_move(src_ub, src_gm, 0, 1, 8, 0, 0) tik_instance.vec_exp(128, dst_ub, src_ub, 1, 8, 8) tik_instance.data_move(dst_gm, dst_ub, 0, 1, 8, 0, 0) tik_instance.BuildCCE(kernel_name="exp", inputs=[src_gm], outputs=[dst_gm]) 输入数据: [0, 1, 2, 3, ......] 输出数据: [1.0, 2.719, 7.391, 20.08, ......]
vec_expm1_high_preci
功能说明
按element取自然底数:。
函数原型
vec_expm1_high_preci(mask, dst, src, work_tensor, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
请参见参数说明。下面仅对dst/src/work_tensor参数进行说明:
dst/src/work_tensor数据类型保持一致,支持的数据类型为:Tensor(float16)
- 如果传入tensor带有偏移,则作为参数传入时应写成tensor[offset1:offset2],表示从offset1开始到offset2结束,也可以写成tensor[offset1:],表示从offset1开始;如果仅仅输入tensor[offset],代表仅传入一个元素,该接口内部实现过程中会对tensor进行切片,无法切分一个元素,运行时可能会产生错误,因此不支持该形式;
- 如果传入操作数tensor不带偏移,可以直接写成tensor传入。
【work_tensor参数说明】:
work_tensor为用户定义的临时buffer空间,存储中间结果,空间限定在scope_ubuf,用于内部计算使用。
【work_tensor空间计算说明】:
- 根据repeat_times、src_rep_stride计算出src计算所需要的最小空间:src_extent_size = (repeat_times - 1)*src_rep_stride*16 + 128。如果0 < src_rep_stride <= 8,则用src_rep_stride = 8代入上式计算,否则保持原值。
- 对src最小空间进行32Byte向上取整对齐: wk_size_unit = (src_extent_size+15)//16*16
- 计算work_tensor大小:11*wk_size_unit
【work_tensor空间计算举例】:
- 如果repeat_times=1,src_rep_stride=8,则src_extent_size=128,work_tensor大小为128 * 11。
- 如果repeat_times=2,src_rep_stride=4,则src_extent_size=(2-1)*8*16 + 128 = 256,work_tensor大小为256 * 11。
注意事项
返回值
无
调用示例
from te import tik tik_instance = tik.Tik() src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_gm = tik_instance.Tensor("float16", (128,), name="dst_gm", scope=tik.scope_gm) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) # 所需空间为 ((1-1)*8*16+128)*11=128*11 work_tensor_ub = tik_instance.Tensor("float16", (128*11,), name="work_tensor_ub", scope=tik.scope_ubuf) tik_instance.data_move(src_ub, src_gm, 0, 1, 8, 0, 0) tik_instance.vec_expm1_high_preci(128, dst_ub, src_ub, work_tensor_ub, 1, 8, 8) tik_instance.data_move(dst_gm, dst_ub, 0, 1, 8, 0, 0) tik_instance.BuildCCE(kernel_name="expm1", inputs=[src_gm], outputs=[dst_gm]) 输入数据: [0, 1, 2, 3, ......] 输出数据: [0.0, 1.719, 6.391, 19.08, ......]
vec_ln
功能说明
按element取自然对数:。
函数原型
vec_ln(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无。
注意事项
- 如果src的数值为非正数,可能会产生未知结果。
- 对于昇腾310 AI处理器,使用该接口处理float16类型的数据时,如果输入数据在(0, 5/3)区间,计算精度不满足双千分之一,如果对精度有更高要求,建议使用vec_ln_high_preci接口。
- 其它注意事项请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() # 申请tensor src_gm = tik_instance.Tensor("float16", (128,), tik.scope_gm, "src_gm") src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) dst_gm = tik_instance.Tensor("float16", (128,), tik.scope_gm, "dst_gm") # 拷贝用户输入数据到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 8, 0, 0) tik_instance.vec_ln(128, dst_ub, src_ub, 1, 8, 8) # 将计算结果拷贝到目标gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 8, 0, 0) tik_instance.BuildCCE("v100_mini_vec_ln_test", [src_gm], [dst_gm]) 输入数据: [1, 2, 3, 4, ......, 128] 输出数据: [0, 0.6931, 1.0986, 1.3863, ......, 4.8520]
vec_ln_high_preci
功能说明
按element取自然对数:。
函数原型
vec_ln_high_preci(mask, dst, src, work_tensor, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
请参见参数说明。下面仅对dst/src/work_tensor参数进行说明:
dst/src/work_tensor数据类型保持一致,支持的数据类型为Tensor(float16)。
- 如果传入tensor带有偏移,则作为参数传入时应写成tensor[offset1:offset2],表示从offset1开始到offset2结束,也可以写成tensor[offset1:],表示从offset1开始;如果仅仅输入tensor[offset],代表仅传入一个元素,该接口内部实现过程中会对tensor进行切片,无法切分一个元素,运行时可能会产生错误,因此不支持该形式;
- 如果传入操作数tensor不带偏移,可以直接写成tensor传入。
【work_tensor参数说明】:
work_tensor为用户定义的临时buffer空间,存储中间结果,空间限定在scope_ubuf,用于内部计算使用。
【work_tensor空间计算说明】:
- 根据repeat_times、mask、src_rep_stride计算出src所需要的最小空间:src_extent_size = (repeat_times - 1)*src_rep_stride*16 + mask_len
如果mask是连续模式,mask_len即为mask值;如果mask为逐bit模式,mask_len为最高有效位的位数值。
- 对src最小空间进行32Byte向上取整对齐: wk_size_unit = (src_extent_size+15)//16*16
- 计算work_tensor大小: 10*wk_size_unit
【work_tensor空间计算举例】:
- 如果mask = 128,rep_times = 2,src_rep_stride = 8,则对应的mask_len = 128, src_extent_size = (2 - 1)*8*16 + mask_len = 256,wk_size_unit = (src_extent_size + 15)//16*16 = 256,最后计算work_tensor需要的空间大小为 10*wk_size_unit = 2560。
- 如果mask = [3, 2**64-1], rep_times = 2,src_rep_stride = 8,则对应的mask_len = 66,mask高位是3,对应的二进制bit位为"11",所以mask_len = 2 + 64;src_extent_size = (2 - 1)*8*16 + mask_len = 194,wk_size_unit = (src_extent_size + 15)//16*16 = 208,最后计算work_tensor需要的空间大小为10*wk_size_unit= 2080。
返回值
无。
注意事项
调用示例
(1)mask连续模式
from te import tik tik_instance = tik.Tik() kernel_name = "vln_rep_8_src_rep_8" # 定义计算tensor src_gm = tik_instance.Tensor("float16", (2, 128), tik.scope_gm, "src_gm") src_ub = tik_instance.Tensor("float16", (2, 128), tik.scope_ubuf, "src_ub") dst_ub = tik_instance.Tensor("float16", (2, 128), tik.scope_ubuf, "dst_ub") # work_tensor大小为src大小的10倍 work_tensor = tik_instance.Tensor("float16", (10, 2, 128), tik.scope_ubuf, "work_tensor") dst_gm = tik_instance.Tensor("float16", (2, 128), tik.scope_gm, "dst_gm") # 将输入数据拷贝到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 16, 0, 0) tik_instance.vec_dup(128, dst_ub, 0.0, 2, 8) mask = 128 rep_times = 2 src_rep_stride = 8 dst_rep_stride = 8 # 如果输入work_tensor有索引需要写成work_tensor[index:] tik_instance.vec_ln_high_preci(mask, dst_ub, src_ub, work_tensor[0:], rep_times, dst_rep_stride, src_rep_stride) # 数据搬移到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 16, 0, 0) tik_instance.BuildCCE(kernel_name, [src_gm], [dst_gm]) 输入数据: [ [1, 2, 3, 4, ......, 128], [1, 2, 3, 4, ......, 128] ] 输出结果: [ [0, 0.6931, 1.0986, 1.3863, ......, 4.8520], [0, 0.6931, 1.0986, 1.3863, ......, 4.8520] ]
(2)mask逐bit模式
from te import tik tik_instance = tik.Tik() kernel_name = "vln_rep_8_src_rep_8" # 申请需要的tensor src_gm = tik_instance.Tensor("float16", (2, 128), tik.scope_gm, "src_gm") src_ub = tik_instance.Tensor("float16", (2, 128), tik.scope_ubuf, "src_ub") dst_ub = tik_instance.Tensor("float16", (2, 128), tik.scope_ubuf, "dst_ub") # 计算work_tensor大小 rep_times = 2 src_rep_stride = 8 dst_rep_stride = 8 mask = [3, 2**64-1] mask_len = 66 src_extent_size = (rep_times - 1)*src_rep_stride*16 + mask_len wk_size_unit = (src_extent_size + 15)//16*16 wk_size = 10*wk_size_unit work_tensor = tik_instance.Tensor("float16", (wk_size, ), tik.scope_ubuf, "work_tensor") dst_gm = tik_instance.Tensor("float16", (2, 128,), tik.scope_gm, "dst_gm") # 将用户输入数据拷贝到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 16, 0, 0) # 初始化dst ubuf空间 tik_instance.vec_dup(128, dst_ub, 0.0, 2, 8) tik_instance.vec_ln_high_preci(mask, dst_ub, src_ub, work_tensor, rep_times, dst_rep_stride, src_rep_stride) # 将计算结果拷贝到目标gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 16, 0, 0) tik_instance.BuildCCE(kernel_name, [src_gm], [dst_gm]) 输入数据: [ [1, 2, 3, 4, ......, 65, 66, 67, ......, 128], [1, 2, 3, 4, ......, 65, 66, 67, ......, 128] ] 输出数据: [ [0, 0.6931, 1.0986, 1.3863, ......, 4.1744, 4.1897, 0, ......, 0], [0, 0.6931, 1.0986, 1.3863, ......, 4.1744, 4.1897, 0, ......, 0] ]
vec_rec
功能说明
按element取倒数:。
函数原型
vec_rec(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
支持的产品形态
昇腾310 AI处理器
昇腾910 AI处理器
海思SoC-es
海思SoC-cs
昇腾710 AI处理器AI Core
昇腾710 AI处理器Vector Core
昇腾610 AI处理器AI Core
昇腾610 AI处理器Vector Core
昇腾615 AI处理器AI Core
注意事项
- 如果src的数值为0,可能会产生未知结果。
- 对于昇腾310 AI处理器,使用该接口处理float16类型的数据时,计算精度不满足双千分之一,如果对精度有更高要求,建议使用vec_rec_high_preci接口;使用该接口处理float32类型的数据时,计算精度不满足双万分之一,如果对精度有更高要求,建议使用vec_rec_high_preci接口。
- 其他注意事项请参考注意事项。
调用示例1
from te import tik # 定义容器 tik_instance = tik.Tik() # 定义计算tensor src_gm = tik_instance.Tensor("float32", (128,), name="src_gm", scope=tik.scope_gm) dst_gm = tik_instance.Tensor("float32", (128,), name="dst_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float32", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float32", (128,), name="dst_ub", scope=tik.scope_ubuf) # 数据从gm搬运到ub tik_instance.data_move(src_ub, src_gm, 0, 1, 128*4 // 32, 0, 0) tik_instance.vec_rec(64, dst_ub, src_ub, 2, 8, 8) # 数据从ub搬运到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*4 // 32, 0, 0) tik_instance.BuildCCE(kernel_name="vec_rec", inputs=[src_gm], outputs=[dst_gm]) 输入: [1.2017815 -8.758528 -3.9551935 ... -1.3599057 -2.319316] 输出: [0.83203125 -0.11401367 -0.2529297 ... -0.734375 -0.43164062]
调用示例2
from te import tik # 定义容器 tik_instance = tik.Tik() # 定义计算tensor src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) dst_gm = tik_instance.Tensor("float16", (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("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) # 数据从gm搬运到ub tik_instance.data_move(src_ub, src_gm, 0, 1, 128*2 // 32, 0, 0) tik_instance.vec_rec(128, dst_ub, src_ub, 1, 8, 8) # 数据从ub搬运到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*2 // 32, 0, 0) tik_instance.BuildCCE(kernel_name="vec_rec", inputs=[src_gm], outputs=[dst_gm]) 输入: [-7.152 -7.24 1.771 ... -1.339 4.473] 输出: [-0.1396 -0.1382 0.5645 ... -0.748 0.2231]
vec_rec_high_preci
功能说明
按element取倒数:。
函数原型
vec_rec_high_preci(mask, dst, src, work_tensor, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
请参见参数说明。下面仅对dst/src/work_tensor参数进行说明:
dst与src的数据类型需要保持一致,支持的数据类型为:Tensor(float16/float32);work_tensor支持的数据类型为Tensor(float32)。
- 如果传入tensor带有偏移,则作为参数传入时应写成tensor[offset1:offset2],表示从offset1开始到offset2结束,也可以写成tensor[offset1:],表示从offset1开始;如果仅仅输入tensor[offset],代表仅传入一个元素,该接口内部实现过程中会对tensor进行切片,无法切分一个元素,运行时可能会产生错误,因此不支持该形式;
- 如果传入操作数tensor不带偏移,可以直接写成tensor传入。
【work_tensor参数说明】:
work_tensor为用户定义的临时buffer空间,存储中间结果,空间限定在scope_ubuf,用于内部计算使用。
【work_tensor空间计算说明】:
- 根据repeat_times、mask、src_rep_stride计算出src计算所需要的最小空间:src_extent_size = (repeat_times - 1)*src_rep_stride*block_len + mask_len
当源操作数数据类型为float16时,block_len=16;
当源操作数数据类型为float32时,block_len=8;
当mask是连续模式时,mask_len 即mask值;
当mask为逐bits模式时,mask_len为最高有效位的位数值。
- 对src最小空间进行32Byte向上取整对齐: wk_size_unit = ((src_extent_size+block_len-1)//block_len)*block_len
- 计算work_tensor大小:
当源操作数数据类型为float16时,则work_tensor需要申请的大小为4*wk_size_unit
当源操作数数据类型为float32时,则work_tensor需要申请的大小为2*wk_size_unit
【work_tensor空间计算举例】:
- 如果src的dtype为float16,mask为128,repeat_times为2,src_rep_stride为8,则block_len=16,mask_len=128,src_extent_size=(2-1)*8*16+128=256;对src_extent_size进行32Byte对齐,wk_size_unit=((256+16-1)//16)*16=256;则work_tensor申请的空间大小为4*256=1024。
- 如果src的dtype为float32,mask为64,repeat_times为2,src_rep_stride为8,则block_len=8,mask_len=64,src_extent_size=(2-1)*8*8+64=128;对src_extent_size进行32Byte对齐,wk_size_unit=((128+8-1)//8)*8=128;则work_tensor申请的空间大小为2*128=256。
注意事项
返回值
无
调用示例1
from te import tik # 定义容器 tik_instance = tik.Tik() # 定义计算tensor src_gm = tik_instance.Tensor("float32", (128,), name="src_gm", scope=tik.scope_gm) dst_gm = tik_instance.Tensor("float32", (128,), name="dst_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float32", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float32", (128,), name="dst_ub", scope=tik.scope_ubuf) # 数据从gm搬运到ub tik_instance.data_move(src_ub, src_gm, 0, 1, 128*4 // 32, 0, 0) # 计算work_tensor大小 mask = [0, 2**64 - 1] mask_len = 64 repeat_times = 2 dst_rep_stride = 8 src_rep_stride = 8 block_len = 8 # src dtype is float32 src_extent_size = (repeat_times - 1)*src_rep_stride*block_len + mask_len wk_size_unit = ((src_extent_size + block_len - 1)//block_len) *block_len wk_size = 2*wk_size_unit # 定义work_tensor work_tensor_ub = tik_instance.Tensor("float32", (wk_size,), name="work_tensor_ub", scope=tik.scope_ubuf) # 如果work_tensor有索引,需要写成work_tensor[index:] tik_instance.vec_rec_high_preci(mask_len, dst_ub, src_ub, work_tensor_ub[0:], repeat_times, dst_rep_stride, src_rep_stride) # 数据从ub搬运到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*4 // 32, 0, 0) tik_instance.BuildCCE(kernel_name="test_vec_rec_high_preci", inputs=[src_gm], outputs=[dst_gm]) 输入: [-6.9427586 -3.5300326 1.176882 ... -6.196793 9.0379095] 输出: [-0.14403497 -0.2832835 0.8497028 ... -0.16137381 0.11064506]
调用示例2
from te import tik # 定义容器 tik_instance = tik.Tik() # 定义计算tensor src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) dst_gm = tik_instance.Tensor("float16", (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("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) # 数据从gm搬运到ub tik_instance.data_move(src_ub, src_gm, 0, 1, 128*2 // 32, 0, 0) # 计算work_tensor大小 mask = 128 mask_len = mask repeat_times = 1 dst_rep_stride = 8 src_rep_stride = 8 block_len = 16 # src dtype is float16 src_extent_size = (repeat_times - 1)*src_rep_stride*block_len + mask_len wk_size_unit = ((src_extent_size + block_len - 1) // block_len)*block_len wk_size = 4*wk_size_unit # 定义work_tensor work_tensor_ub = tik_instance.Tensor("float32", (wk_size,), name="work_tensor_ub", scope=tik.scope_ubuf) # 如果work_tensor有索引,需要写成work_tensor[index:] tik_instance.vec_rec_high_preci(mask_len, dst_ub, src_ub, work_tensor_ub[0:], repeat_times, dst_rep_stride, src_rep_stride) # 数据从ub搬运到gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*2 // 32, 0, 0) tik_instance.BuildCCE(kernel_name="test_vec_rec_high_preci", inputs=[src_gm], outputs=[dst_gm]) 输入: [-7.08 -4.434 1.294 ... 8.82 -2.854] 输出: [-0.1412 -0.2256 0.773 ... 0.1134 -0.3503]
vec_rsqrt
功能说明
按element做开方后,再取倒数:。
函数原型
vec_rsqrt(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
- 如果src的数值为非正数,可能会产生未知结果。
- 对于昇腾310 AI处理器,使用该接口处理float16类型的数据时,计算精度不满足双千分之一;使用该接口处理float32类型的数据时,计算精度不满足双万分之一,如果对精度有更高要求,建议使用vec_rsqrt_high_preci接口。
- 其他注意事项请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() # 申请tensor src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) dst_gm = tik_instance.Tensor("float16", (128,), name="dst_gm", scope=tik.scope_gm) # 拷贝用户输入数据到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 8, 0, 0) tik_instance.vec_rsqrt(128, dst_ub, src_ub, 1, 8, 8) # 将计算结果拷贝到目标gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 8, 0, 0) tik_instance.BuildCCE("test_vec_rsqrt", [src_gm], [dst_gm]) 输入数据: [1, 2, 3, 4, ......, 128] 输出数据: [0.998, 0.705, 0.576, 0.499, ......, 0.08813]
vec_rsqrt_high_preci
功能说明
按element做开方后,再取倒数:。
函数原型
vec_rsqrt_high_preci(mask, dst, src, work_tensor, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
请参见参数说明。下面仅对dst/src/work_tensor参数进行说明:
dst与src的数据类型需要保持一致,支持的数据类型为:Tensor(float16/float32);work_tensor支持的数据类型为Tensor(float32)。
- 如果传入tensor带有偏移,则作为参数传入时应写成tensor[offset1:offset2],表示从offset1开始到offset2结束,也可以写成tensor[offset1:],表示从offset1开始;如果仅仅输入tensor[offset],代表仅传入一个元素,该接口内部实现过程中会对tensor进行切片,无法切分一个元素,运行时可能会产生错误,因此不支持该形式;
- 如果传入操作数tensor不带偏移,可以直接写成tensor传入。
【work_tensor参数说明】:
work_tensor为用户定义的临时buffer空间,存储中间结果,空间限定在scope_ubuf,用于内部计算使用。
【work_tensor空间计算说明】:
- 根据repeat_times、mask、src_rep_stride计算出src计算所需要的最小空间:src_extent_size = (repeat_times- 1)*src_rep_stride*block_len + mask_len
当源操作数数据类型为float16时,block_len=16;
当源操作数数据类型为float32时,block_len=8;
当mask是连续模式,mask_len 即mask值;
当mask为逐bits模式,mask_len为最高有效位的位数值。
- 对src最小空间进行32B向上取整对齐: wk_size_unit = ((src_extent_size+block_len-1)//block_len)*block_len
- 计算work_tensor大小:
对于昇腾310 AI处理器:当源操作数数据类型为float16时,则work_tensor需要申请的大小为6*wk_size_unit;当源操作数数据类型为float32时,则work_tensor需要申请的大小为4*wk_size_unit。例如当src数据类型为float16,mask = 128, repeat_times=2, src_rep_stride=8时,block_len=16, mask_len=128, src_extent_size=(2-1)*8*16+128=256;对src_extent_size进行32Byte对齐后wk_size_unit=256;则work_tensor申请的空间大小为6*256=1536。
返回值
无
注意事项
调用示例1
from te import tik tik_instance = tik.Tik() # 定义tensor dst_gm = tik_instance.Tensor("float16", (128,), name="dst_gm", scope=tik.scope_gm) src_gm = tik_instance.Tensor("float16", (128,), name="src_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) # 拷贝输入数据到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 128*2 // 32, 0, 0) mask = 128 mask_len = mask # mask 是连续模式,mask_len则等于mask的值 repeat_times = 1 dst_rep_stride = 8 src_rep_stride = 8 block_len = 16 # src dtype is float16 src_extent_size = (repeat_times - 1)*src_rep_stride*block_len + mask_len wk_size_unit = ((src_extent_size + block_len - 1) // block_len)*block_len wk_size = 6*wk_size_unit # 得到work_tensor的大小 # 申请work_tensor work_tensor = tik_instance.Tensor("float32", (wk_size ,), name="work_tensor", scope=tik.scope_ubuf) # 指令传入tensor时,若有下标偏移请按照如下格式传入,在下标后加':'符号;否则可能导致程序报错 tik_instance.vec_rsqrt_high_preci(mask, dst_ub, src_ub, work_tesnor[0:], repeat_times, dst_rep_stride, src_rep_stride) # 将计算结果拷贝到目标gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*2 // 32, 0, 0) tik_instance.BuildCCE("test_vec_rsqrt_high_preci", inputs=[src_gm], outputs=[dst_gm]) 例: 输入: src_gm= [6.996 1.381 5.996 7.902 ... 5.113 5.78 1.672 5.418 ] 输出: dst_gm: [0.3782 0.851 0.4084 0.3557 ... 0.4421 0.416 0.7734 0.4297]
调用示例2
from te import tik tik_instance = tik.Tik() # 定义tensor dst_gm = tik_instance.Tensor("float32", (128,), name="dst_gm", scope=tik.scope_gm) src_gm = tik_instance.Tensor("float32", (128,), name="src_gm", scope=tik.scope_gm) src_ub = tik_instance.Tensor("float32", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float32", (128,), name="dst_ub", scope=tik.scope_ubuf) # 拷贝输入数据到src ubuf tik_instance.data_move(src_ub, src_gm, 0, 1, 128*4 // 32, 0, 0) mask = [0, 2**64 - 1] mask_len = 64 # mask是逐bits模式,mask_len等于mask的最高有效位的位数值 repeat_times = 2 dst_rep_stride = 8 src_rep_stride = 8 block_len = 8 # src dtype is float32 src_extent_size = (repeat_times - 1)*src_rep_stride*block_len + mask_len wk_size_unit = ((src_extent_size + block_len - 1)//block_len)*block_len wk_size = 4*wk_size_unit # 得到work_tensor的大小 # 申请work_tensor work_tensor = tik_instance.Tensor("float32", (wk_size ,), name="work_tensor", scope=tik.scope_ubuf) # 指令传入tensor时,若有下标偏移请按照如下格式传入,在下标后加':'符号;否则可能导致程序报错 tik_instance.vec_rsqrt_high_preci(mask, dst_ub, src_ub, work_tesnor[0:], repeat_times, dst_rep_stride, src_rep_stride) # 将计算结果拷贝到目标gm tik_instance.data_move(dst_gm, dst_ub, 0, 1, 128*4 // 32, 0, 0) tik_instance.BuildCCE("test_vec_rsqrt_high_preci", inputs=[src_gm], outputs=[dst_gm]) 例: 输入: src_gm= [5.349619, 0.4301902, 4.7152824, 9.539162, ..., 5.7243876, 4.4785686, 7.030495, 7.489954] 输出: dst_gm: [0.43235308, 1.5246484, 0.46051747, 0.32377616, ..., 0.41796073, 0.47253108, 0.37714386, 0.36539316]
双目(Gather模式)
通用定义
功能说明
此为有两个源操作数时指令的通用格式,注:这不是真正的指令。
函数原型
instruction (mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,TIK DSL中为全小写字符串。 |
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输出 |
目的操作数,tensor起始element,支持数据类型见具体指令。 |
src0 |
输入 |
源操作数0,tensor起始element,支持数据类型见具体指令。 |
src1 |
输入 |
源操作数1,tensor起始element,支持数据类型见具体指令。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src0_rep_stride |
输入 |
相邻迭代间,源操作数0相同block地址步长。 |
src1_rep_stride |
输入 |
相邻迭代间,源操作数1相同block地址步长。 |
注意事项
- repeat_times∈[0,255]。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64),当repeat_times为立即数时,不支持0。
- 每个repeat的并行度取决于数据精度、芯片版本,以下以PAR代表并行度。
- dst_rep_stride/src0_rep_stride/src1_rep_stride
,单位为32B。支持的数据类型:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。以下情况是支持地址重叠的:对于vec_add/vec_sub/vec_mul/vec_max/v_min/vec_and/vec_or指令,当数据类型为float16,int32,float32时,且目的操作数与第二个源操作数重叠;src1_rep_stride/dst_rep_stride相等且为0;src0与src1之间不能有任何的地址重叠。
- 操作数地址偏移对齐要求请见通用约束。
vec_add
功能说明
按element求和:
函数原型
vec_add(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
请参考参数说明。
dst/src0/src1的数据类型需要保持一致。
昇腾310 AI处理器,dst/src0/src1支持的数据类型为:Tensor(float16/float32/int32)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_add(128, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_sub
功能说明
按element求差:
函数原型
vec_sub(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
请参见参数说明。
dst/src0/src1的数据类型需要保持一致。
昇腾310 AI处理器,dst/src0/src1支持的数据类型为:Tensor(float16/float32/int32)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_sub(128, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_mul
功能说明
按element求积:
函数原型
vec_mul(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
请参见参数说明。
dst/src0/src1的数据类型需要保持一致。
昇腾310 AI处理器,dst/src0/src1支持的数据类型为:Tensor(float16/float32/int32)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_mul(128, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_max
功能说明
按element求最大值:
函数原型
vec_max(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
请参见参数说明。
dst/src0/src1的数据类型需要保持一致。
昇腾310 AI处理器,dst/src0/src1支持的数据类型为:Tensor(float16/float32/int32)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float32", (64,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float32", (64,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float32", (64,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_max(64, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_min
功能说明
按element求最小值:
函数原型
vec_min(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
参数说明
请参见参数说明。
dst/src0/src1的数据类型需要保持一致。
昇腾310 AI处理器,dst/src0/src1支持的数据类型为:Tensor(float16/float32/int32)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float32", (64,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float32", (64,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float32", (64,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_min(64, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_and
功能说明
每对elements按位与运算:
函数原型
vec_and(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
返回值
无
注意事项
请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("uint16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("uint16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("uint16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_and([0, 2**64-1], dst_ub, src0_ub, src1_ub, 1, 8, 8, 8)
vec_or
功能说明
每对elements按位或运算:
函数原型
vec_or(mask, dst, src0, src1, repeat_times, dst_rep_stride, src0_rep_stride, src1_rep_stride)
返回值
无
注意事项
其他请参考注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("uint16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("uint16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("uint16", (128,), name="dst_ub", scope=tik.scope_ubuf) mask_h = tik_instance.Scalar(dtype="uint64", init_value=1) mask_l = tik_instance.Scalar(dtype="uint64", init_value=15) mask = [mask_h, mask_l] repeat_times = tik_instance.Scalar(dtype="int32", init_value=1) tik_instance.vec_or(mask, dst_ub, src0_ub, src1_ub, repeat_times, 8, 8, 8)
标量双目(Gather模式)
通用定义
功能说明
此为有两个源操作数时指令的通用格式,两个源操作数为src和标量scalar。注:这不是真正的指令。
函数原型
instruction (mask, dst, src, scalar, repeat_times, dst_rep_stride, src_rep_stride, mask_mode="normal")
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,TIK DSL中为全小写字符串。 |
mask |
输入 |
根据mask_mode,分为两种模式:
昇腾310 AI处理器,按照normal mode处理。 |
dst |
输出 |
矢量目的操作数,tensor起始element,支持数据精度见具体指令。 |
src |
输入 |
矢量源操作数,tensor起始element,支持数据精度见具体指令。 |
scalar |
输入 |
标量源操作数,支持Scalar/立即数。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,矢量目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,矢量源操作数相同block地址步长。 |
mask_mode |
输入 |
mask模式选择参数,支持的数据类型:string,取值:
昇腾310 AI处理器,该参数不生效。 |
注意事项
- repeat_times∈[0,255],支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64),当repeat_times为立即数时,不支持0。
- dst_rep_stride/src_rep_stride∈[0,255] ,单位为32B。支持的数据类型:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst和src的地址不能重叠。
- scalar参数支持Scalar/立即数(int/float)两种数据类型。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
vec_adds
功能说明
矢量内每个element与标量求和:
函数原型
vec_adds(mask, dst, src, scalar, repeat_times, dst_rep_stride, src_rep_stride, mask_mode="normal")
参数说明
请参见参数说明。
dst/src/scalar操作数的类型需要保持一致 。
昇腾310 AI处理器,dst/src/scalar支持的数据类型为:Tensor(float16/float32)。
返回值
无
注意事项
请参见注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) scalar = tik_instance.Scalar(dtype="float16", init_value=2) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_adds(128, dst_ub, src_ub, scalar, 1, 8, 8)
vec_muls
功能说明
矢量内每个element与标量求积:
函数原型
vec_muls(mask, dst, src, scalar, repeat_times, dst_rep_stride, src_rep_stride, mask_mode="normal")
参数说明
请参见参数说明。
dst/src类型需要保持一致 。scalar为Scalar时,要求和dst/src数据类型保持一致。
昇腾310 AI处理器,dst/src/scalar支持的数据类型为:Tensor(float16/float32)。
返回值
无
注意事项
请参见注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) scalar = 2 dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_muls(128, dst_ub, src_ub, scalar, 1, 8,8)
标量三目(Gather模式)
通用定义
功能说明
三个源操作数时指令的通用格式,三个源操作数分别为src, dst和标量scalar。注:这不是真正的指令。
函数原型
instruction (mask, dst, src, scalar, repeat_times, dst_rep_stride, src_rep_stride, )
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,TIK DSL中为全小写字符串。 |
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输出 |
矢量目的操作数/矢量元操作数1,tensor起始element,支持数据精度见具体指令。 |
src |
输入 |
矢量源操作数0,tensor起始element,支持数据精度见具体指令。 |
scalar |
输入 |
标量源操作数,支持Scalar/立即数 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,矢量目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,矢量源操作数相同block地址步长。 |
注意事项
- repeat_times∈[0,255]。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64),当repeat_times为立即数时,不支持0。
- dst_rep_stride/src_rep_stride
,单位为32B。支持的数据类型:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst既是目的操作数,也是源操作数。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
vec_axpy
功能说明
矢量每个element与标量求积后累加:
函数原型
vec_axpy(mask, dst, src, scalar, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
请参见参数说明。且src和scalar操作数的类型需要保持一致 。
该接口支持的精度组合如下:
类型 |
float16精度组合 |
float32精度组合 |
fix精度组合 |
---|---|---|---|
昇腾310 AI处理器支持度 |
Y |
Y |
Y |
上表中各精度组合代表的含义:
- float16精度组合:src.dtype=float16;scalar.dtype=float16;dst.dtype=float16;并行度PAR/repeat=128
- float32精度组合:src.dtype=float32;scalar.dtype=float32;dst.dtype=float32;并行度PAR/repeat=64
- fix精度组合:src.dtype=float16;scalar.dtype=float16;dst.dtype=float32;并行度PAR/repeat=64
返回值
无
注意事项
- 请参见注意事项。
- 注意存在混合精度fmix的支持。
- fmix模式下,src每次迭代仅选取前4个block参与计算。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) scalar = 2 dst_ub = tik_instance.Tensor("float32", (128,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_axpy(64, dst_ub, src_ub, scalar, 1, 8, 4)
比较/选择相关指令(Gather模式)
vec_cmpv_xx
功能说明
按element比较产生1bit结果,1'b1为真,1'b0为假,比较支持多种模式。
函数原型
vec_cmpv_xx (dst, src0, src1, repeat_times, src0_rep_stride, src1_rep_stride)
PIPE:Vector
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,支持以下几种比较:
|
dst |
输出 |
目的操作数,tensor中起始element,支持uint64, uint32, uint16和uint8。 |
src0 |
输入 |
源操作数0,tensor中起始element。 昇腾310 AI处理器,支持的数据类型为:Tensor(float16)。 |
src1 |
输入 |
源操作数1,tensor中起始element。 数据类型需保证与src0类型一致。 |
repeat_times |
输入 |
重复迭代次数。
|
src0_rep_stride |
输入 |
相邻迭代间,源操作数0相同block地址步长。 |
src1_rep_stride |
输入 |
相邻迭代间,源操作数1相同block地址步长。 |
返回值
无。
注意事项
- 无mask参数。
- dst连续产生。比如当源操作数为float16,目的操作数为uint16时,相邻迭代间dst跳8个elements;当源操作数float32,目的操作数为uint16时,跳4个elements。
- src0_rep_stride/src1_rep_stride
;单位:block;支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
调用示例
from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("uint16", (16,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_dup(16, dst_ub, 5, 1, 1) # 将dst_ub初始化为全5 tik_instance.vec_cmpv_eq(dst_ub, src0_ub, src1_ub, 1, 8, 8) """实际例子如下: 输入数据(float16): src0_ub = {1,2,3,...,128} src1_ub = {2,2,2,...,2} 输出结果: dst_ub = {2,0,0,0,0,0,0,0,5,5,5,5,5,5,5,5} """
vec_sel
功能说明
实现element选取,根据每bit进行elements选取,1'b1时从src0中选取,否则从src1选取。
函数原型
vec_sel(mask, mode, dst, sel, src0, src1, repeat_times, dst_rep_stride=0, src0_rep_stride=0, src1_rep_stride=0)
PIPE:Vector
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表12-25中mask参数描述。 |
mode |
输入 |
指令模式,支持0~2共3种模式; 0 -> 根据sel的值对两个tensor进行选取,支持多次迭代,每次迭代均依据sel的前128(目的操作数为float16类型)/64(目的操作数为float32类型)个bit位; 1 -> 根据sel中的逐个bit,对一个tensor与一个标量进行选取,支持多次迭代; 2 -> 根据sel中的逐个bit,对两个tensor的进行选取,支持多次迭代; 昇腾310 AI处理器,仅支持mode=0。 |
dst |
输出 |
目的操作数,tensor起始element。 昇腾310 AI处理器,支持的数据类型为:Tensor(float16)。 |
sel |
输入 |
选取mask,每个bit表示1个element的选取; mode配置为0/1/2时sel均传入tensor,支持的数据类型为:Tensor(uint8/uint16/uint32/uint64)。 mode为1/2时,多次迭代连续消耗。 |
src0 |
输入 |
源操作数0,tensor起始element。 注:src0,src1数据类型应与dst保持一致。 |
src1 |
输入 |
源操作数1,tensor起始element。 模式0/2应配置为tensor;模式1应配置为Scalar/立即数(int, float); 注:src0,src1数据类型应与dst保持一致。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src0_rep_stride |
输入 |
相邻迭代间,源操作数0相同block地址步长。 |
src1_rep_stride |
输入 |
相邻迭代间,源操作数1相同block地址步长。 注:模式1时无效。 |
返回值
无
注意事项
- 参数mode仅支持立即数。
- 参数repeat_times∈[0,255],支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64),当repeat_times为立即数时,不支持0。
- 指令dst_rep_stride/src0_rep_stride/src1_rep_stride
,单位为32B。支持的数据类型:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst与src0、dst与src1应为不同tensor,或同一tensor的同一element,不支持同一tensor的不同element。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
调用示例
# mode 0 from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) cmpmask = tik_instance.vcmp_eq(128, src0_ub, src1_ub, 1, 1) tik_instance.vsel(128, 0, dst_ub, cmpmask, src0_ub, src1_ub, 1, 1, 1, 1, 8, 8, 8) """实际例子如下: 输入数据(float16): src0_ub = {1,2,3,...,128} src1_ub = {2,2,2,...,2} 输出结果: CMPMASK: 0x4000 0000 0000 0000, 0000 0000 0000 0000 dst_ub = {2,2,2,...,2} """ # mode 1 from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1 = tik_instance.Scalar(dtype="float16", init_value=5.2) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) sel = tik_instance.Tensor("uint16", (8,), name="sel", scope=tik.scope_ubuf) tik_instance.vsel(128, 1, dst_ub, sel, src0_ub, src1, 1, 1, 1, 1, 8, 8, 8) # mode 2 from te import tik tik_instance = tik.Tik() src0_ub = tik_instance.Tensor("float16", (128,), name="src0_ub", scope=tik.scope_ubuf) src1_ub = tik_instance.Tensor("float16", (128,), name="src1_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (128,), name="dst_ub", scope=tik.scope_ubuf) sel = tik_instance.Tensor("uint16", (8,), name="sel", scope=tik.scope_ubuf) tik_instance.vsel(128, 2, dst_ub, sel, src0_ub, src1_ub, 1, 1, 1, 1, 8, 8, 8)
数据精度转换指令(Gather模式)
vec_conv
功能说明
根据src与dst tensor的类型进行精度转换。
函数原型
vec_conv(mask, round_mode, dst, src, repeat_times, dst_rep_stride, src_rep_stride, deqscale=None, ldst_high_half=False)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表12-25中mask参数描述。 |
round_mode |
输入 |
在转换过程中,最后一位转换处理模式,支持以下字符串配置:
|
dst |
输出 |
目的操作数。 |
src |
输入 |
源操作数。 |
repeat_times |
输入 |
重复迭代次数。 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。 |
deqscale |
输入 |
量化scale,辅助转换参数,默认值为None。 支持的数据类型为:Scalar(float16)、立即数(float)。 |
ldst_high_half |
输入 |
指定dst_list/src_list是存储/来自每个block的高半部或者低半部,默认值为False。 支持bool类型,True/Flase表示高半部/低半部; 注:该参数对于不同组合会分别表现为不同的功能定义,分别表示dst_list/src_list的存储/读取。 昇腾310 AI处理器,不支持该参数。 |
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 |
返回值
无
注意事项
- 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。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
调用示例
from te import tik tik_instance = tik.Tik() 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) tik_instance.vec_conv(64, "round", dst_ub, src_ub, 2, 8, 4)
对归约(Pair Reduce)
通用定义
功能说明
此为对归约指令的通用格式,指令对当前迭代的相邻内对(elements)源操作数进行统一处理。注:这不是真正的指令。
函数原型
instruction (mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
instruction |
输入 |
指令名称,TIK DSL中为全小写字符串。 |
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输出 |
目的操作数,tensor起始element。 |
src |
输入 |
源操作数,tensor起始element。 |
repeat_times |
输入 |
重复迭代次数 |
dst_rep_stride |
输入 |
相邻迭代间,目的操作数相同block地址步长。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。 |
注意事项
- repeat_times∈[0,255]。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。当repeat_times为立即数时,不支持0。
- 每个repeat的并行度取决于数据精度、芯片版本,以下以PAR代表并行度。
- dst_rep_stride/src_rep_stride
,支持Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。当dst_rep_stride传入0时,按照1处理。
- 需注意dst_rep_stride的实现方式有所不同,单位为128B。
- 为了节省地址空间,开发者可以定义一个Tensor,供源操作数与目的操作数同时使用(即地址重叠),相关约束如下:
- 对于单次repeat(repeat_times=1),且源操作数与目的操作数之间要求100%完全重叠,不支持部分重叠。
- 对于多次repeat(repeat_times>1),若源操作数与目的操作数之间存在依赖,即第N次迭代的目的操作数是第N+1次的源操作数,这种情况是不支持地址重叠的。
- 操作数地址偏移对齐要求请见通用约束。
vec_cpadd
功能说明
相邻内对(奇偶)elements求和:
函数原型
vec_cpadd(mask, dst, src, repeat_times, dst_rep_stride, src_rep_stride)
返回值
无
注意事项
请参见注意事项。
调用示例
from te import tik tik_instance = tik.Tik() src_ub = tik_instance.Tensor("float16", (128,), name="src_ub", scope=tik.scope_ubuf) dst_ub = tik_instance.Tensor("float16", (64,), name="dst_ub", scope=tik.scope_ubuf) tik_instance.vec_cpadd(128, dst_ub, src_ub, 1, 1, 8)
归约
vec_reduce_add
功能说明
对所有输入数据求和。
数据采用二叉树方式,两两相加。
假设源操作数为256个float16的数据[data0,data1,data2...data255],两个repeat可以计算完,计算过程如下。
- [data0,data1,data2...data127]为第一个repeat的源操作数,计算得到result01,具体计算方式为:
- data0和data1相加得到data00,data2和data3相加得到data01...data124和data125相加得到data62,data126和data127相加得到data63;
- data00和data01相加得到data000,data02和data03相加得到data001...data62和data63相加得到data031;
- 以此类推,计算得到result01。
- [data128,data1,data2...data255]为第二个repeat的源操作数,计算得到result02;
- 将result01与result02相加,得到目的操作数为1个float16的数据[data]。
函数原型
vec_reduce_add(mask, dst, src, work_tensor, repeat_times, src_rep_stride)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输出 |
目的操作数,tensor起始element |
src |
输入 |
源操作数,tensor起始element |
work_tensor |
输入 |
指令执行期间存储中间结果,用于内部计算所需操作空间,需特别注意空间大小,参见各指令注意事项。 |
repeat_times |
输入 |
重复迭代次数。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。 |
cal_index |
输入 |
指定是否获取最值的索引(仅vec_reduce_max/vec_reduce_min支持),仅支持bool类型,默认值为False,取值:
|
dst、src和work_tensor的数据类型需保持一致。
昇腾310 AI处理器,dst、src和work_tensor支持的数据类型为:Tensor(float16/float32)
返回值
无
注意事项
- work_tensor空间至少需要repeat_times个elements。例如当repeat_times=120时,work_tensor的shape至少为120。
- repeat_times
[1, 4095]。支持的数据类型为:Scalar(int32)、立即数(int)、Expr(int32)。
- src_rep_stride
[0,65535],支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- 需要注意的是两两相加的计算过程中,计算结果溢出时根据系统inf/nan控制位决定溢出后处理方式,分为按照最值处理和inf/nan处理两种。当按照最值处理时,float16类型数据相加后大于65504时结果保存为65504。例如源操作数为[60000,60000,-30000,100],首先60000+60000溢出,结果为65504,第二步计算-30000+100=-29900,第四步计算65504-29900=35604。
- src、dst和work_tensor三者互相之间不能存在地址重叠。
- 操作数地址偏移对齐要求请见通用约束。
调用示例
from te import tik tik_instance = tik.Tik() dst_ub = tik_instance.Tensor("float16", (32,), tik.scope_ubuf, "dst_ub") src_ub = tik_instance.Tensor("float16", (256,), tik.scope_ubuf, "src_ub") work_tensor_ub = tik_instance.Tensor("float16", (32,), tik.scope_ubuf, "work_tensor_ub") tik_instance.vec_reduce_add(128, dst_ub, src_ub, work_tensor_ub, 2, 8) 上述例子构造输入、输出如下: 输入: src_ub=[1,1,1,,...,1] 输出结果为: dst_ub=[256]
vec_reduce_max
功能说明
在所有的输入数据中找出最大值及最大值对应的索引位置。注意:如果有多个最大值,返回哪个最大值,请看注意事项。
函数原型
vec_reduce_max(mask, dst, src, work_tensor, repeat_times, src_rep_stride, cal_index=False)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输入 |
目的操作数,tensor起始element,起始地址要求4Byte对齐。 |
src |
输入 |
源操作数,tensor起始element,起始地址对齐要求请见通用约束。 |
work_tensor |
输入 |
指令执行期间存储中间结果,用于内部计算所需操作空间,需特别注意空间大小,参见各指令注意事项。 |
repeat_times |
输入 |
重复迭代次数。Scalar(int32)、立即数(int)、Expr(int32)。注意,推荐使用立即数,性能比较高。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。 |
cal_index |
输入 |
指定是否获取最值的索引,仅支持bool类型,默认值为False,取值:
|
dst、src和work_tensor的数据类型需保持一致。
昇腾310 AI处理器,dst、src和work_tensor支持的数据类型为:Tensor(float16)
返回值
无
注意事项
- repeat_times支持的数据类型为:Scalar(int32)、立即数(int)、Expr(int32)。
- 当cal_index=False时,repeat_times
[1,4095]
- 当cal_index=True时:
- 当操作数数据类型为int16时,操作数最大表示数值为32767,因此最多支持255次迭代,repeat_times
[1,255]。
- 当操作数数据类型为float16,操作数最大表示数值为65504,因此最多支持511次迭代,repeat_times
[1,511]。
- 当操作数数据类型为float32时,repeat_times
[1,4095]。
- 当操作数数据类型为int16时,操作数最大表示数值为32767,因此最多支持255次迭代,repeat_times
- 当cal_index=False时,repeat_times
- src_rep_stride
[0,65535],支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst结果存储顺序为最值,最值索引。返回结果中索引index数据实际上是按照相应整数类型进行存储的,如dst定义为float16时,index为uint16类型,如果按照float16格式进行读取,index 的值不对,因此注意index使用时需要使用reinterpret_cast_to()方法转换到相应整数类型。
- work_tensor空间限制如下:
- 当cal_index=False时,至少需要repeat_times*2个elements。例如当repeat_times=120时,work_tensor的shape至少为240。
- 当cal_index=True时,需要使用公式计算空间大小,公式如下,举例请参考调用示例。
# DTYPE_SIZE指数据类型所占的空间,以Byte为单位,如float16类型占2Bytes。elements_per_block指每个block所需的element个数 elements_per_block = 32 // DTYPE_SIZE[dtype] elements_per_repeat = 256 // DTYPE_SIZE[dtype] # elements_per_repeat指每个repeat所需的element个数 it1_output_count = 2*repeat_times # 第一轮操作产生的元素个数 it2_align_start = ceil_div(it1_output_count, elements_per_block)*elements_per_block # 第二轮操作起始位置偏移,ceil_div功能为相除之后向上取整 it2_output_count = ceil_div(it1_output_count, elements_per_repeat)*2 # 第二轮操作产生的元素个数 it3_align_start = ceil_div(it2_output_count, elements_per_block)*elements_per_block # 第三轮操作起始位置偏移 it3_output_count = ceil_div(it2_output_count, elements_per_repeat)*2 # 第三轮操作产生的元素个数 it4_align_start = ceil_div(it3_output_count, elements_per_block)*elements_per_block # 第四轮操作起始位置偏移 it4_output_count = ceil_div(it3_output_count, elements_per_repeat)*2 # 第四轮操作产生的元素个数 final_work_tensor_need_size = it2_align_start + it3_align_start + it4_align_start + it4_output_count # 最终所需的work_tensor大小
- dst和work_tensor之间不能存在地址重叠。
调用示例
from te import tik tik_instance = tik.Tik() dst_ub = tik_instance.Tensor("float16", (2,), tik.scope_ubuf, "dst_ub") src_ub = tik_instance.Tensor("float16", (256,), tik.scope_ubuf, "src_ub") work_tensor_ub = tik_instance.Tensor("float16", (18,), tik.scope_ubuf, "work_tensor_ub") tik_instance.vec_reduce_max(128, dst_ub, src_ub, work_tensor_ub, 2, 8, cal_index=True)
- 【举例一】
src, work_tensor, dst均为float16的tensor,src的shape为(65, 128),vec_reduce_max/vec_reduce_min的repeat_times为65。
接口调用示例为:
tik_instance.vec_reduce_max(128, dst, src, work_tensor, 65, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 16 (elements) elements_per_repeat = 128 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 16)*16 = 144 (elements) it2_output_count = ceil_div(130, 128)*2 = 4 (elements) it3_align_start = ceil_div(4, 16)*16 = 16 (elements) it3_output_count = ceil_div(4, 128)*2 = 2 (elements)
三轮即可拿到最终的最值以及下标,需要的空间work_tensor为:it2_align_start + it3_align_start + it3_output_count = 144 + 16 + 2 = 162 (elements)
- 【举例二】
src, work_tensor, dst均为float16的tensor,src的shape为(65, 128),vec_reduce_max/vec_reduce_min的repeat_times为scalar,值65。对于repeat_times为scalar或包含scalar的情况,需要做四轮计算。
接口调用示例为:
scalar = tik_instance.Scalar(init_value=65, dtype=”int32”) tik_instance.vec_reduce_max(128, dst, src, work_tensor, scalar, 8, cal_index=True)
此时work_tensor的空间计算过程:
elements_per_block = 16 (elements) elements_per_repeat = 128 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 16)*16 = 144 (elements) it2_output_count = ceil_div(130, 128)*2 = 4 (elements) it3_align_start = ceil_div(4, 16)*16 = 16 (elements) it3_output_count = ceil_div(4, 128)*2 = 2 (elements) it4_align_start = ceil_div(2, 16)*16 = 16 (elements) it4_output_count = ceil(2, 128)*2 = 2(elements)
对于repeat_times为scalar或包含scalar的情况,虽然第三轮就能拿到结果,但是由于在Python编译时无法获取scalar的值,因此还是跑了四轮,需要的空间work_tensor为:it2_align_start + it3_align_start + it4_aign_start + it4_output_count = 144 + 16 + 16 + 2 = 178 (elements)
- 【举例三】
src, work_tensor, dst均为float32的tensor,src的shape为(65, 64),vec_reduce_max/vec_reduce_min的repeat_times为65。
接口调用示例为:
tik_instance.vec_reduce_max(64, dst, src, work_tensor, 65, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 8 (elements) elements_per_repeat = 64 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 8)*8 = 136 (elements) it2_output_count = ceil_div(130, 64)*2 = 6 (elements) it3_align_start = ceil_div(6, 8)*8 = 8 (elements) it3_output_count = ceil_div(6, 64)*2 = 2 (elements)
此时三轮即可拿到最终的最值以及下标,需要的空间work_tensor为:it2_align_start + it3_align_start + it3_output_count = 136 + 8 + 2 = 146 (elements)
- 【举例四】
src, work_tensor, dst均为float32的tensor,src的shape为(65, 64),vec_reduce_max/vec_reduce_min的repeat_times为scalar,值65。对于repeat_times为scalar或包含scalar的情况,需要做四轮计算。
接口调用示例为:
scalar = tik_instance.Scalar(init_value=65, dtype=”int32”) tik_instance.vec_reduce_max(64, dst, src, work_tensor, scalar, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 8 (elements) elements_per_repeat = 64 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 8)*8 = 136 (elements) it2_output_count = ceil_div(130, 64)*2 = 6 (elements) it3_align_start = ceil_div(6, 8)*8 = 8 (elements) it3_output_count = ceil_div(6, 64)*2 = 2 (elements) it4_align_start = ceil_div(2, 8)*8 = 8 (elements) it4_output_count = ceil(2, 64)*2 = 2(elements)
对于repeat_times为scalar或包含scalar的情况,虽然第三轮就能拿到结果,但是由于在Python编译时无法获取scalar的值,因此还是跑了四轮,需要的空间work_tensor为:it2_align_start + it3_align_start + it4_align_start + it4_output_count = 136 + 8 + 8 + 2 = 154 (elements)
vec_reduce_min
功能说明
在所有的输入数据中找出最小值及最小值对应的索引位置。注意:如果有多个最小值,返回哪个最小值,请看注意事项。
函数原型
vec_reduce_min(mask, dst, src, work_tensor, repeat_times, src_rep_stride, cal_index=False)
参数说明
参数名称 |
输入/输出 |
含义 |
---|---|---|
mask |
输入 |
请参考表12-25中mask参数描述。 |
dst |
输入 |
目的操作数,tensor起始element,起始地址要求4Byte对齐。 |
src |
输入 |
源操作数,tensor起始element,起始地址对齐要求请见通用约束。 |
work_tensor |
输入 |
指令执行期间存储中间结果,用于内部计算所需操作空间,需特别注意空间大小,参见各指令注意事项。 |
repeat_times |
输入 |
重复迭代次数。Scalar(int32)、立即数(int)、Expr(int32)。建议采用立即数,性能比scalar和表达式高。 |
src_rep_stride |
输入 |
相邻迭代间,源操作数相同block地址步长。支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。 |
cal_index |
输入 |
指定是否获取最值的索引(仅vec_reduce_max/vec_reduce_min支持),仅支持bool类型,默认值为False,取值:
|
dst、src和work_tensor的数据类型需保持一致。
昇腾310 AI处理器,dst、src和work_tensor支持的数据类型为:Tensor(float16)
返回值
无
注意事项
- repeat_times支持的数据类型为:Scalar(int32)、立即数(int)、Expr(int32)。
- 当cal_index=False时,repeat_times
[1,4095]
- 当cal_index=True时:
- 当操作数数据类型为int16时,repeat_times
[1,255],由于index最大支持数值为int16最大表示数值32767,因此最多支持255次迭代。
- 当操作数数据类型为float16,repeat_times
[1,511],由于index最大支持数值为float16最大表示数值65504,因此最多支持511次迭代。
- 当操作数数据类型为float32时,repeat_times
[1,4095]。
- 当操作数数据类型为int16时,repeat_times
- 当cal_index=False时,repeat_times
- src_rep_stride
[0,65535],支持的数据类型为:Scalar(int16/int32/int64/uint16/uint32/uint64)、立即数(int)、Expr(int16/int32/int64/uint16/uint32/uint64)。
- dst结果存储顺序为最值,最值索引。返回结果中索引index数据实际上是按照相应整数类型进行存储的,如dst定义为float16时,index为uint16类型,但按照float16格式进行读取,因此注意index使用时需要使用reinterpret_cast_to()方法转换到相应整数类型。
- work_tensor空间限制如下:
- 当cal_index=False时,至少需要repeat_times*2个elements。例如当repeat_times=120时,work_tensor的shape至少为240。
- 当cal_index=True时,需要使用公式计算空间大小,公式如下。
# DTYPE_SIZE指数据类型所占的空间,以Byte为单位,如float16类型占2Bytes。elements_per_block指每个block所需的element个数 elements_per_block = 32 // DTYPE_SIZE[dtype] elements_per_repeat = 256 // DTYPE_SIZE[dtype] # elements_per_repeat指每个repeat所需的element个数 it1_output_count = 2*repeat_times # 第一轮操作产生的元素个数 it2_align_start = ceil_div(it1_output_count, elements_per_block)*elements_per_block # 第二轮操作起始位置偏移,ceil_div功能为相除之后向上取整 it2_output_count = ceil_div(it1_output_count, elements_per_repeat)*2 # 第二轮操作产生的元素个数 it3_align_start = ceil_div(it2_output_count, elements_per_block)*elements_per_block # 第三轮操作起始位置偏移 it3_output_count = ceil_div(it2_output_count, elements_per_repeat)*2 # 第三轮操作产生的元素个数 it4_align_start = ceil_div(it3_output_count, elements_per_block)*elements_per_block # 第四轮操作起始位置偏移 it4_output_count = ceil_div(it3_output_count, elements_per_repeat)*2 # 第四轮操作产生的元素个数 final_work_tensor_need_size = it2_align_start + it3_align_start + it4_align_start + it4_output_count # 最终所需的work_tensor大小
- dst和work_tensor之间不能存在地址重叠。
调用示例
from te import tik tik_instance = tik.Tik() dst_ub = tik_instance.Tensor("float16", (32,), tik.scope_ubuf, "dst_ub") src_ub = tik_instance.Tensor("float16", (256,), tik.scope_ubuf, "src_ub") work_tensor_ub = tik_instance.Tensor("float16", (18,), tik.scope_ubuf, "work_tensor_ub") tik_instance.vec_reduce_min(128, dst_ub, src_ub, work_tensor_ub, 2, 8, cal_index=True)
- 【举例一】
src, work_tensor, dst均为float16的tensor,src的shape为(65, 128),vec_reduce_max/vec_reduce_min的repeat_times为65。
接口调用示例为:
tik_instance.vec_reduce_max(128, dst, src, work_tensor, 65, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 16 (elements) elements_per_repeat = 128 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 16)*16 = 144 (elements) it2_output_count = ceil_div(130, 128)*2 = 4 (elements) it3_align_start = ceil_div(4, 16)*16 = 16 (elements) it3_output_count = ceil_div(4, 128)*2 = 2 (elements)
三轮即可拿到最终的最值以及下标,需要的空间work_tensor为:it2_align_start + it3_align_start + it3_output_count = 144 + 16 + 2 = 162 (elements)
- 【举例二】
src, work_tensor, dst均为float16的tensor,src的shape为(65, 128),vec_reduce_max/vec_reduce_min的repeat_times为scalar,值65。对于repeat_times为scalar或包含scalar的情况,需要做四轮计算。
接口调用示例为:
scalar = tik_instance.Scalar(init_value=65, dtype=”int32”) tik_instance.vec_reduce_max(128, dst, src, work_tensor, scalar, 8, cal_index=True)
此时work_tensor的空间计算过程:
elements_per_block = 16 (elements) elements_per_repeat = 128 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 16)*16 = 144 (elements) it2_output_count = ceil_div(130, 128)*2 = 4 (elements) it3_align_start = ceil_div(4, 16)*16 = 16 (elements) it3_output_count = ceil_div(4, 128)*2 = 2 (elements) it4_align_start = ceil_div(2, 16)*16 = 16 (elements) it4_output_count = ceil(2, 128)*2 = 2(elements)
对于repeat_times为scalar或包含scalar的情况,虽然第三轮就能拿到结果,但是由于在Python编译时无法获取scalar的值,因此还是跑了四轮,需要的空间work_tensor为:it2_align_start + it3_align_start + it4_aign_start + it4_output_count = 144 + 16 + 16 + 2 = 178 (elements)
- 【举例三】
src, work_tensor, dst均为float32的tensor,src的shape为(65, 64),vec_reduce_max/vec_reduce_min的repeat_times为65。
接口调用示例为:
tik_instance.vec_reduce_max(64, dst, src, work_tensor, 65, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 8 (elements) elements_per_repeat = 64 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 8)*8 = 136 (elements) it2_output_count = ceil_div(130, 64)*2 = 6 (elements) it3_align_start = ceil_div(6, 8)*8 = 8 (elements) it3_output_count = ceil_div(6, 64)*2 = 2 (elements)
此时三轮即可拿到最终的最值以及下标,需要的空间work_tensor为:it2_align_start + it3_align_start + it3_output_count = 136 + 8 + 2 = 146 (elements)
- 【举例四】
src, work_tensor, dst均为float32的tensor,src的shape为(65, 64),vec_reduce_max/vec_reduce_min的repeat_times为scalar,值65。对于repeat_times为scalar或包含scalar的情况,需要做四轮计算。
接口调用示例为:
scalar = tik_instance.Scalar(init_value=65, dtype=”int32”) tik_instance.vec_reduce_max(64, dst, src, work_tensor, scalar, 8, cal_index=True)
此时work_tensor的空间计算过程为:
elements_per_block = 8 (elements) elements_per_repeat = 64 (elements) it1_output_count = 2*65 = 130 (elements) it2_align_start = ceil_div(130, 8)*8 = 136 (elements) it2_output_count = ceil_div(130, 64)*2 = 6 (elements) it3_align_start = ceil_div(6, 8)*8 = 8 (elements) it3_output_count = ceil_div(6, 64)*2 = 2 (elements) it4_align_start = ceil_div(2, 8)*8 = 8 (elements) it4_output_count = ceil(2, 64)*2 = 2(elements)
对于repeat_times为scalar或包含scalar的情况,虽然第三轮就能拿到结果,但是由于在Python编译时无法获取scalar的值,因此还是跑了四轮,需要的空间work_tensor为:it2_align_start + it3_align_start + it4_align_start + it4_output_count = 136 + 8 + 8 + 2 = 154 (elements)