pypto_pro.language.get_block_num#

产品支持情况#

  • Ascend 950PR/Ascend 950DT:支持

  • Atlas A3 训练系列产品/Atlas A3 推理系列产品:不支持

  • Atlas A2 训练系列产品/Atlas A2 推理系列产品:不支持

功能说明#

获取本次实际启动的逻辑Block数量,用于多核控制和数据偏移计算。

函数原型#

pypto_pro.language.get_block_num() -> int

参数说明#

无。

约束说明#

无。

返回值说明#

返回DT_INT64类型的标量值,表示限核后实际启动的Block数,可用于Kernel内的整数计算和数据索引。 JIT每次启动通过C++启动器查询实际Stream的有效资源限制,按Kernel执行域和配对比例限制Host请求的block_dim。 因此返回值可能小于Host请求值;数据切分应使用本接口返回值作为循环步长,避免遗漏任务。

仅启动Cube(AIC)或仅启动Vector(AIV)时,该值等于执行域逻辑核数。 在AIC:AIV为1:2的混合Kernel中,该值表示逻辑Block数;AIC逻辑核数为get_block_num(), AIV逻辑核数为get_block_num() * get_subblock_num()

调用示例#

按实际Block数循环切分#

用Kernel[None, NUM_CORES]请求最多2个逻辑Block,每个AIV以get_block_num()返回值为步长跨步处理64行Tile。用pypto_pro.language.printf打印实际启动的Block数:

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

限核启动下的返回值#

启动Block数是请求的上界,实际启动数可能更小。复用上例Kernel与__main__中的x/y,仅把启动Block数改为1:

    z = torch.zeros([128, 128], device=device, dtype=torch.float16)
    multicore_add_kernel[None, 1](x, y, z)
    torch.npu.synchronize()
    torch.testing.assert_close(z, x + y, rtol=1e-2, atol=1e-2)  # 仍覆盖全部128行

回显:

=> Vec 0
block_idx = 0, block_num = 1