TIK Program Control
The three basic structures of procedural programming are sequencing, selection, and iteration. In a TIK DSL program, you can use the if_scope, elif_scope, and else_scope APIs to define selection structures and the for_range API to define iteration structures, in addition to the TIK DSL APIs for sequencing. TIK expresses code block semantics by using the with statement of Python.
Selection
TIK provides the if_scope, elif_scope, and else_scope APIs to define selection structures. The if_scope( ), elif_scope( ), and else_scope( ) APIs are represented as with statements in Python. The body of a with statement defines the if, elif, and else code blocks of TIK, in which elif and else parts are optional in syntax. If else_scope appears, it is logically complementary with if_scope at the same indentation level in the script above.
# if_scope: When cond is met, the if code block is executed and TikWithScope is returned. if_scope(cond) # Execute the elif_scope code block if the if_scope condition is not met while the cond2 condition in this statement is met. # The first elif_scope statement must be after the if_scope function. elif_scope(cond2) # Execute the else_scope code block if the previous if_scope and elif_scope conditions are not met. # The else_scope statement must be after the if_scope or elif_scope function. else_scope()
The following is an example.
scalar_a = 4
with self.tik_instance.if_scope(scalar_a == 4): # Condition: scalar_a = 4
scalar_a.set_as(1) # if code block, executed when scalar_a = 4
with self.tik_instance.elif_scope(scalar_a == 5):
scalar_a.set_as(2) # elif code block, executed when scalar_a = 5
with self.tik_instance.else_scope():
scalar_a.set_as(0) # else code block, executed when scalar_a ≠ 4 and scalar_a ≠ 5
# Result: scalar_a = 1
TIK selection statements
a = tik_instance.Scalar("int32", init_value = 2)
with tik_instance.if_scope(a > 1):
a.set_as(0) # if code block, executed when a > 1
with tik_instance.elif_scope(a == 1):
a.set_as(1) # elif code block, executed when a == 1
with tik_instance.else_scope():
a.set_as(2) # else code block, executed when a < 1
# Result: a = 0
Python native statements
a = 2
if a > 1:
a = 0 # if code block, executed when a > 1
elif a < 1:
a = 1 # if code block, executed when a < 1
else:
a = 2 # else code block, executed when a == 1
The differences between TIK selection statements and Python native equivalents are as follows:
- In Python native selection statements, a must be an immediate, which is a constant determined at build time. At build time, only one instruction is built based on the decision-making condition.
- In TIK selection statements, if_scope, elif_scope, and else_scope are common Python instructions, which are built at TIK build time and one of which is executed depending on the value of a. However, only one of the instructions is executed based on the value of a.
Iteration
TIK provides the for_range API to define iteration structures in a TIK DSL program.
tik.Tik.for_range(begint, endt, name="i", thread_num = 1, bock_num = 1)
- begint: initial value of the iteration variable
- endt: final value of the iteration variable
- name: (optional) iteration variable name in TIK DSL. Defaults to i.
- thread_num: (optional) double buffering enable, which controls the instruction parallelism. For details, see Double Buffering.
- block_num: (optional) number of AI Cores used in the iteration, which controls the instruction parallelism. For details, see AI Core Parallelism.
The for_range( ) API is represented by with statements in Python. The body of a with statement defines the iteration body of a TIK for loop. The iteration body of a TIK for loop forms a statement block. TIK statements in the iteration body are executed in parallel when possible.
TIK iteration statements
# Example 1: TIK statement in Python
# Define three tensors: vec_a, vec_b, vec_c
vec_a = tik_instance.Tensor(...)
vec_b = tik_instance.Tensor(...)
vec_c = tik_instance.Tensor(...)
# for_range iteration statement of TIK:
with tik_instance.for_range(0, 10) as i: # iteration variable i, iteration count 10
tik_instance.vec_add(..., vec_c, vec_a, vec_b, ...) # iteration body: computes addition by using the vec_add call
Python native statements
# Example: Python native statements
# Define three tensors: vec_a, vec_b, vec_c
Tensor vec_a(...)
Tensor vec_b(...)
Tensor vec_c(...)
# Python native iteration statement:
for i in range(0, 10): # iteration variable i, iteration count 10
vec_add(vec_c, vec_a, vec_b, ...) # iteration body
The differences between TIK iteration statements and Python native equivalents are as follows:
- In Python native statements, the iteration variable i is an immediate, which is unfolded at build time as follows:
c[0] = a[0] + b[0] c[1] = a[1] + b[1] c[2] = a[2] + b[2] ... c[9] = a[9] + b[9]
- In TIK iteration statements, the iteration variable i is a scalar and is not unfolded at build time. The TIK iteration statement is similar to the Python native iteration statement in the execution phase.
Nested Selection
TIK supports nested selection by nesting its if_scope/elif_scope/else_scope statement and another if_scope/elif_scope/else_scope statement or its for_range statement. However, it is not supported to nest if_scope/elif_scope/else_scope with Python native for statement or if/elif/else statement.
# Positive example 1: nesting TIK's if_scope/else_scope statements
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()
# Positive example 2: nesting TIK's if_scope/else_scope statement with TIK's for statement
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()
# Negative example 1: nesting TIK's if_scope/else_scope statement with a Python native if/else statement
with self.tik_instance.if_scope(...):
do_something()
if x > 2:
do_something()
else:
do_something()
with self.tik_instance.else_scope():
do_something()
# Negative example 2: nesting TIK's if_scope/else_scope statement with a Python native for statement
for i in range(0, 10) :
with self.tik_instance.if_scope(...):
do_something()
with self.tik_instance.else_scope():
do_something()
Nested Iteration
TIK supports nested iteration by nesting its for_range statement with another for_range statement, if_scope/elif_scope/else_scope statement, or Python native for statement. However, it is not supported to nest TIK's for_range statement with the Python native if/elif/else statement.
# Positive example 1: nesting TIK's for statement with TIK's another for statement
with tik_instance.for_range(0, 10) as i:
with tik_instance.for_range(0, 20) as j:
do_something()
# Positive example 2: nesting TIK's for statement with TIK's if_scope/else_scope statement
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()
# Positive example 3: nesting TIK's for statement with a Python native for statement
with tik_instance.for_range(0, 10) as i:
for j in range(0, 20):
do_something()
# Negative example: nesting TIK's for statement with a Python native if/else statement
with tik_instance.for_range(0, 10) as i:
if i == 0:
do_something()
else:
do_something()