更新时间:2021-03-18 GMT+08:00
分享

数据搬运

对于Vector计算,一般是用Unified Buffer去存放数据,再进行计算,所以整体数据流应该是从Global Memory>Unified Buffer>Global Memory。TIK提供了data_move接口实现Global MemoryUnified Buffer间的数据搬运,函数原型为:

data_move(dst, src, sid, nburst, burst, src_stride, dst_stride, *args, **argv)

在data_move的函数原型中,用户需要着重关注dst、src、nburst、burst、src_stride、dst_stride等6个参数。其中,dst、src分别表示目的操作数与源操作数,也是数据搬运的起始地址;nburst、burst分别表示待搬运数据包含的数据片段数与每个连续片段的长度(单位32 bytes);src_stride、dst_stride则分别代表相邻数据片段的间隔(即前 burst 尾与后 burst 头的间隔)。通过以上6个参数,data_move支持连续地址与间隔地址两种搬运模式。

图1 data_move的连续/间隔地址搬运模式

图1a所示,一个shape为(2, 128)且数据类型为float16的张量可一次性全部搬入Unified Buffer中。在连续搬运模式中,数据0~255构成一个连续片段;由于只有一个连续片段,源Tensor与目的Tensor相邻连续片段间隔为0,对应搬运示例如下:

# 传输数据片段的数目
nburst = 1
 
# Unified Buffer上数据读取和写入必须32 bytes对齐,一个block的大小为32 bytes
block_bite_size = 32
 
# 根据输入的数据类型dtype_x,计算一个block可以存放多少个对应的元素
dtype_bytes_size = cce.cce_intrin.get_bit_len(dtype_x) // 8
data_each_block = block_bite_size // dtype_bytes_size
 
# 连续数据片段的长度,32 bytes对齐
burst = math.ceil(2 * 128 / data_each_block)
 
# 连续搬运
tik_instance.data_move(input_x_ub, input_x_gm, 0, nburst, burst, 0, 0)

图1b所示的间隔搬运模式中,假设需要搬运的数据为0~63与128~191,则构成两个长度相等的连续数据片段。此时,源Tensor相邻数据片段间隔为4个32 bytes,搬入到目的Tensor中连续存放,间隔为0。代码示例如下:

# 传输数据片段的数目
nburst = 2
 
# Unified Buffer上数据读取和写入必须32 bytes对齐,一个block的大小为32 bytes
block_bite_size = 32
 
# 根据输入的数据类型dtype_x,计算一个block可以存放多少个对应的元素
dtype_bytes_size = cce.cce_intrin.get_bit_len(dtype_x) // 8
data_each_block = block_bite_size // dtype_bytes_size
 
# 连续数据片段的长度,32 bytes对齐
burst = math.ceil(64 / data_each_block)
 
# 间隔搬运
tik_instance.data_move(input_x_ub, input_x_gm, 0, nburst, burst, 4, 0)

无论采用连续或间隔搬运模式,当搬入数据超过Unified Buffer容量上限后,必须通过多次循环以完成搬运,此时,为最大化利用Unified Buffer存储空间,数据定义指定的shape大小一般为Unified Buffer允许的最大值。循环搬运示例如下:

# move_num表示输入张量大小,超过了Unified Buffer允许的最大值ub_tensor_size
loop_time = move_num // ub_tensor_size
# 搬运偏移量
move_offset = 0
 
# 循环搬运
with tik_instance.for_range(0, loop_time) as loop_index:
    move_offset += loop_index * ub_tensor_size
    burse_len = ub_tensor_size / data_each_block
    tik_instance.data_move(input_x_ub, input_x_gm[move_offset], 0, 1, burse_len, 0, 0)
    move_offset += loop_index * ub_tensor_size
 
# 最后一次搬运
last_num = move_num % ub_tensor_size
if last_num > 0:
    burse_len = math.ceil(last_num / data_each_block)
    tik_instance.data_move(input_x_ub, input_x_gm[move_offset], 0, 1, burse_len, 0, 0)
分享:

    相关文档

    相关产品

关闭导读