TIK功能调试
功能介绍
用户开发完TIK算子之后,建议使用TIK调试工具进行算子调试,这样可以通过模拟算子运行的过程,解决算子的绝大部分功能问题(例如数据越界)。
TIK功能调试用于调试TIK DSL的执行行为。该调试功能通过TIK模块的tik.tikdb对象提供。tik.tikdb对象通过tik.Tik对象的tik_instance.tikdb()方法获得,并针对这个TIK对象进行调试。
tikdb提供类似pdb(The Python Debugger)的调试命令行界面。调试者通过tikdb.start_debug()函数启动一个调试过程(需要给定用于测试的TIK DSL程序的输入参数,详细可参考start_debug),tikdb将根据TIK的Dprofile启动一个本地的模拟器,模拟执行TIK定义的执行过程。执行过程遇到断点,tikdb会进入调试命令行界面,详细可参考4。
支持的型号
Atlas 200/300/500 推理产品
Atlas 训练系列产品
Atlas 推理系列产品
Atlas A2训练系列产品/Atlas 800I A2推理产品
Atlas 200/500 A2推理产品
使用方法
- 在进行功能调试前,需要在定义TIK实例时设置disable_debug参数为False,该参数默认值为“True”,代表默认不开启调试功能,详细参数含义可参见TIK类构造函数。
tik_instance = tik.Tik(disable_debug=False)
注意:开启调试功能会影响算子性能,开发者完成功能调试后可以删除disable_debug参数或将disable_debug参数手动置为True,禁用调试功能,可以降低编译时间时长,提升部分性能。
debug调试中使用到的API接口主要包括:- start_debug:启动调试并在调试结束后返回输出结果。
- debug_print:可选接口,为了方便用户打印算子运行过程中的数据。在TIK DSL中插入一个对表达式求值并打印结果的语句。调试器执行到这行代码时会对表达式求值并将结果打印在屏幕上。
- 准备调试数据。
可以通过numpy生成随机数或者从文件中读取。
完整代码示例参考如下,文件名以simple_add.py为例。
import numpy as np from tbe import tik from tbe.common.platform import set_current_compile_soc_info def simple_add(): tik_instance = tik.Tik(disable_debug=False) kernel_name = "tik_vec_add_128_float32" dst_ub = tik_instance.Tensor("float32", [128], tik.scope_ubuf, "dst_ub") dst_gm = tik_instance.Tensor("float32", (128,), tik.scope_gm, "dst_gm") src0_gm = tik_instance.Tensor("float32", (128,), tik.scope_gm, "src0_gm") src0_ub = tik_instance.Tensor("float32", (128,), tik.scope_ubuf, "src0_ub") src1_gm = tik_instance.Tensor("float32", (128,), tik.scope_gm, "src1_gm") src1_ub = tik_instance.Tensor("float32", (128,), tik.scope_ubuf, "src1_ub") tik_instance.data_move(src0_ub, src0_gm, 0, 1, 16, 0, 0) tik_instance.data_move(src1_ub, src1_gm, 0, 1, 16, 0, 0) tik_instance.vec_add(64, dst_ub, src0_ub, src1_ub, 2, 8, 8, 8) tik_instance.data_move(dst_gm, dst_ub, 0, 1, 16, 0, 0) tik_instance.BuildCCE(kernel_name, [src0_gm, src1_gm], [dst_gm]) return tik_instance if __name__=='__main__': # 请根据实际昇腾AI处理器型号进行设置 soc_version="xxx" set_current_compile_soc_info(soc_version) # 请根据AI处理器实际版本设置,具体请参考set_current_compile_soc_info接口说明 tik_instance = simple_add() data_x = np.ones((128,)).astype("float32") data_y = np.ones((128,)).astype("float32") feed_dict = {'src0_gm': data_x, 'src1_gm': data_y} model_data, = tik_instance.tikdb.start_debug(feed_dict=feed_dict,interactive=True) print(model_data)
- 运行算子文件进入TIK调试器的交互命令行。
- 请参见环境准备配置好相关环境变量。
- 运行算子文件。
调用tikdb.start_debug()函数且interactive参数为True后,运行算子文件进入TIK调试器的交互命令行,此时调试器会停止在执行第一条TIK DSL之前。如下图所示。
- 在TIK调试器交互命令行模式下,用户可输入调试命令,详细调试命令请参考调试命令参考。
com(mand) param1 [param2]
- com(mand) 为命令的名字,可以是command,也可缩写为com。
- param1不带中括号,表示必选参数。
- [param2]带中括号,表示可选参数。
- 其他使用说明:
- 若命令行提示符中输入空白符,表示重复执行上一条命令。
- 在debug 调试下,可以进行单步调试,也可以执行至下一个断点或程序结束。如果程序功能正确,则运行到程序结束可以看到debug产生的数据和期望数据的差别为0。
调试命令参考
调试器命令行模式下包括如下几种命令:
- block [block_idx1] [block_idx2] ... [block_idxn]
- 功能说明:对于多核用例,用于核状态查询、调试核切换,该命令对单核用例无效。
- 参数说明:block_idxn对应多核用例中的block_num取值。
- 查询核状态:执行到多核对应的with tik_instance.for_range()及之后语句,"block"命令可以查询所有核对应的状态,输出信息说明:
- Block表示核编号。
- Status表示当前核状态,包括:Stepping(交互状态),Running(非交互运行状态),Finished(运行结束)。
- Current表示当前调试核;包括True(当前调试核),False(当前非调试核)。
图1 多核交互信息查询
- 核切换:执行到多核对应的with tik_instance.for_range()及之后语句,"block block_idx"命令进行核切换,从当前核切换到block_idx对应的核进行调试。
图2 多核切换调试
- b(reak) [tag] [block block_idx1 [block_idx2] ... [block_idxn]]
- 功能说明:在TIK DSL对应的tag上设置断点、查询断点。
- 参数说明:
- tag:TIK DSL程序的断点标记,内容为:
该TIK DSL定义函数所在的文件名:该TIK DSL定义函数所在函数的行号
若不设置任何参数,则直接列出所有已设置断点的信息,包含断点的编号,断点的使能状态,断点对应的tag。其中断点的编号从“0”开始按照设置先后顺序递增。
需要注意:若设置断点格式不准确或者断点处语句非TIK DSL语句均会提示断点设置失败。支持设置断点的语句包括Tensor定义、if-else语句、for语句以及所有的指令(如data_move、vadd等)。
- block:仅对多核用例有效,对单核用例无效。通过命令“block”指定断点对所有核生效(Running和Finished状态的核无效);通过命令“block block_idx1 block_idx2 ...”指定断点对特定的核生效。
- 样例说明:以上文的simple_add.py为例。
- b或者break(显示当前所有断点)
- b simple_add.py(输入格式不匹配)
- b simple_add.py:16(输入准确)
- b simple_add.py:100(行号超过文件代码行数或该行代码不会执行)
- b simple_add.py:1(行号对应代码非TIK原语代码)
- b others.py:18(设置其它文件断点)
- b others.py:19 block 1 2 (如果是多核用例,通过block指定该断点只对核1、2生效)
图3 设置断点示例
- tag:TIK DSL程序的断点标记,内容为:
- clear [bpnumber] [block block_idx1 [block_idx2] ... [block_idxn]]
- 功能说明:清除指定编号的断点,如果不指定参数,将清除所有断点。
- 参数说明:
- bpnumber:断点的编号,即为b(reak)命令查询到的Num。
- block:仅对多核用例有效,对单核用例无效。通过命令“block”清除所有核的断点(Running和Finished状态的核无效);通过命令“block block_idx1 block_idx2 ...”清除特定核的指定断点。
- 样例说明:以上文的simple_add.py为例。
- clear (清除所有断点)
- clear 1 (断点存在)
- clear 10 (断点不存在)
- clear cc (编号不规范)
- clear 1 block 2 3 (对于多核用例,指定清除核2、3上的断点1)
图4 清除断点示例
- disable [bpnumber] [block block_idx1 [block_idx2] ... [block_idxn]]
- 功能说明:禁用指定编号的断点。
- 参数说明:
- bpnumber:断点的编号,即为b(reak)命令查询到的Num。
- block:仅对多核用例有效,对单核用例无效。通过命令“block”禁用所有核的断点(Running和Finished状态的核无效),通过命令“block block_idx1 block_idx2 ...”禁用特定核的指定断点。
- 样例说明:以上文的simple_add.py为例。
- disable 2 (断点存在)
- disable 11 (断点不存在)
- disable aa (编号不规范)
- disable 1 block 2 3 (对于多核用例,禁用核2、3上对应的断点1)
图5 禁用指定编号断点示例
- enable [bpnumber] [block block_idx1 [block_idx2] ... [block_idxn]]
- 功能说明:使能指定编号的断点。
- 参数说明:
- bpnumber:断点的编号,即为b(reak)命令查询到的Num。
- block:仅对多核用例有效,对单核用例无效。通过命令“block”使能所有核的断点(Running和Finished状态的核无效);通过命令“block block_idx1 block_idx2 ...”指定使能特定核的指定断点。
- 样例说明:以上文的simple_add.py为例。
- enable 2 (断点存在)
- enable 11 (断点不存在)
- enable bb (编号不规范)
- enable 1 block 2 3(对于多核用例,使能核2、3上对应的断点1)
图6 使能指定编号断点示例
- n(ext)
- 功能说明:执行至下一个TIK DSL语句。
- 参数说明:无。
- c(ontinue) [-a(ll)]
- 功能说明:执行至程序结束,如果遇到断点或异常,会重新进入交互模式。
- 参数说明:-a或-all仅对多核用例有效,c(ontinue)只会对当前调试进程生效,c(ontinue) -a、c(ontinue) -all会对所有进程生效。
- l(ist)或w(here)
- 功能说明:打印出将要执行的TIK DSL代码对应的Python代码及上下文。
- 参数说明:无。
- 样例说明:如图7所示,总共打印出7行代码。
- p(rint) expression
- 功能说明:对表达式求值并打印结果。
- 参数说明:expression可以是任意Python表达式。expression可以使用的变量有TIK DSL当前作用域的Tensor和Scalar。其中Tensor会被替换为与Tensor等价的numpy.ndarray,这个numpy对象的形状、类型和数据都与Tensor一致,Scalar会被求值并替换为Python的float或int类型的数值。expr也可以传入纯字符串或者字符串与表达式的复合情况。
- 样例说明:如图8所示。
- q(uit)
- 功能说明:退出调试器并终止当前执行的程序。
- 参数说明:无。
- 样例说明:如图9所示。
多核调试示例
完整代码示例参考如下,文件名以tik_multi_core_debug.py为例。
import numpy as np from tbe.common.platform import set_current_compile_soc_info from tbe import tik def simple_add_multi_core(): tik_instance = tik.Tik(disable_debug=False) kernel_name = "tik_multi_core_debug" dtype = "float16" block_nums = 3 dst_gm = tik_instance.Tensor(dtype, (block_nums*128,), tik.scope_gm, "dst_gm") src0_gm = tik_instance.Tensor(dtype, (block_nums*128,), tik.scope_gm, "src0_gm") src1_gm = tik_instance.Tensor(dtype, (block_nums*128,), tik.scope_gm, "src1_gm") with tik_instance.for_range(0, block_nums, block_num=block_nums) as blk_idx: dst_ub = tik_instance.Tensor(dtype, (128,), tik.scope_ubuf, "dst_ub") src0_ub = tik_instance.Tensor(dtype, (128,), tik.scope_ubuf, "src0_ub") src1_ub = tik_instance.Tensor(dtype, (128,), tik.scope_ubuf, "src1_ub") tik_instance.data_move(src0_ub, src0_gm[blk_idx*128], 0, 1, 8, 0, 0) tik_instance.data_move(src1_ub, src1_gm[blk_idx*128], 0, 1, 8, 0, 0) tik_instance.vec_add(128, dst_ub, src0_ub, src1_ub, 1, 8, 8, 8) tik_instance.data_move(dst_gm[blk_idx*128], dst_ub, 0, 8, 1, 0, 0) tik_instance.BuildCCE(kernel_name, [src0_gm, src1_gm], [dst_gm]) return tik_instance if __name__ == '__main__': # 请根据实际昇腾AI处理器型号进行设置 soc_version="xxx" set_current_compile_soc_info(soc_version) # 请根据AI处理器实际版本设置,具体请参考set_current_compile_soc_info接口说明 tik_instance = simple_add_multi_core() data_x = np.ones((3*128,)).astype("float16") data_y = np.ones((3*128,)).astype("float16") feed_dict = {'src0_gm': data_x, 'src1_gm': data_y} model_data, = tik_instance.tikdb.start_debug(feed_dict=feed_dict, interactive=True) print(model_data)
- 对于多核用例,在进入多核for_range语句(tik_instance.for_range(0, block_nums, block_num=block_nums))之前,可以通过打断点指定哪些核进入交互模式,或者通过单步走(默认所有核都会进入交互模式)。对于不进入交互模式的核,会自动执行结束。图10 单步走所有核进入交互模式
图11 通过打断点指定特定核进入交互模式
如果断点不指定核,默认对所有核打断点。
图12 单步调试及多核切换执行
单步调试及多核切换,单步调试过程中只有当前核会执行代码,其它核保持原位置不变。
- 多核断点相关测试。
在进入多核for_range循环(tik_instance.for_range(0, block_nums, block_num=block_nums))之前,如果设置断点,会对所有的核生效,并且会将所有核设置进入交互模式;
如果已经进入多核for_range循环,设置断点默认对所有可交互核生效,“Running”、“Finished”状态的核无效;
如果只想对特定的核设置断点,可以通过字符“block index1 index2 …”指定核编号;
图13 进入多核for_range之前设置断点
断点0对所有核生效,断点1只对核0、1生效,断点2只对核1、2生效。
图14 进入多核for_range之前设置断点指定特定核进入交互状态
断点只对核1、2生效,执行c,可以看到执行到断点处停止,同时核0状态为“Finished”,表示执行结束,不会进入交互模式。
图15 进入多核for_range之后指定核设置断点
设置断点指定核0、1、2,核0已经处于“Finished”状态,不能设置断点,给出告警提示信息,其它两个核设置断点成功。
对于断点disable、enable、clear与设置断点指令类似,在此不再赘述。
图16 enable、disable多核断点
图17 clear命令测试
- continue、quit命令测试。
进入多核交互模式之后,continue命令只会对当前核生效,如果想所有核都继续执行,输入命令“continue -a” or “continue -all”or “c -a”or “c -all”。
quit命令直接退出执行。
图18 continue命令测试
图19 quit命令测试