MLIRについてもう少し具体的な例を勉強するために、資料を読み込んでいくことにした。
以下の資料を参考にした。Chris Lattnerの所属がSiFiveに変わっているので、比較的最近の資料だ。
MLIRはMulti-Level Intermediate Representation Compiler Ifrastructureの略称である。
2004にLLVMを開発したときの想定構成。1つのIRを用意してすべてを解決する。マルチターゲット、解析、最適化など。
ところがこれだけでは上手く行かなくなった。LLVM-IRだけでなく複数の表現形式を使用する必要がある。現在のLLVM IRでは並列性やループなどの表現形式に問題がある。
Clangも同様。LLVM IRを出力するだけでなく、様々なアノテーションを出力する必要が生じたり、もはやC++の複雑な言語構文を表現するためにhあLLVM IRは非効率になった。
最終的にこのようになった。言語毎に独自のIRを定義する必要が生じ、そこからLLVM IRに落とし込むというフローが導入されている。
TensorFlowも同様に多くのコンパイラシステムを導入しており、またまた多くのIRが内部で生成されている。
ドメイン固有のIRを作ることにはメリットとデメリットがある。
- メリット:高レベルでのドメイン固有の最適化が適用可能。
- デメリット:同じような機能をIR毎に何度も実装する必要がある。
MLIR : Multi-Level IRの導入
MLIRはLLVMのIRと似ている。SSAレジスタベース、明示的な型定義。モジュール、関数、ブロック、オペレーション。
型システムとしては「スカラ」「ベクトル」「テンソル」などを定義することができる。
MLIRにはビルトインのオペレーションが存在しない。PassによってUnknownなオペレーションが処理されることを期待している。
オペレーションには常にopcodeとソースの該当するlocation情報が入っている。
命令にはSSAのresultsとoperands、Attributes、Block operands、Regionsなどの情報が入っている。
TensorFlowによる複雑なMLIRの例:
5つの引数を取りそれぞれの型が定義されている。
%arg0 : tensor<8x?x?x8xf32>
%arg1 : tensor<8xf32>
%arg2 : tensor<8xf32>
%arg3 : tensor<8xf32>
%arg4 : tensor<8xf32>
また、このオペレーションには5つの演算結果が含まれる。
tensor<8x?x?x8xf32>, tensor<8xf32>, tensor<8xf32>, tensor<8xf32>, tensor<8xf32>
また、このオペレーションにはAttributesが付いている。
data_format : "NHWC"
epsilon: 0.001
is_training: false
リージョンのネストも実現できる。
まさにコンパイラIRのJSONと言えよう。