vf.shift_right#
产品支持情况#
Ascend 950PR&950DT系列产品:支持
Atlas A3系列产品:不支持
Atlas A2系列产品:不支持
功能说明#
vf.shift_right指令根据preg对源操作数src进行右移操作,将结果写入目的操作数dst。移位量shift既可以是标量(所有元素移动相同位数),也可以是**reg_tensor**(每个元素按对应lane的位数移动)。接口会根据shift参数的类型自动选择:
标量模式(整数值或标量变量):所有元素统一右移。
reg_tensor模式:reg_tensor中元素逐元素右移。根据源操作数的数据类型,右移操作分为以下两种情况:
数据类型为无符号类型:执行逻辑右移。
逻辑右移会将二进制数整体向右移动指定的位数,最低位被丢弃,最高位用0填充。例如,二进制数1010101010101010(DT_UINT16类型)逻辑右移1位后,结果为0101010101010101。
数据类型为有符号类型:执行算术右移。
算术右移会将二进制数整体向右移动指定的位数,最低位被丢弃,最高位复制符号位。例如,二进制数1010101010101010(DT_INT16类型)算术右移1位后,结果为1101010101010101;算术右移3位后,结果为1111010101010101。
函数原型#
shift_right(src, shift, preg, /, *, mode: Optional[MergeMode] = None) -> dst
参数说明#
参数 |
输入/输出 |
说明 |
|---|---|---|
src |
输入 |
源操作数,reg_tensor。源操作数src与目的操作数dst的数据类型保持一致。支持的数据类型参见约束说明。 |
shift |
输入 |
右移位数。标量(整型,所有元素统一移位)或reg_tensor(逐元素移位),支持的数据类型参见约束说明。 |
preg |
输入 |
|
mode |
输入 |
可选,对应MergeMode类型。 |
约束说明#
数据类型约束:
dst
src
shift
DT_INT8
DT_INT8
标量模式:整型标量;reg_tensor模式:DT_INT8
DT_UINT8
DT_UINT8
标量模式:整型标量;reg_tensor模式:DT_INT8
DT_INT16
DT_INT16
标量模式:整型标量;reg_tensor模式:DT_INT16
DT_UINT16
DT_UINT16
标量模式:整型标量;reg_tensor模式:DT_INT16
DT_INT32
DT_INT32
标量模式:整型标量;reg_tensor模式:DT_INT32
DT_UINT32
DT_UINT32
标量模式:整型标量;reg_tensor模式:DT_INT32
DT_INT64
DT_INT64
标量模式:整型标量;reg_tensor模式:DT_INT64
DT_UINT64
DT_UINT64
标量模式:整型标量;reg_tensor模式:DT_INT64
返回值说明#
返回dst目的操作数,reg_tensor,支持的数据类型参见约束说明。
调用示例#
标量模式#
import os
import pypto_pro.language as pl
import torch
import torch_npu
@pl.vector_function
def example_vf_scalar(src_tile, dst_tile):
preg = vf.create_mask(pattern=pl.MaskPattern.ALL, dtype=pl.DT_UINT32)
reg_src = vf.load_align(src_tile, 0)
reg_out = vf.shift_right(reg_src, 24, preg)
vf.store_align(dst_tile, reg_out, preg)
@pl.jit()
def example_kernel(
a: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_UINT32],
out: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_UINT32],
):
tf = pl.TileType(shape=[1, 64], dtype=pl.DT_UINT32, target_memory=pl.MemorySpace.Vec)
in_a_grp = pl.make_tile_group(type=tf, addrs=0x0, mutex_ids=[0])
in_a = in_a_grp.current()
t_out_grp = pl.make_tile_group(type=tf, addrs=0x100, mutex_ids=[1])
t_out = t_out_grp.current()
with pl.section_vector():
pl.load(in_a, a, [0, 0])
example_vf_scalar(in_a, t_out)
pl.store(out, t_out, [0, 0])
def test_example():
device_id = int(os.environ.get("TILE_FWK_DEVICE_ID", 0))
device = f"npu:{device_id}"
core_nums = 1
torch.npu.set_device(device)
a = torch.randint(0, 2**31 - 1, [1, 64], device=device, dtype=torch.int32)
out = torch.empty([1, 64], device=device, dtype=torch.int32)
example_kernel[None, core_nums](a, out)
torch.npu.synchronize()
torch.testing.assert_close(out, a >> 24, rtol=0, atol=0)
if __name__ == "__main__":
test_example()
print("PASSED")
reg_tensor模式#
import os
import pypto_pro.language as pl
import torch
import torch_npu
@pl.vector_function
def example_vf_vector(src_tile, shift_tile, dst_tile):
preg = vf.create_mask(pattern=pl.MaskPattern.ALL, dtype=pl.DT_UINT32)
reg_src = vf.load_align(src_tile, 0)
reg_shift = vf.load_align(shift_tile, 0)
reg_out = vf.shift_right(reg_src, reg_shift, preg)
vf.store_align(dst_tile, reg_out, preg)
@pl.jit()
def example_kernel_vector(
a: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_UINT32],
shift: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT32],
out: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_UINT32],
):
tf_u32 = pl.TileType(shape=[1, 64], dtype=pl.DT_UINT32, target_memory=pl.MemorySpace.Vec)
tf_i32 = pl.TileType(shape=[1, 64], dtype=pl.DT_INT32, target_memory=pl.MemorySpace.Vec)
in_a_grp = pl.make_tile_group(type=tf_u32, addrs=0x0, mutex_ids=[0])
in_a = in_a_grp.current()
in_shift_grp = pl.make_tile_group(type=tf_i32, addrs=0x100, mutex_ids=[1])
in_shift = in_shift_grp.current()
t_out_grp = pl.make_tile_group(type=tf_u32, addrs=0x200, mutex_ids=[2])
t_out = t_out_grp.current()
with pl.section_vector():
pl.load(in_a, a, [0, 0])
pl.load(in_shift, shift, [0, 0])
example_vf_vector(in_a, in_shift, t_out)
pl.store(out, t_out, [0, 0])
def test_example_2():
device_id = int(os.environ.get("TILE_FWK_DEVICE_ID", 0))
device = f"npu:{device_id}"
core_nums = 1
torch.npu.set_device(device)
a = torch.randint(0, 2**31 - 1, [1, 64], device=device, dtype=torch.int32)
shift = torch.full([1, 64], 4, device=device, dtype=torch.int32)
out = torch.empty([1, 64], device=device, dtype=torch.int32)
example_kernel_vector[None, core_nums](a, shift, out)
torch.npu.synchronize()
torch.testing.assert_close(out, a >> 4, rtol=0, atol=0)
if __name__ == "__main__":
test_example_2()
print("PASSED")
INT64数据类型示例#
import os
import pypto_pro.language as pl
import torch
import torch_npu
@pl.vector_function
def example_vf_int64(src_tile, dst_tile):
preg = vf.create_mask(pattern=pl.MaskPattern.ALL, dtype=pl.DT_INT64)
reg_a = vf.load_align(src_tile, 0)
reg_out = vf.shift_right(reg_a, 2, preg)
vf.store_align(dst_tile, reg_out, preg)
@pl.jit()
def example_kernel_int64(
a: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT64],
out: pl.Tensor[[pl.DYNAMIC, pl.DYNAMIC], pl.DT_INT64],
):
tf = pl.TileType(shape=[1, 32], dtype=pl.DT_INT64, target_memory=pl.MemorySpace.Vec)
in_a_grp = pl.make_tile_group(type=tf, addrs=0, mutex_ids=[0])
in_a = in_a_grp.current()
t_out_grp = pl.make_tile_group(type=tf, addrs=256, mutex_ids=[1])
t_out = t_out_grp.current()
with pl.section_vector():
pl.load(in_a, a, [0, 0])
example_vf_int64(in_a, t_out)
pl.store(out, t_out, [0, 0])
def test_example_int64():
device_id = int(os.environ.get("TILE_FWK_DEVICE_ID", 0))
device = f"npu:{device_id}"
core_nums = 1
torch.npu.set_device(device)
a = torch.randint(-100, 100, [1, 32], device=device, dtype=torch.int64)
out = torch.empty([1, 32], device=device, dtype=torch.int64)
example_kernel_int64[None, core_nums](a, out)
torch.npu.synchronize()
torch.testing.assert_close(out, a >> 2, rtol=0, atol=0)
if __name__ == "__main__":
test_example_int64()
print("PASSED")