<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【從零開始學(xué)深度學(xué)習(xí)編譯器】十六,MLIR ODS要點(diǎn)總結(jié)上篇

          共 13747字,需瀏覽 28分鐘

           ·

          2021-12-01 22:33

          前言

          【從零開始學(xué)深度學(xué)習(xí)編譯器】十二,MLIR Toy Tutorials學(xué)習(xí)筆記一 中提到MLIR是通過Dialect來統(tǒng)一各種不同級別的IR,即負(fù)責(zé)定義各種Operation(算子)。然后對Dialect和Operation的定義又是通過TabelGen規(guī)范構(gòu)造的,通過TableGen驅(qū)動MLIR的Operation定義也被稱作ODS( Operation Definition Specification) 。我們目前只是簡單認(rèn)識了Toy Tutorials的Dialect和Operation是如何通過ODS定義的,但對ODS本身的語法以及一些限制都沒有太多了解,這就導(dǎo)致在看一些相關(guān)工程的Operation定義時時常陷入迷惑,不知道某個字段是什么含義,或者說自定義Op的時候的應(yīng)當(dāng)如何聲明操作數(shù)和Attr(舉個例子,要將卷積的groups參數(shù)設(shè)置為可選的屬性,應(yīng)該怎么做)。

          因此這篇文章(這是上篇,還有下篇)將基于MLIR的ODS文檔來講解ODS中的一些要點(diǎn),幫助我們更好的了解和上手MLIR。我會把官方文檔中需要注意的點(diǎn)拆成一些小的要點(diǎn)。下面文章中提到的TableGen和ODS不做特別區(qū)分,ODS中的語法也就是TableGen語法。這里介紹的要點(diǎn)在OneFlow對接MLIR時都或多或少用到了,感興趣的可以對照著看看OneFlow的這部分源碼。https://github.com/Oneflow-Inc/oneflow/blob/master/oneflow/ir/include/OneFlow/OneFlowOps.td。另外MLIR和TVM學(xué)習(xí)的所有的文章都匯總到了這個倉庫:https://github.com/BBuf/tvm_mlir_learn ,目前已經(jīng)獲得了170左右star,歡迎點(diǎn)點(diǎn)關(guān)注,謝謝。

          由于篇幅原因以及我最近時間比較緊,這篇文章主要總結(jié)10個要點(diǎn)。剩下的一些要點(diǎn),在下篇文章給出。歡迎大家交流指正。

          1. 為什么要使用ODS來定義Operation

          在MLIR中要定義Operation支持用C++直接定義以及基于ODS框架定義兩種方法。使用C++直接定義要求我們繼承基類Op的一些構(gòu)造方法并重寫,對于每一個Op都要寫一段C++代碼??梢韵氲竭@樣做整個系統(tǒng)的Op定義部分會非常冗余,產(chǎn)生大量可重復(fù)代碼并且可讀性也會比較差。如果基于ODS來定義Operation,我們只需要將Op定義按照ODS的規(guī)范統(tǒng)一寫到一個td文件中,然后使用MLIR提供的代碼生成工具自動生成Operation的C++定義,這種完全auto codegen的方式非常優(yōu)雅的實(shí)現(xiàn)了Operation定義并且需要用戶操心的東西(也就是ODS的語法規(guī)范)更加直觀。

          ODS是MLIR定義Operation的不二選擇,因此我們有必要學(xué)習(xí)ODS的語法規(guī)范。

          2. TableGen語法

          一個TableGen文件(以.td結(jié)尾)包含以下一些語法:

          • TableGen class 類似于C++的class,可以作為模板或者基類去派生子類。
          • TableGen def 類似于C++的對象。以用一個TableGen class的特化來聲明,例如,def MyDef: MyClass<...>;,也可以單獨(dú)使用def MyDef;。它不能用作模板,也不能作為基類去派生子類。
          • TableGen dag 是一種專門用于有向無環(huán)圖元素的類型。一個dag類型帶有一個操作符和零個或者多個參數(shù)。語法形如(operator arg0, arg1, argN.),其中operator可以是任意的TableGen def。參數(shù)可以是任何東西,包括dag本身。我們可以將名稱附加到操作符和參數(shù)上,如(MyOp:$op_name MyArg:$arg_name)。

          想了解更多TableGen支持的類型和表達(dá)式可以點(diǎn)這個鏈接:https://llvm.org/docs/TableGen/ProgRef.html。

          3. Operation定義

          MLIR定義了幾個公共的結(jié)構(gòu)用于幫助定義Operation,并通過TableGen backend : OpDefinitionsGen提供它們的語義。這些公共結(jié)構(gòu)在文件OpBase.td中定義。主要包括:

          • Op類:這是定義Operation時使用的主要結(jié)構(gòu)。在特化該類時,通過下述結(jié)構(gòu)的幫助,指定與Operation有關(guān)的所有事實(shí)。
          • Dialect類:歸屬于同一個邏輯組的Operation會被放置在同一個Dialect下。Dialect包含了方言等級信息。
          • OpTrait類及其子類:它們用于指定Operation的特殊屬性和約束,包括Operation是否具有副作用、Op的輸出是否與輸入具有相同的形狀等。
          • ins/outs標(biāo)記:這是OpDefinitionsGen后端內(nèi)置的兩個特殊標(biāo)記,分別引導(dǎo)操作數(shù)(operands)/屬性(attributes)、結(jié)果(results)的定義。
          • TypeConstraint類及其子類:它們用于指定對操作數(shù)(operands)或結(jié)果(results)的約束。一個值得注意的子類是Type,它代表通用C++類型的約束。
          • AttrConstraint類及其子類:它們用于指定對屬性(attributes)的約束。一個值得注意的子類是Attr,它代表值為通用類型的屬性的約束。

          一個Operation是通過特化Op類定義的,特化后的Op類包含它需要的所有字段的具體內(nèi)容。舉個例子,tf.AvgPool定義如下:

          def?TF_AvgPoolOp?:?TF_Op<"AvgPool",?[NoSideEffect]>?{
          ??let?summary?=?"Performs?average?pooling?on?the?input.";

          ??let?description?=?[{
          Each?entry?in?`output`?is?the?mean?of?the?corresponding?size?`ksize`
          window?in?`value`.
          ??}];

          ??let?arguments?=?(ins
          ????TF_FpTensor:$value,

          ????Confined4>]>:$ksize,
          ????Confined4>]>:$strides,
          ????TF_AnyStrAttrOf<["SAME",?"VALID"]>:$padding,
          ????DefaultValuedAttr"NHWC">:$data_format
          ??);

          ??let?results?=?(outs
          ????TF_FpTensor:$output
          ??);

          ??TF_DerivedOperandTypeAttr?T?=?TF_DerivedOperandTypeAttr<0>;
          }

          下面描述一下定義一個Operation所需的所有字段。有關(guān)支持的字段的完整列表,請參閱Op類的定義(就是OpBase.td)。

          • 「Operation name」 : 就是Operation的名字,比如TensorFlow Dialect中的tf.Add。
          • 「Operation documentation」 : Operation的文檔描述,包含summarydescription兩種,大家看下就懂,不多說。
          • 「Operation arguments」 :Operation的參數(shù),一個Operation有兩種參數(shù)一種是operands即操作數(shù),一種是attributes屬性參數(shù)。其中屬性參數(shù)又分為Natural attributesDerived attributes兩種,前者為自然屬性必須指定比如卷積的輸出通道數(shù),后者為派生屬性比如輸出Tensor的形狀。

          操作數(shù)和屬性都在dag類型的arguments中被指定,以ins引導(dǎo):

          let?arguments?=?(ins
          ??:$,
          ??...
          ??:$,
          ??...
          );

          這里是一個來自TypeConstraint類層次的TableGen def。與此類似的,是一個來自AttrConstraint類層次的TableGen def。在Constraints章節(jié)有更多詳細(xì)內(nèi)容。

          • 「可變操作數(shù)」。定義一個可變操作數(shù),需要用Variadic<...>TypeConstraint包起來。通常,Operation是沒有可變操作數(shù)或者只有一個可變操作數(shù)。對于后一種情況,可以通過靜態(tài)可變操作數(shù)的定義很容易的推導(dǎo)出動態(tài)可變操作數(shù)。但是,如果一個Operation有多個可變長度操作數(shù)(可選的或可變長度的),在沒有來自該操作的進(jìn)一步信息的情況下,就不可能將動態(tài)操作數(shù)歸因于相應(yīng)的靜態(tài)可變長度操作數(shù)定義。因此,需要用SameVariadicOperandSizeAttrSizedOperandSegments特征來表明所有的可變長度操作數(shù)都有與之對應(yīng)的動態(tài)值。
          • 「可選操作數(shù)」。定義一個可選操作數(shù),需要用Optional<...>TypeConstraint包起來。解釋和可變操作數(shù)一樣。
          • 「可選屬性」。定義一個可選屬性,需要使用OptionalAttr<...>AttrConstraint包起來。
          • 「帶默認(rèn)值的可選屬性」。使用DefaultValuedAttr<..., "...">AttrConstraint包起來。DefaultValuedAttr的第二個參數(shù)應(yīng)該是包含C++默認(rèn)值的字符串。舉個例子,一個單精度浮點(diǎn)默認(rèn)值需要被指定為“0.5f”,一個整型數(shù)組的默認(rèn)值需要被指定為"{1, 2, 3}"。
          • 「限制屬性(Confining attributes)」Confined作為一種通用機(jī)制被提供,以幫助對值類型帶來的屬性約束進(jìn)行進(jìn)一步建模??梢酝ㄟ^Confined將較為原始的約束組合成為復(fù)雜約束。舉個例子,一個32bit的整型最小值為10,可以被表示為Confined]>。還有一些其它例子,比如IntMinValue:指定一個大于等于N的整型屬性等等。
          • 「Operation results」:類似操作數(shù),結(jié)果使用tag類型的results聲明,使用outs引導(dǎo)。
          let?results?=?(outs
          ??:$,
          ??...
          );
          • 還有「Operation regions」「Operation successors」目前我還沒用過,暫時不清楚應(yīng)用場景。

          • 「Op的特征和約束(Operation traits and constraints)」:特征是影響語法或語義的Operation屬性。MLIR C++的各種特征在mlir::OpTrait命名空間中。Operation的特征、接口或者約束涉及多個操作數(shù)/屬性/結(jié)果時,要作為Op類的第二個模板參數(shù)傳入。它們都需要繼承于OpTrait類。詳見Constraints章節(jié)。

          4. Operation自動生成的默認(rèn)構(gòu)建方法

          定義了Operation之后,我們怎么構(gòu)建呢??每一個Operation,都會基于Operation的參數(shù)和Operation的返回值自動生成一些builers。舉個例子,給出如下的Operation定義:

          def?MyOp?:?...?{
          ??let?arguments?=?(ins
          ????I32:$i32_operand,
          ????F32:$f32_operand,
          ????...,

          ????I32Attr:$i32_attr,
          ????F32Attr:$f32_attr,
          ????...
          ??);

          ??let?results?=?(outs
          ????I32:$i32_result,
          ????F32:$f32_result,
          ????...
          ??);
          }

          下面的builders被產(chǎn)生:

          //?All?result-types/operands/attributes?have?one?aggregate?parameter.
          //?所有?結(jié)果類型/操作數(shù)/屬性都集合為一個聚合參數(shù)。
          static?void?build(OpBuilder?&odsBuilder,?OperationState?&odsState,
          ??????????????????ArrayRef?resultTypes,
          ??????????????????ValueRange?operands,
          ??????????????????ArrayRef?attributes)
          ;

          //?Each?result-type/operand/attribute?has?a?separate?parameter.?The?parameters
          //?for?attributes?are?of?mlir::Attribute?types.
          //?每一個?結(jié)果類型/操作數(shù)/屬性?都是一個獨(dú)立的參數(shù)。屬性參數(shù)為 mlir::Attribute 類型
          static?void?build(OpBuilder?&odsBuilder,?OperationState?&odsState,
          ??????????????????Type?i32_result,?Type?f32_result,?...,
          ??????????????????Value?i32_operand,?Value?f32_operand,?...,
          ??????????????????IntegerAttr?i32_attr,?FloatAttr?f32_attr,?...)
          ;

          //?Each?result-type/operand/attribute?has?a?separate?parameter.?The?parameters
          //?for?attributes?are?raw?values?unwrapped?with?mlir::Attribute?instances.
          //?(Note?that?this?builder?will?not?always?be?generated.?See?the?following
          //?explanation?for?more?details.)
          //?每一個?結(jié)果類型/操作數(shù)/屬性?都是一個獨(dú)立的參數(shù)。
          //?屬性參數(shù)是未經(jīng) mlir::Attribute 實(shí)例包裝的原始值。
          //?(注意,該構(gòu)建器并不總是生成。詳見下列解釋獲得更多細(xì)節(jié)。)
          static?void?build(OpBuilder?&odsBuilder,?OperationState?&odsState,
          ??????????????????Type?i32_result,?Type?f32_result,?...,
          ??????????????????Value?i32_operand,?Value?f32_operand,?...,
          ??????????????????APInt?i32_attr,?StringRef?f32_attr,?...)
          ;

          //?Each?operand/attribute?has?a?separate?parameter?but?result?type?is?aggregate.
          //?每一個?操作數(shù)/屬性?都是一個獨(dú)立的參數(shù)。但是結(jié)果全部集合為了一個聚合類型。
          static?void?build(OpBuilder?&odsBuilder,?OperationState?&odsState,
          ??????????????????ArrayRef?resultTypes,
          ??????????????????Value?i32_operand,?Value?f32_operand,?...,
          ??????????????????IntegerAttr?i32_attr,?FloatAttr?f32_attr,?...)
          ;

          //?All?operands/attributes?have?aggregate?parameters.
          //?Generated?if?return?type?can?be?inferred.
          //?這個構(gòu)建器只有在返回值類型能夠被推斷出的情況下,才會生成。
          static?void?build(OpBuilder?&odsBuilder,?OperationState?&odsState,
          ??????????????????ValueRange?operands,?ArrayRef?attributes)
          ;

          //?(And?manually?specified?builders?depending?on?the?specific?op.)

          上面的代碼注釋翻譯已經(jīng)解釋了這些builder的不同之處。并且可能還存在一些其它的builder,請參考https://mlir.llvm.org/docs/OpDefinitions/#run-mlir-tblgen-to-see-the-generated-content 這里的文檔進(jìn)行查看。

          5. 自定義builder方法

          假設(shè)上面生成的C++代碼中構(gòu)造方法沒有我們所期待的,這個時候我們就需要自定義builder方法。比如:

          def?MyOp?:?Op<"my_op",?[]>?{
          ??let?arguments?=?(ins?F32Attr:$attr);

          ??let?builders?=?[
          ????OpBuilder<(ins?"float":$val)>
          ??];
          }

          builders字段是添加到Op類的自定義構(gòu)建器列表。在這個例子中,我們提供了一個方便的builer,它接受浮點(diǎn)值而不是屬性。在使用TableGen dag的ODS中,許多函數(shù)聲明都使用ins前綴。緊隨其后的是用逗號分隔的列表,列表的每一項(xiàng)都是類型與帶$前綴的名字的組合。上述定義將會轉(zhuǎn)換成如下格式的builder:

          class?MyOp?:?/*...*/?{
          ??/*...*/
          ??static?void?build(::mlir::OpBuilder?&builder,?::mlir::OperationState?&state,
          ????????????????????float?val)
          ;
          };

          注意,這個builder有兩個額外的前置參數(shù)。這些參數(shù)對于構(gòu)建Operation很有用。特別地,為了能夠通過該方法構(gòu)建Operation,必須向state填充該Operation的屬性,操作數(shù),域和返回值類型。builder可以用于構(gòu)建屬于Op的任意IR對象,例如類型或嵌套操作。當(dāng)類型與名字轉(zhuǎn)換為C++代碼時,它們應(yīng)該是有效的C++結(jié)構(gòu),一個類型(在Op的命名空間中)與一個標(biāo)識符(例如,class不是一個有效標(biāo)識符)。可以在ODS中直接提供builder的實(shí)現(xiàn),使用如下TableGen的代碼塊:

          def?MyOp?:?Op<"my_op",?[]>?{
          ??let?arguments?=?(ins?F32Attr:$attr);

          ??let?builders?=?[
          ????OpBuilder<(ins?"float":$val),?[{
          ??????$_state.addAttribute("attr",?$_builder.getF32FloatAttr(val));
          ????}]>
          ??];
          }

          $_builder$_state這兩個特殊參數(shù)等效于builderstateins部分中的參數(shù)可以被直接使用,比如val。builer的c++代碼實(shí)現(xiàn)會通過替換ODS中的特殊變量來完成,要保證builder ODS實(shí)現(xiàn)的其他部分是有效的C++結(jié)構(gòu)。雖然對代碼大小沒有限制,但我們鼓勵只在ODS中內(nèi)聯(lián)較短定義的builder,而將定義較長的builder的定義放在C++文件中。最后,如果某些參數(shù)需要默認(rèn)值,可以使用 CArg 定義它們以包裝類型和此值,如下所示:

          def?MyOp?:?Op<"my_op",?[]>?{
          ??let?arguments?=?(ins?F32Attr:$attr);

          ??let?builders?=?[
          ????OpBuilder<(ins?CArg<"float",?"0.5f">:$val),?[{
          ??????$_state.addAttribute("attr",?$_builder.getF32FloatAttr(val));
          ????}]>
          ??];
          }

          轉(zhuǎn)換后的C++代碼中,默認(rèn)參數(shù)只在聲明中出現(xiàn),而不會在定義中出現(xiàn),這符合C++要求。

          ///?Header?file.
          class?MyOp?:?/*...*/?{
          ??/*...*/
          ??static?void?build(::mlir::OpBuilder?&builder,?::mlir::OperationState?&state,
          ????????????????????float?val?=?0.5f)
          ;
          };

          ///?Source?file.
          MyOp::build(::mlir::OpBuilder?&builder,?::mlir::OperationState?&state,
          ????????????float?val)?{
          ??state.addAttribute("attr",?builder.getF32FloatAttr(val));
          }

          6. 聲明指令格式(Declarative Assembly Format)

          Operation的聲明指令格式可以在與Operation操作數(shù)、屬性等匹配的聲明性字符串中指定。具有表達(dá)需要解析以構(gòu)建Operation的附加信息能力:

          def?CallOp?:?Std_Op<"call",?...>?{
          ??let?arguments?=?(ins?FlatSymbolRefAttr:$callee,?Variadic:$args);
          ??let?results?=?(outs?Variadic);

          ??let?assemblyFormat?=?[{
          ????$callee?`(`?$args?`)`?attr-dict?`:`?functional-type($args,?results)
          ??}];
          }

          主要由三部分組成:

          • 「Directives:指令」。指令是一種帶有可選參數(shù)的內(nèi)置函數(shù)??捎玫闹噶钣?code style="font-size: 14px;word-wrap: break-word;padding: 2px 4px;border-radius: 4px;margin: 0 2px;background-color: rgba(27,31,35,.05);font-family: Operator Mono, Consolas, Monaco, Menlo, monospace;word-break: break-all;color: #595959;">attr-dict,attr-dict-with-keywordoperands,ref等等。
          • 「字面值(Literals)」 。字面值是用``包裹起來的鍵值或者標(biāo)點(diǎn)符號。下列是有效的標(biāo)點(diǎn)符號集合::, ,, =, <, >, (, ), {, }, [, ], ->, ?, +, * 。\n標(biāo)點(diǎn)符號有另起一行的效果。如下:
          let?assemblyFormat?=?[{
          ??`{`?`\n`?`?`?`?`?`this_is_on_a_newline`?`\n`?`}`?attr-dict
          }];
          %results?=?my.operation?{
          ??this_is_on_a_newline
          }

          內(nèi)容為空的字面量可用于刪除隱式插入某些字面量元素后的空格。例如)或者]等等。舉個例子,]可能出現(xiàn)在輸出output的末尾,但它并不是格式中的最后一個元素,在這個例子里可以使用 "]``"刪除掉后續(xù)的空格。

          • 「Variables(變量)」。變量是注冊在Operation上的實(shí)體,例如Operation的參數(shù)(屬性或操作數(shù)),域,結(jié)果,后繼者,等等。在CallOp中,變量代表$callee$args。屬性變量將顯示其各自的值類型。除非其值的類型可以構(gòu)造,在這種情況下,屬性變量的值類型可以省略。

          7. 自定義指令(Custom Directives) & 可選組(Optional Groups)

          聲明指令格式規(guī)范在格式化一個Operation的時候能夠處理大部分的普通場景。對于那些想要在格式中指定Operations的某一部分的Op,聲明式語法是不支持的,這個時候可以嘗試使用自定義指令。

          在某些情況下,Operations可能具有“可選”信息,例如 屬性或一組空的可變參數(shù)操作數(shù)。在這些情況下,可以根據(jù)此信息的存在將匯編格式的一部分標(biāo)記為可選。

          這兩部分比較復(fù)雜,我還沒用到,所以這里不展開,感興趣請看官方文檔。

          8. 類型推斷

          格式的一項(xiàng)要求是操作數(shù)和結(jié)果的類型必須始終存在。在某些情況下,可以通過類型約束或其他可用信息來推斷變量的類型。在這些情況下,可以從格式中省略該變量的類型。

          • 「Buildable Types??蓸?gòu)建類型」 。一些類型約束可能只有一種表示,允許它們直接構(gòu)建;例如 I32Index類型。ODS 中的類型可以通過設(shè)置 builderCall 字段或從 BuildableType 類繼承來將自己標(biāo)記為可構(gòu)建。
          • 「Trait Equality Constraints。特征等價約束」。有許多Operations具有在Operations上注冊為已知類型相等特征的約束;例如,select Operation的真、假和結(jié)果值通常具有相同的類型。匯編格式可以檢查這些等價的約束以辨別缺失變量的類型。當(dāng)前支持的特征有:AllTypesMatch、TypesMatchWithSameTypeOperandsSameOperandsAndResultType。
          • 「InferTypeOpInterface」 。實(shí)現(xiàn) InferTypeOpInterface 的Operations可以在其匯編格式中省略其結(jié)果類型,因?yàn)榭梢詮牟僮鲾?shù)中推斷出結(jié)果類型。
          • 「hasCanonicalizer」。此布爾字段指示是否已為此Operation定義規(guī)范化模式。如果它是 1,那么 ::getCanonicalizationPatterns() 應(yīng)該被定義。
          • 「hasCanonicalizeMethod」。當(dāng)此布爾字段設(shè)置為 true 時,表示操作為簡單的“matchAndRewrite”樣式規(guī)范化模式實(shí)現(xiàn)了canonicalize方法。如果 hasCanonicalizer 為 0,則實(shí)現(xiàn) ::getCanonicalizationPatterns() 的實(shí)現(xiàn)來調(diào)用此函數(shù)。
          • 「hasFolder」。此布爾字段指示是否已為此操作定義了通用折疊規(guī)則。如果它是 1,那么 ::fold() 應(yīng)該被定義。

          9. 額外聲明

          表驅(qū)動操作定義的目標(biāo)之一是為每個操作自動生成盡可能多的邏輯和方法。話雖如此,總會有無法涵蓋的長尾案例。對于這種情況,您可以使用 extraClassDeclaration。extraClassDeclaration 中的代碼將逐字復(fù)制到生成的 C++ op 類。

          請注意,extraClassDeclaration 是一種針對高級用戶的長尾案例的機(jī)制;對于尚未實(shí)施的廣泛適用的情況,改善基礎(chǔ)設(shè)施是可取的。

          10. 生成C++代碼

          OpDefinitionsGen (https://github.com/llvm/llvm-project/blob/main/mlir/tools/mlir-tblgen/OpDefinitionsGen.cpp)處理Operation定義規(guī)范文件(.td文件)并生成兩個包含相應(yīng) C++ 代碼的文件:一個用于聲明,另一個用于定義。前者通過 -gen-op-decls 命令行選項(xiàng)生成,而后者通過 -gen-op-defs 選項(xiàng)生成。

          定義文件包含所有的op方法定義,可以通過定義GET_OP_CLASSES來包含和啟用。對于每個操作,OpDefinitionsGen 生成一個操作類和一個操作數(shù)適配器類(operand adaptor class)。此外,它還包含一個以逗號分隔的所有已定義Operations的列表,可以通過定義 GET_OP_LIST 來包含和啟用這些操作。

          • 「Class name and namespaces」 。

          對于每個Operation,其生成的C++類名是使用TableGen def為前綴的名字,并刪除了Dialect前綴。第一個_用作分隔符。例如,對于def TF_AddOp,C++類名會是AddOp。我們移除了TF前綴,因?yàn)樗嵌鄠€Operation作用域。其它Dialect也可以定義自己的AddOps。

          生成的C++類的namespace將來自Dialect的cppNamespace字段。舉個例子,如果一個Dialect的NamespaceA::B,那么該Dialect的Op將被放置在namespace A { namespace B { ... } }。如果Dialect沒有指定cppNamespace,我們就使用方言的名稱作為命名空間。

          這意味著生成的 C++ 類的名稱不一定與Operation 名稱中的操作名稱完全匹配。這是為了允許靈活命名以滿足編碼風(fēng)格要求。

          • 「Operand adaptors」

          對于每個Operation,MLIR會自動生成一個操作數(shù)適配器。這個類解決了訪問作為列表值提供的操作數(shù)而不使用“魔術(shù)“”常量的問題。操作數(shù)適配器引用一個 Value 數(shù)組,并提供與Operation類中名稱相同的方法來訪問它們。例如,對于二元算術(shù)運(yùn)算,它可以提供 .lhs() 來訪問第一個操作數(shù)和 .rhs() 來訪問第二個操作數(shù)。操作數(shù)適配器類與Operation類位于同一命名空間中,類的名稱由Operation類的名稱后面接一個Adaptor組成。

          操作數(shù)適配器也可以用于處理Operation的函數(shù)模板:

          template?<typename?BinaryOpTy>
          std::pair?zip(BinaryOpTy?&&op)?{
          ??return?std::make_pair(op.lhs(),?op.rhs());;
          }

          void?process(AddOp?op,?ArrayRef?newOperands)?{
          ??zip(op);
          ??zip(Adaptor(newOperands));
          ??/*...*/
          }

          在OneFlow中,我們可以看到生成的UserOpAdaptor代碼。里面提供了一系列接口可以訪問Operation的操作數(shù)以及相關(guān)屬性。

          //===----------------------------------------------------------------------===//
          //?::mlir::oneflow::UserOp?declarations
          //===----------------------------------------------------------------------===//

          class?UserOpAdaptor?{
          public:
          ??UserOpAdaptor(::mlir::ValueRange?values,?::mlir::DictionaryAttr?attrs,?::mlir::RegionRange?regions?=?{});
          ??UserOpAdaptor(UserOp?&op);
          ??::mlir::ValueRange?getOperands();
          ??std::pair<unsigned,?unsigned>?getODSOperandIndexAndLength(unsigned?index);
          ??::mlir::ValueRange?getODSOperands(unsigned?index);
          ??::mlir::ValueRange?data_input();
          ??::mlir::ValueRange?ctrl_inputs();
          ??::mlir::DictionaryAttr?getAttributes();
          ??::mlir::StringAttr?op_name();
          ??::mlir::BoolAttr?trainable();
          ??::mlir::StringAttr?device_tag();
          ??::mlir::ArrayAttr?device_name();
          ??::mlir::IntegerAttr?scope_symbol_id();
          ??::mlir::ArrayAttr?hierarchy();
          ??::mlir::DenseIntElementsAttr?operand_segment_sizes();
          ??::mlir::DenseIntElementsAttr?result_segment_sizes();
          ??::mlir::StringAttr?op_type_name();
          ??::mlir::ArrayAttr?input_lbn_segment_keys();
          ??::mlir::ArrayAttr?input_lbn_segment_sizes();
          ??::mlir::ArrayAttr?output_lbn_segment_keys();
          ??::mlir::ArrayAttr?output_lbn_segment_sizes();
          ??::mlir::ArrayAttr?output_lbns();
          ??::mlir::LogicalResult?verify(::mlir::Location?loc);

          private:
          ??::mlir::ValueRange?odsOperands;
          ??::mlir::DictionaryAttr?odsAttrs;
          ??::mlir::RegionRange?odsRegions;
          };

          11. 約束

          約束(Constraint)是表驅(qū)動Operation定義中的一個核心概念:Operation驗(yàn)證和圖Operation匹配都是基于滿足約束。因此,Operation定義和重寫規(guī)則都直接涉及寫入約束。MLIR在OpBase.td(https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/IR/OpBase.td)中定義了Constraint基類。一個Operation的約束可以覆蓋不同的范圍,可能是:

          • 僅關(guān)注單個屬性(例如大于 5 的 32 位整數(shù))
          • 多個操作數(shù)和結(jié)果(例如,第一個結(jié)果的形狀必須與第一個操作數(shù)(可理解為Tensor)相同)
          • 操作本身固有的。(例如沒有副作用,參考Transpose Op消除那個案例)

          我們將它們分別稱為單實(shí)體約束、多實(shí)體約束和特征。

          ?

          這里就不寫小結(jié)了,下篇文章總結(jié)完再寫。

          ?


          瀏覽 165
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  www.五月 | 91aigaogao | 国产午夜精品久久久久 | 一级黄色电影网 | 777777亚洲成人 |