概念及使用说明
相关概念
本章中的接口涉及对算子的算子二进制、核函数、核函数参数列表以及参数的操作,为便于理解,您可以先通过下图了解它们之间的关系。
Kernel加载与执行接口调用流程
关键流程说明如下:
- 调用acl.init接口初始化。
- 申请运行时资源,包括调用acl.rt.set_device接口指定用于运算的Device、调用acl.rt.create_stream接口创建Stream。
- 调用acl.rt.binary_load_from_file接口加载算子二进制文件。
- 调用acl.rt.binary_get_function接口获取核函数句柄。
- 根据核函数句柄操作其参数列表,操作包括:
- 初始化参数列表
当前支持由系统管理内存(调用acl.rt.kernel_args_init接口)、由用户管理内存(调用acl.rt.kernel_args_init_by_user_mem接口)两种方式。
- 追加参数、更新参数值
核函数参数列表中包含不同类型的参数,例如指针类型参数、placeholder、uint8_t类型参数等,其中:
- 指针类型参数:其值为Device内存地址。一般来说,算子的输入、输出是该种类型的参数,用户需提前调用Device内存申请接口(例如acl.rt.malloc接口)申请内存,并自行拷贝数据至Device侧。
- placeholder:也是指针类型参数,但区别在于,用户无需手动将参数数据复制到Device,这项操作由Runtime完成。在追加参数时Runtime并不会填写真实的Device地址,而是在Launch Kernel时才会刷新为真实的Device地址,所以称之为placeholder。对算子的非输入、输出参数,可以使用placeholder方式,将小块数据(建议小于2KB)的Host->Device拷贝合并到Launch Kernel时的一次拷贝操作中去,减少拷贝次数,提升性能。
不同类型参数,可调用不同的参数追加接口:
- 对于placeholder参数,由于关联的内存必须放在所有参数之后,所以在追加参数时,先调用acl.rt.kernel_args_append_place_holder接口占位,等所有参数都追加之后,可调用acl.rt.kernel_args_get_place_holder_buffer接口获取对应占位符指向的内存地址。用户可根据获取的内存地址,管理该内存中的数据。
- 对于非placeholder参数(例如指针类型参数、uint8_t类型参数等),调用acl.rt.kernel_args_append接口将用户设置的参数值追加拷贝到argsHandle指向的参数数据区域。如果要更新参数值,可调用acl.rt.kernel_args_para_update接口进行更新。
注意,核函数参数列表中,实际可能存在多个参数,并且不同类型的参数可能交错出现,因此需要按照参数列表中的参数顺序从左到右进行追加,追加的参数最多支持128个。
- 结束参数列表的追加、参数值的更新
在所有参数追加之后,调用acl.rt.kernel_args_finalize接口以标识参数组装完毕。但acl.rt.kernel_args_finalize接口之后,也支持继续更新参数值,更新之后,还要再调用一次acl.rt.kernel_args_finalize接口。
- 初始化参数列表
- 调用acl.rt.launch_kernel_with_config接口Launch Kernel,启动对应算子的计算任务。
- 调用接口acl.rt.binary_unload卸载算子二进制文件。
- 释放运行时资源,包括调用acl.rt.destroy_stream接口释放Stream、调用acl.rt.reset_device接口释放Device上的资源。
- 调用acl.finalize接口去初始化。
父主题: Kernel加载与执行