下载
中文
注册

TIK程序控制

过程式编程的程序结构元素包括:顺序、分支、循环。TIK提供if_scopeelif_scopeelse_scope接口在TIK DSL程序中定义分支结构;提供for_range接口在TIK DSL程序中定义循环结构;除此之外,其它的TIK DSL接口在当前的代码块中形成顺序结构。TIK借用Python的with语句特性,表达代码块语义。

分支

TIK提供if_scopeelif_scopeelse_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()