pypto_pro.language.get_block_idx#
产品支持情况#
Ascend 950PR/Ascend 950DT:支持
Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持
Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持
功能说明#
获取当前实际执行核在所属执行域中的全局索引,用于多核控制和数据偏移计算。
函数原型#
pypto_pro.language.get_block_idx() -> int
参数说明#
无。
约束说明#
无。
返回值说明#
返回DT_INT64类型的当前逻辑核索引,可用于Kernel内的整数计算和数据索引。取值范围与Kernel的执行域有关:
仅启动Cube(AIC)或仅启动Vector(AIV)时,范围为[0, get_block_num())。
同时启动AIC与AIV时,AIC侧范围为[0, get_block_num());AIV侧范围为[0, get_subblock_num() × get_block_num())。当前1:2配置下,AIV侧范围为[0, 2 × get_block_num())。
在Vector段中,该接口返回全局AIV逻辑索引,编号方式为:物理核号 × get_subblock_num() + 子核号,可直接用于数据分片和偏移计算。混合Kernel在Vector段做跨步切分时,工作单元总数为get_block_num() × get_subblock_num()。
调用示例#
多核数据分片(纯Vector Kernel)#
通过Kernel[None, NUM_CORES]形式实际启动2个AIV,每个AIV用get_block_idx()获取全局逻辑索引并处理64行逐元素加法,用pypto_pro.language.printf打印获取到的索引值:
import os
import pypto_pro.language as pl
import torch
NUM_CORES = 2
@pl.jit(auto_mutex=True)
def multicore_add_kernel(
x: pl.Tensor[[128, 128], pl.DT_FP16],
y: pl.Tensor[[128, 128], pl.DT_FP16],
z: pl.Tensor[[128, 128], pl.DT_FP16],
):
tt = pl.TileType(shape=[64, 128], dtype=pl.DT_FP16, target_memory=pl.MemorySpace.Vec)
tile_a = pl.make_tile_group(type=tt, addrs=0x0000, mutex_ids=[0])
tile_b = pl.make_tile_group(type=tt, addrs=0x4000, mutex_ids=[1])
tile_c = pl.make_tile_group(type=tt, addrs=0x8000, mutex_ids=[2])
with pl.section_vector():
vidx = pl.get_block_idx() # 当前AIV的全局逻辑索引
num_blocks = pl.get_block_num() # 实际启动的Block数
pl.printf("block_idx = %d, block_num = %d\n", vidx, num_blocks)
for tile_idx in pl.range(vidx, 2, num_blocks):
offset = tile_idx * 64
cur_a = tile_a.current()
cur_b = tile_b.current()
cur_c = tile_c.current()
pl.load(cur_a, x, [offset, 0])
pl.load(cur_b, y, [offset, 0])
pl.add(cur_c, cur_a, cur_b)
pl.store(z, cur_c, [offset, 0])
if __name__ == "__main__":
device = f"npu:{int(os.environ.get('TILE_FWK_DEVICE_ID', 0))}"
torch.npu.set_device(device)
torch.manual_seed(42)
x = torch.rand([128, 128], device=device, dtype=torch.float16)
y = torch.rand([128, 128], device=device, dtype=torch.float16)
z = torch.zeros([128, 128], device=device, dtype=torch.float16)
multicore_add_kernel[None, NUM_CORES](x, y, z)
torch.npu.synchronize()
torch.testing.assert_close(z, x + y, rtol=1e-2, atol=1e-2)
print(f"max diff = {(z - (x + y)).abs().max().item()}")
回显(=> Vec后为核号,多核间输出顺序不固定):
=> Vec 0
block_idx = 0, block_num = 2
=> Vec 1
block_idx = 1, block_num = 2
混合Kernel中AIC与AIV的返回值#
混合Kernel(AIC:AIV=1:2)中,Cube段返回物理核号[0, get_block_num()),Vector段返回全局AIV逻辑编号[0, get_block_num() × get_subblock_num()),编号方式为:物理核号 × get_subblock_num() + 子核号:
import os
import pypto_pro.language as pl
import torch
@pl.jit()
def block_idx_mix_kernel(out: pl.Tensor[[1], pl.DT_INT32]):
with pl.section_cube():
aic_idx = pl.get_block_idx()
pl.printf("[cube] block_idx = %d\n", aic_idx)
pl.setval(out, 0, 1)
with pl.section_vector():
aiv_idx = pl.get_block_idx()
pl.printf("[vector] block_idx = %d\n", aiv_idx)
if __name__ == "__main__":
device = f"npu:{int(os.environ.get('TILE_FWK_DEVICE_ID', 0))}"
torch.npu.set_device(device)
out = torch.zeros(1, device=device, dtype=torch.int32)
block_idx_mix_kernel[None, 2](out)
torch.npu.synchronize()
回显(实际启动2个AIC和4个AIV:AIC侧返回0/1,AIV侧返回0~3):
=> Cube 0
[cube] block_idx = 0
=> Vec 0
[vector] block_idx = 0
=> Vec 1
[vector] block_idx = 1
=> Cube 1
[cube] block_idx = 1
=> Vec 2
[vector] block_idx = 2
=> Vec 3
[vector] block_idx = 3