Taichi 与 Python 程序间的差异
尽管 Taichi 使用 Python 作为前端,在许多方面它遵循不一样的规则,比如:
Return 语句与返回类型注释
- 如果一个 Taichi kernel/函数没有 return 语句,那么它不可以有返回类型注释。
- 如果Taichi kernel 有 return 语句,那么它必须有返回类型注释。
- 如果 Taichi 函数有 return 语句,建议使用返回类型注释,它将来是强制性的。
@ti.kernel
def error_kernel_no_return_annotation():
return 0 # Error: Have return statement but have no return type annotation
@ti.kernel
def error_kernel_no_return() -> ti.i32: # Error: Have return type annotation but have no return statement
pass
@ti.func
def error_func_no_return() -> ti.i32: # Error: Have return type annotation but have no return statement
pass
- Return 语句不能在非静态
if
/for
/while
作用域内。
@ti.kernel
def error_return_inside_non_static_if(a: ti.i32) -> ti.i32:
if a:
return 1 # Error: Return statement inside if scope
- 编译器会丢弃第一个 return 语句后的代码。
@ti.kernel
def discarded_after_first_return(a: ti.i32) -> ti.i32:
return 1
if a: # Discarded
return 1 # Discarded
discarded_after_first_return(0) # OK: returns 1
- 如果代码中有 编译时间评估 ,无论如何请确保代码中有 return 语句。 不然,当一个没有 return 语句的分支被选中后系统就会报错。
@ti.kernel
def return_inside_static_if(a: ti.template()) -> ti.i32:
if ti.static(a):
return 1
return 0
return_inside_static_if(1) # OK: Returns 1
return_inside_static_if(0) # OK: Returns 0
@ti.kernel
def return_inside_static_if_no_return_outside(a: ti.template()) -> ti.i32:
if ti.static(a):
return 1
return_inside_static_if_no_return_outside(1) # OK: Returns 1
return_inside_static_if_no_return_outside(0) # Error: No return statement
@ti.kernel
def ok_return_inside_static_for() -> ti.i32:
a = 0
for i in ti.static(range(10)): # Static for
a += i
if ti.static(i == 8): # Static if
return a # OK: Returns 36
变量作用范围
Python 规定在 if
/for
/while
代码块定义的变量可以从代码块之外被访问。 然而, Taichi 的变量只能在被定义的代码块内被访问。
@ti.kernel
def error_access_var_outside_for() -> ti.i32:
for i in range(10):
a = i
return a # Error: variable "a" not found
@ti.kernel
def error_access_var_outside_if(a: ti.i32) -> ti.i32:
if a:
b = 1
else:
b = 2
return b # Error: variable "b" not found
@ti.kernel
def ok_define_var_before_if(a: ti.i32) -> ti.i32:
b = 0
if a:
b = 1
else:
b = 2
return b # OK: "b" is defined before "if"
ok_define_var_before_if(0) # Returns 2
目前不支持或仅部分支持的 Python 语言功能
集合、列表、字典和操作符 in
目前,Taichi 不支持 set
。
List 或 dictionary 在分配变量之前是一个 Python list 或 Python dictionary。 然而,在分配给变量后,list 的内容还有 dictionary 的值(而不是键)都被转换成 Taichi 变量。
Taichi 目前并没有 in
的运行时实现 。 因此,运算符 in
和 not in
仅在 静态作用域内 (ti.static()
内)有效。
@ti.kernel
def list_without_assign() -> ti.i32:
if ti.static(1 in [1, 2]): # [1, 2]
return 1
return 0
list_without_assign() # Returns 1
@ti.kernel
def list_assigned() -> ti.i32:
a = [1, 2] # a: [Variable(1), Variable(2)]
if ti.static(1 in a): # 1 is not in [Variable(1), Variable(2)]
return 1
return 0
list_assigned() # Returns 0
@ti.kernel
def error_non_static_in():
if i in [1, 2]: # Error: Cannot use `in` outside static scope
pass
推导
Taichi 部分支持列表推导和字典推导, 但不支持集合推导。
对于列表推导和字典推导,他们中的 if
和 for
语句的评估是在编译期间完成的。 迭代器和条件在 静态范围内是隐式的。
操作符 is
目前,Taichi 不支持运算符 is
和 is not
。