Toy 語言
???本教程,將會借助一個玩具語言來講解,這個語言我們稱其為 Toy。Toy 是一個基于張量的語言,它允許你定義函數,執行一些數學計算,并且打印結果。做這樣的設定,是因為我們希望讓教程保持簡明;codegen 部分將會限制張量的維度小于等于2,而且Toy中的數據類型都是 64bit 浮點型的,也就是C語言中的double類型。于是,所有的值都隱式定義為double精度的,而且,所有的值都是不變的常量,也就是說,每一個操作的返回值都會是新分配的變量,再就是,重新分配變量是自動化管理的。上述說明已經足夠了,沒有什么比通讀一個示例更有助于理解 MLIR 的目的和方法了。
def main() {# Define a variable `a` with shape <2, 3>, initialized with the literal value.# The shape is inferred from the supplied literal.#定義一個形狀為2行3列的變量a,如下字面逐元素初始化。變量的形狀通過提供的初始化來推導。var a = [[1, 2, 3], [4, 5, 6]];# b is identical to a, the literal tensor is implicitly reshaped: defining new# variables is the way to reshape tensors (element count must match).#變量b與a是一樣的,這個初始化的方式是隱式地變形了:變形張量是通過定義新的變量的方式實現的,但是元素個數必須能對上。var b<2, 3> = [1, 2, 3, 4, 5, 6];# transpose() and print() are the only builtin, the following will transpose# a and b and perform an element-wise multiplication before printing the result.#transpose() 和 print() 函數是唯一內置的函數,接下來將會轉置a 和 b,并且逐元素做乘法運算,然后打印結果。print(transpose(a) * transpose(b));
}
類型檢查是通過類型推導靜態執行的;Toy 語言僅僅要求在必要的時候指定張量的類型。函數是通用的:它們的參數未指定階數,也就是說,我們知道函數的每個參數是一個張量,但是我們不知道它們的維度。為每一個新發現的調用點的簽名,都被特化處理。讓我們看一遍之前的示例代碼,這次我們增加了一個 用戶自定義的函數:
# User defined generic function that operates on unknown shaped arguments.
# 用戶自定義的通用函數,它作用在未知形狀的參數上
def multiply_transpose(a, b) {return transpose(a) * transpose(b);
}def main() {# Define a variable `a` with shape <2, 3>, initialized with the literal value.var a = [[1, 2, 3], [4, 5, 6]];var b<2, 3> = [1, 2, 3, 4, 5, 6];# This call will specialize `multiply_transpose` with <2, 3> for both# arguments and deduce a return type of <3, 2> in initialization of `c`.# 這個調用將會給函數 multiply_transpose 指定兩個形狀為2行3列的張量作為參數,并且推導出返回值c的形狀為3行2列,按此做初始化。var c = multiply_transpose(a, b);# A second call to `multiply_transpose` with <2, 3> for both arguments will# reuse the previously specialized and inferred version and return <3, 2>.#基本同上var d = multiply_transpose(b, a);# A new call with <3, 2> (instead of <2, 3>) for both dimensions will# trigger another specialization of `multiply_transpose`.# 這里是一個新的調用,入參的形狀變為3行2列,而不再是2行3列,這將會觸發特化另一新的 multiply_transpose函數的實現。var e = multiply_transpose(c, d);# Finally, calling into `multiply_transpose` with incompatible shapes# (<2, 3> and <3, 2>) will trigger a shape inference error.# 最后,調用對函數 multiply_transpose 做一次參數形狀不兼容的調用,這將會觸發一個形狀推導錯誤。var f = multiply_transpose(a, c);
}
dump AST
從上邊的代碼生成的 AST 是相當簡單的。這里對它做了轉儲:
Module:Function Proto 'multiply_transpose' @test/Examples/Toy/Ch1/ast.toy:4:1Params: [a, b]Block {ReturnBinOp: * @test/Examples/Toy/Ch1/ast.toy:5:25Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:10var: a @test/Examples/Toy/Ch1/ast.toy:5:20]Call 'transpose' [ @test/Examples/Toy/Ch1/ast.toy:5:25var: b @test/Examples/Toy/Ch1/ast.toy:5:35]} // BlockFunction Proto 'main' @test/Examples/Toy/Ch1/ast.toy:8:1Params: []Block {VarDecl a<> @test/Examples/Toy/Ch1/ast.toy:11:3Literal: <2, 3>[ <3>[ 1.000000e+00, 2.000000e+00, 3.000000e+00], <3>[ 4.000000e+00, 5.000000e+00, 6.000000e+00]] @test/Examples/Toy/Ch1/ast.toy:11:11VarDecl b<2, 3> @test/Examples/Toy/Ch1/ast.toy:15:3Literal: <6>[ 1.000000e+00, 2.000000e+00, 3.000000e+00, 4.000000e+00, 5.000000e+00, 6.000000e+00] @test/Examples/Toy/Ch1/ast.toy:15:17VarDecl c<> @test/Examples/Toy/Ch1/ast.toy:19:3Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:19:11var: a @test/Examples/Toy/Ch1/ast.toy:19:30var: b @test/Examples/Toy/Ch1/ast.toy:19:33]VarDecl d<> @test/Examples/Toy/Ch1/ast.toy:22:3Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:22:11var: b @test/Examples/Toy/Ch1/ast.toy:22:30var: a @test/Examples/Toy/Ch1/ast.toy:22:33]VarDecl e<> @test/Examples/Toy/Ch1/ast.toy:25:3Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:25:11var: c @test/Examples/Toy/Ch1/ast.toy:25:30var: d @test/Examples/Toy/Ch1/ast.toy:25:33]VarDecl f<> @test/Examples/Toy/Ch1/ast.toy:28:3Call 'multiply_transpose' [ @test/Examples/Toy/Ch1/ast.toy:28:11var: a @test/Examples/Toy/Ch1/ast.toy:28:30var: c @test/Examples/Toy/Ch1/ast.toy:28:33]} // Block
可以在文件夾 examples/toy/Ch1/ 中的示例代碼上重新生成這個AST。請嘗試運行:
path/to/BUILD/bin/toyc-ch1 test/Examples/Toy/Ch1/ast.toy -emit=ast