---
title: TIK作用域
description: "TIK的作用域即一个TIK变量有效的区域，又可叫生命周期或活跃状态。"
url: https://www.hiascend.com/document/detail/zh/canncommercial/latest/others/tbeaicpudevg/atlasopdev_10_0051.html
sourcePath: /source/zh/canncommercial/900/others/tbeaicpudevg/atlasopdev_10_0051.html
indexId: d38cd63e69845f4f1c39e66552be5c6df5c9c7a1545efb8089e27374117558b273
---
# TIK作用域

#### 什么是TIK作用域

TIK的作用域即一个TIK变量有效的区域，又可叫生命周期或活跃状态。

一个TIK变量在申请时被创建，至它所在的代码块末尾时被释放，在创建到释放之间处于活跃状态，并且只有在活跃状态时/生命周期/作用域内才能被访问。

在TIK中访问一个变量，会从内到外依次访问所有的作用域直到找到，否则会报未定义的错误。


#### Scalar的作用域

Scalar的作用域/生命周期符合如下规则：

1. Scalar自申请时被创建，跳出所在代码块，则被释放，创建与释放之间的状态称为活跃状态。
2. Scalar只有在活跃状态时能被访问。

Scalar的作用域/生命周期示例如图1所示，该图显示了S0，S1，S2三个变量的活跃状态。

图1 Scalar生命周期示例

TIK中，定义函数、for循环、if判断等都会引入新的作用域，外部无法访问在它们的作用域内定义的变量，例如：

```
g_scalar = tik_instance.Scalar(dtype = "int16", init_value = 1)                    # 全局作用域，g_scalar在全局都能被访问
def tik_func_1():
func_scalar = tik_instance.Scalar(dtype = "int16", init_value = 2)             # func_scalar 仅在函数tik_func_1的作用域内被访问，此处可访问g_scalar和func_scalar
with tik_instance.if_scope(func_scalar < 5):
if_scalar = tik_instance.Scalar(dtype = "int16", init_value = 3)            # if_scalar仅在if的作用域内被访问，此处可访问g_scalar,func_scalar和if_scalar
with tik_instance.for_range(0, 4) as i:
for_scalar = tik_instance.Scalar(dtype = "int16", init_value = 4)   # for_scalar仅在for的作用域内被访问，此处可访问g_scalar,func_scalar,if_scalar和for_scalar
```


#### Tensor的作用域

Tensor的作用域/生命周期符合如下规则：

1. Tensor自申请时被创建，跳出所在代码块，则被释放，创建与释放之间的状态称为活跃状态。
2. Tensor只有在活跃状态时能被访问。
3. 任何时刻，活跃状态的Tensor所占用的buffer总大小，不超过对应物理buffer的总大小。

Tensor的作用域/生命周期示例如图2所示。

图2 Tensor生命周期示例

上述示例中，代码被分成了5个时段，分别用1-5表示，每个时段活跃的Tensor以及总共使用的UB大小如表1所示。


**表1 每个时段Tensor所占UB大小**

| 时段 | 活跃Tensor | 使用UB总大小 |
| --- | --- | --- |
| 1 | B0 | 256\*2 Byte |
| 2 | B0，B1 | 256\*2\*2 Byte |
| 3 | B0，B1，B2 | 256\*3\*2 Byte |
| 4 | B0，B1，B3 | 256\*3\*2 Byte |
| 5 | B0，B4 | 256\*2\*2 Byte |


实际开发活动中，输入张量shape可能超过Unified Buffer容量上限，必须经过多次传输才能完成计算；此时，为最大化利用Unified Buffer存储空间，数据定义指定的shape大小一般为Unified Buffer允许的最大值。代码示例如下：

```
# 获取Unified Buffer空间大小，单位为Byte
ub_size_bytes = tbe.common.platform.get_soc_spec("UB_SIZE")           # 例如：unified buffer空间大小为：128 Bytes
# Unified Buffer上数据读取和写入必须32 Bytes对齐，一个block的大小为32 Bytes
block_byte_size = 32
# 根据输入的数据类型dtype_x，计算一个block可以存放多少个对应的元素
def get_bit_len(dtype):
index = 0
for i in dtype:
if i.isdigit():
break
index += 1
return int(dtype[index:])
dtype_bytes_size = get_bit_len(dtype_x) // 8   # 将bit换算成byte，输入数据类型为int16，一个int16的数为 2 Bytes
data_each_block = block_byte_size // dtype_bytes_size         # 则一个block可以放 32/2=16 个元素
# 计算在Unified Buffer上需要分别分配多少空间，并进行32Bytes对齐
ub_tensor_size = (ub_size_bytes // dtype_bytes_size //        # 则 ub_tensor_size = 128 // 2 // 16 * 16 = 64
data_each_block * data_each_block)                            # 即 最多定义包含64个int16的元素的Tensor
# 在Unified Buffer上创建tensor input_x_ub
input_x_ub = tik_instance.Tensor(dtype_x, (ub_tensor_size,),
name="input_x_ub", scope=tik.scope_ubuf)
```

另外，用户也可通过地址复用（或称地址重叠）以节省Unified Buffer存储空间。以矢量单目运算为例，当地址复用满足相应约束时，用户可以定义一个Tensor供源操作数与目的操作数同时使用，此时能节省一倍的存储空间。

```
'''
示例：
tensor_a 既是源操作数，也是目的操作数
下面这条语句将tensor_a的值修改为它的绝对值:
before: tensor_a = [-3, -2, -1, 0, 1, 2, 3, ...]
after: tensor_a = [3, 2, 1, 0, 1, 2, 3, ...]
'''
tensor_a = tik_instance.Tensor("int16", (128,), name="tensor_a", scope=tik.scope_ubuf)
tik_instance.vec_abs(128, tensor_a, tensor_a, 1, 8, 8)
```

需特别注意因地址对齐导致的超出对应内存类型的总容量时，会引起编译报错。

例如：在下图示例中，假设UB的空间大小为1024B（B为Byte的简写），申请两个UB Buffer的tensor_a和tensor_b，大小分别为1008B和16B，内存分配时按照32Byte对齐要求向上对齐到1024B和32B，实际要求内存共1056B，大于UB Buffer的内存总容量1024B。

图3 因对齐产生的空间超限

用户定义的Tensor在内存分配时会对起始地址进行对齐，不同scope的对齐要求如下表：


**表2 不同scope的对齐要求**

| scope | 对齐要求 |
| --- | --- |
| Unified Buffer | Atlas 训练系列产品 ，要求32Byte对齐 Atlas 推理系列产品 AI Core，要求32Byte对齐 Atlas 推理系列产品 Vector Core，要求32Byte对齐 Atlas A2 训练系列产品 / Atlas A2 推理系列产品 ，要求32Byte对齐 Atlas 200I/500 A2 推理产品 ，要求32Byte对齐 Atlas A3 训练系列产品 / Atlas A3 推理系列产品 ， 要求32Byte对齐 |
| L1 Buffer | 512Byte对齐 |
| L1OUT Buffer | float16类型数据要求512Byte对齐；float32/int32/uint32类型数据要求1024Byte对齐 |
| Global Memory | 暂无对齐要求 |


使用TIK数据计算和数据搬运接口时，目的操作数和源操作数地址偏移对齐要求和上表保持一致，如果TIK指令接口中已说明操作数起始地址对齐要求，则以具体指令中的说明为准。
