跳转至主要内容
Version: v1.5.0

Taichi 与 Python 程序间的差异

尽管 Taichi 使用 Python 作为前端,在许多方面它遵循不一样的规则,比如:

  1. Taichi 仅支持程序中非静态 if/for/while 作用域以外的 return 语句

  2. if/for/while 代码块定义的变量不能从代码块之外被访问。

  3. 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 的运行时实现 。 因此,运算符 innot 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 部分支持列表推导和字典推导, 但不支持集合推导。

对于列表推导和字典推导,他们中的 iffor 语句的评估是在编译期间完成的。 迭代器和条件在 静态范围内是隐式的。

操作符 is

目前,Taichi 不支持运算符 isis not