TIK程序控制
过程式编程的程序结构元素包括:顺序、分支、循环。TIK提供if_scope、elif_scope和else_scope接口在TIK DSL程序中定义分支结构;提供for_range接口在TIK DSL程序中定义循环结构;除此之外,其它的TIK DSL接口在当前的代码块中形成顺序结构。TIK借用Python的with语句特性,表达代码块语义。
分支
TIK提供if_scope、elif_scope和else_scope接口定义分支结构。if_scope( )、elif_scope( )和else_scope( )接口在python脚本中以with语句的形式出现,with语句的语句体定义了TIK的if/elif/else代码块,elif与else部分在语法上为可选部分。else_scope如果出现,则与脚本上文中位于相同缩进等级的if_scope形成逻辑互补关系。
# if_scope接口:当满足cond时,执行if代码块。返回值:TikWithScope if_scope(cond) # 当if_scope语句条件不满足时,且本语句cond2条件满足时,执行此elif_scope代码块 # 首个elif_scope必须在if_scope函数后 elif_scope(cond2) # 当前面的if_scope以及elif_scope条件都不满足,则执行此else_scope代码块 # else_scope必须在if_scope/elif_scope函数后 else_scope()
示例如下:
scalar_a = 4 with self.tik_instance.if_scope(scalar_a == 4): # 判断条件:scalar_a 为 4 scalar_a.set_as(1) # if代码块,scalar_a 为 4时执行 with self.tik_instance.elif_scope(scalar_a == 5): scalar_a.set_as(2) # elif代码块,scalar_a 为 5时执行 with self.tik_instance.else_scope(): scalar_a.set_as(0) # else代码块,scalar_a 不为4且不为5时执行 # 运行结果: scalar_a = 1
TIK分支语句:
a = tik_instance.Scalar("int32", init_value = 2) with tik_instance.if_scope(a > 1): a.set_as(0) # if代码块:a > 1 时执行 with tik_instance.elif_scope(a == 1): a.set_as(1) # elif代码块:a == 1 时执行 with tik_instance.else_scope(): a.set_as(2) # else代码块:a < 1 时执行 # 运行结果:a = 0
Python原生语句:
a = 2 if a > 1: a = 0 # if代码块:a > 1 时执行 elif a < 1: a = 1 # if代码块:a < 1 时执行 else: a = 2 # else代码块:a == 1 时执行
TIK的分支语句和Python原生语句的主要区别在于:
- Python原生分支语句:要求a必须是立即数,是在编译时就可以确定的常量数据。编译时会根据判断条件,只编译其中一条指令。
- TIK分支语句:if_scope、elif_scope和else_scope是普通的python指令,几条指令在tik编译的时候都会被编译到,而在运行时,根据a的值,运行其中一条指令。
循环
TIK提供for_range接口在TIK DSL程序中定义循环结构,定义方法为:
tik.Tik.for_range(begint, endt, name="i", thread_num = 1, bock_num = 1)
- begint:循环变量起始值。
- endt:循环变量终止值。
- name:可选,TIK DSL中循环变量名,默认为“i”。
- thread_num:可选,循环中是否开启Double Buffer,用于控制指令并行度。相关功能说明请参考double buffer。
- block_num:可选循环中使用的核数,用于控制指令并行度。相关功能说明请参考多核。
for_range( )接口在python脚本中以with语句的形式出现,with语句的语句体定义了TIK for循环的循环体。TIK中for循环的循环体构成一个语句块。循环体中的TIK语句,将以尽可能并行的方式被执行。
TIK循环语句:
# 示例 1 :TIK的Python语句 # 定义vec_a, vec_b, vec_c三个Tensor vec_a = tik_instance.Tensor(...) vec_b = tik_instance.Tensor(...) vec_c = tik_instance.Tensor(...) # TIK的for_range循环语句: with tik_instance.for_range(0, 10) as i: # 循环变量 i,循环次数 10 tik_instance.vec_add(..., vec_c, vec_a, vec_b, ...) # 循环体语句:调用vec_add接口实现加加法运算
Python原生语句:
# 示例:Python原生语句 # 定义vec_a, vec_b, vec_c三个Tensor Tensor vec_a(...) Tensor vec_b(...) Tensor vec_c(...) # Python原生循环语句: for i in range(0, 10): # 循环变量 i,循环次数 10 vec_add(vec_c, vec_a, vec_b, ...) # 循环体语句
TIK的循环语句和Python原生语句的主要区别在于:
- Python原生语句:循环变量 i 是立即数,在编译时期会把循环展开如下:
c[0] = a[0] + b[0] c[1] = a[1] + b[1] c[2] = a[2] + b[2] ... c[9] = a[9] + b[9]
- TIK循环语句:TIK的循环语句中,循环变量 i 是scalar类型,在编译时期不会将循环展开。运行时期TIK循环语句与Python原生循环语句类似。
分支嵌套
TIK的if_scope/elif_scope/else_scope语句可以和另一个if_scope/elif_scope/else_scope、以及tik的for_range互相嵌套,但不能和python原生的for或if/elif/else语句互相嵌套。
# 示例 1 : tik 的 if/else_scope可以和另一个if/else_scope嵌套,允许: with self.tik_instance.if_scope(...): do_something() with self.tik_instance.if_scope(...): do_something() with self.tik_instance.else_scope(): do_something() with self.tik_instance.else_scope(): do_something() # 示例 2 : tik 的 if/else_scope可以和tik的for嵌套,允许: with self.tik_instance.if_scope(...): with tik_instance.for_range(0, 10) as i: do_something() with self.tik_instance.else_scope(): do_something() # 错误示例 1 : tik 的 if/else_scope不可以和python原生if/else嵌套: with self.tik_instance.if_scope(...): do_something() if x > 2: do_something() else: do_something() with self.tik_instance.else_scope(): do_something() # 错误示例 2 : tik 的 if/else_scope不可以和python原生for嵌套: for i in range(0, 10) : with self.tik_instance.if_scope(...): do_something() with self.tik_instance.else_scope(): do_something()
循环嵌套
TIK的for_range语句可以和另一个tik 的for_range、tik的if_scope/elif_scope/else_scope、以及python原生的for互相嵌套,但不能和python原生的if/elif/else语句互相嵌套。
# 示例 1:tik的for和另一个tik的for嵌套,允许: with tik_instance.for_range(0, 10) as i: with tik_instance.for_range(0, 20) as j: do_something() # 示例 2:tik的for和另一个tik的if/else_scope嵌套,允许: with tik_instance.for_range(0, 10) as i: with self.tik_instance.if_scope(...): do_something() with self.tik_instance.else_scope(): do_something() # 示例 3:tik的for和另一个python原生的for嵌套,允许: with tik_instance.for_range(0, 10) as i: for j in range(0, 20): do_something() # 错误示例:tik的for不可以和另一个python原生的if/else嵌套: with tik_instance.for_range(0, 10) as i: if i == 0: do_something() else: do_something()