Pass Infrastructure基础架构(上)
Pass Infrastructure基礎(chǔ)架構(gòu)(上)
Operation
Pass
- OperationPass
- Op-Specific
OperationPass - Op-Agnostic
Dependent
Dialects
Analysis
Management
Querying
Analyses
Preserving
Analyses
Pass
Failure
Pass
Manager
OpPassManager
Dynamic
Pass Pipelines
Instance
Specific Pass Options
Pass
Statistics
Pass
Registration
Pass
Pipeline Registration
Textual
Pass Pipeline Specification
Declarative
Pass Specification
Tablegen
Specification
Pass
Instrumentation
Standard
Instrumentations
Crash and
Failure Reproduction
Local
Reproducer Generation
pass代表了轉(zhuǎn)換和優(yōu)化的基本基礎(chǔ)架構(gòu)。本文檔概述了MLIR中的pass基礎(chǔ)結(jié)構(gòu)以及如何使用它。
有關(guān)MLIR?及其核心方面(如IR結(jié)構(gòu)和算子)的更多信息,請(qǐng)參見?MLIR規(guī)范。
有關(guān)?在MLIR中進(jìn)行圖形重寫的快速入門,請(qǐng)參見?MLIR?Rewrites。如果轉(zhuǎn)換涉及模式匹配算子DAG,那么這是一個(gè)很好的起點(diǎn)。
算子pass
在MLIR中,抽象和轉(zhuǎn)換的主要單元是一個(gè)?運(yùn)算?。這樣,pass管理器被設(shè)計(jì)為處理不同嵌套級(jí)別的算子實(shí)例。pass通行管理器的結(jié)構(gòu)?和嵌套的概念將在下面詳細(xì)介紹。MLIR中的所有pass均源自O(shè)perationPass,并遵守以下限制;在多線程和其它高級(jí)方案中,任何不符合都會(huì)導(dǎo)致有問(wèn)題的行為:
修改正在算子的當(dāng)前之外引用或依賴的任何狀態(tài)。這包括在父塊中添加或刪除算子,更改屬性(取決于當(dāng)前算子的規(guī)定)/當(dāng)前算子數(shù)/結(jié)果/后繼對(duì)象。
修改另一個(gè)未嵌套在當(dāng)前算子的狀態(tài)。
其它線程可能同時(shí)在這些算子上運(yùn)行。
檢查同級(jí)算子的狀態(tài)。
其它線程可能正在并行修改這些算子。
允許檢查祖先/父項(xiàng)算子的狀態(tài)。
步長(zhǎng)調(diào)用pass狀態(tài)runOnOperation保持可變的。傳遞可能在許多不同的算子上運(yùn)行,而不能保證執(zhí)行順序。
在進(jìn)行多線程處理時(shí),特定的傳遞實(shí)例甚至可能不會(huì)在IR內(nèi)的所有算子上執(zhí)行。因此,傳遞不應(yīng)該依賴于所有算子上的運(yùn)行。
保持任何全局可變狀態(tài),例如源文件中的靜態(tài)變量。所有可變狀態(tài)都應(yīng)pass傳遞實(shí)例來(lái)維護(hù)。
必須是可復(fù)制的
流程管理器可以創(chuàng)建流程的多個(gè)實(shí)例,以并行處理算子。
創(chuàng)建算子傳遞時(shí),根據(jù)使用情況,有兩種不同的類型可供選擇:
OperationPass:特定于算子
在op-specific算子上傳遞給定算子類型明確的算子。此算子類型必須遵守pass管理器設(shè)置的限制,以執(zhí)行pass。
要定義特定于算子通道,派生類必須遵守以下規(guī)定:
從CRTP類繼承,OperationPass并提供算子類型作為附加模板參數(shù)。
覆蓋void
runOnOperation()虛擬方法。
一個(gè)簡(jiǎn)單的過(guò)程可能看起來(lái)像:
namespace {
/// Here
we utilize the CRTP PassWrapper utility class to provide some
///
necessary utility hooks. This is only necessary for passes defined directly
/// in
C++. Passes defined declaratively use a cleaner mechanism for providing
/// these
utilities.
struct MyFunctionPass : public PassWrapper<OperationPass,
MyFunctionPass> {
void runOnOperation() override {
// Get the
current FuncOp operation being operated on.
FuncOp f =
getOperation();
// Walk
the operations within the function.
f.walk([](Operation *inst) {
…
});
}
};
} // end anonymous namespace
///
Register this pass so that it can be built via from a textual pass pipeline.
/// (Pass
registration is discussed more below)
void registerMyPass() {
PassRegistration(
“flag-name-to-invoke-pass-via-mlir-opt”, “Pass
description here”);
}
OperationPass:不可知
op-agnostic pass,添加到通管理器的算子類型進(jìn)行運(yùn)算。這意味著這種類型的pass通道可以在幾種不同的算子類型上進(jìn)行運(yùn)算。通常使用算子接口?和?特征來(lái)存儲(chǔ)此類pass?。此類pass傳遞的示例包括“?常見子表達(dá)式消除”?和“?內(nèi)聯(lián)”?。
要?jiǎng)?chuàng)建算子pass傳遞,派生類必須遵守以下規(guī)定:
從CRTP類繼承OperationPass。
覆蓋虛擬void
runOnOperation()方法。
一個(gè)簡(jiǎn)單的過(guò)程可能看起來(lái)像:
/// Here
we utilize the CRTP PassWrapper utility class to provide some
///
necessary utility hooks. This is only necessary for passes defined directly
/// in
C++. Passes defined declaratively use a cleaner mechanism for providing
/// these
utilities.
struct MyOperationPass : public PassWrapper<OperationPass<>, MyOperationPass> {
void runOnOperation() override {
// Get the
current operation being operated on.
Operation *op =
getOperation();
…
}
};
從屬語(yǔ)言
必須先在MLIRContext中加載語(yǔ)言,然后才能從這些語(yǔ)言創(chuàng)建實(shí)體(算子,類型,屬性等)。在開始執(zhí)行多線程傳遞管道之前,還必須加載語(yǔ)言。為此,可能無(wú)法保證已從其加載的語(yǔ)言創(chuàng)建實(shí)體的過(guò)程,必須pass重寫getDependentDialects()?方法并明確聲明此語(yǔ)言列表來(lái)表達(dá)。
分析管理
一個(gè)重要的概念,以及轉(zhuǎn)換過(guò)程,都是分析。這些在概念上與轉(zhuǎn)換過(guò)程相似,不同之處在于不修改特定算子的情況下計(jì)算信息。在MLIR中,分析不是pass而是pass獨(dú)立式類,這些類是按需延遲計(jì)算并緩存的,以避免不必要的重新計(jì)算。MLIR中的分析必須遵循以下條件:
提供一個(gè)采用Operation*的有效構(gòu)造函數(shù)。
不得修改給定的算子。
分析可能會(huì)提供其它鉤子來(lái)控制各種行為:
bool isInvalidated(const
AnalysisManager::PreservedAnalyses &)
給定一個(gè)保留的分析集,如果該分析確實(shí)無(wú)效,則該分析返回true。如果沒有明確標(biāo)記保留分析,但可以根據(jù)其它屬性(例如分析集)保留(或使之無(wú)效),則可以進(jìn)行更精細(xì)的失效。
查詢分析
基OperationPass類提供用于查詢和保留當(dāng)前正在處理的算子的分析的實(shí)用程序。
OperationPass自動(dòng)提供以下實(shí)用程序來(lái)查詢分析:
getAnalysis<>
獲得當(dāng)前算子的分析,并在必要時(shí)進(jìn)行構(gòu)建。
getCachedAnalysis<>
獲取當(dāng)前算子的分析(如果已經(jīng)存在)。
getCachedParentAnalysis<>
獲取給定父算子的分析(如果存在)。
getCachedChildAnalysis<>
對(duì)給定的子算子(如果存在)進(jìn)行分析。
getChildAnalysis<>
對(duì)給定的子算子進(jìn)行分析,并在必要時(shí)進(jìn)行構(gòu)造。
使用上面定義的示例pass傳遞,看一些示例:
/// An
interesting analysis.
struct MyOperationAnalysis {
// Compute
this analysis with the provided operation.
MyOperationAnalysis(Operation *op);
};
void MyOperationPass::runOnOperation()
{
// Query
MyOperationAnalysis for the current operation.
MyOperationAnalysis &myAnalysis =
getAnalysis();
// Query a
cached instance of MyOperationAnalysis for the current operation.
// It will
not be computed if it doesn’t exist.
auto optionalAnalysis =
getCachedAnalysis();
if (optionalAnalysis)
…
// Query a
cached instance of MyOperationAnalysis for the parent operation of
// the
current operation. It will not be computed if it doesn’t exist.
auto optionalAnalysis =
getCachedParentAnalysis();
if (optionalAnalysis)
…
}
保存分析
在pass查詢后構(gòu)造的分析將被緩存,以避免不必要的計(jì)算(如果稍后再次請(qǐng)求)。為避免過(guò)時(shí)的分析,假定所有分析均pass傳遞而無(wú)效。為避免無(wú)效,過(guò)程必須專門標(biāo)記已知保留的分析。
所有Pass類都會(huì)自動(dòng)提供以下用于保留分析的實(shí)用程序:
markAllAnalysesPreserved
markAnalysesPreserved<>
void MyOperationPass::runOnOperation()
{
// Mark
all analyses as preserved. This is useful if a pass can guarantee
// that no
transformation was performed.
markAllAnalysesPreserved();
// Mark
specific analyses as preserved. This is used if some transformation
// was
performed, but some analyses were either unaffected or explicitly
//
preserved.
markAnalysesPreserved<MyAnalysis,
MyAnalyses…>();
}
pass失敗
允許MLIR中的傳遞正常失敗。如果pass的某些不變性被破壞,可能會(huì)使IR處于某種無(wú)效狀態(tài),則可能發(fā)生這種情況。如果發(fā)生這種情況,signalPassFailure方法直接向pass管理器發(fā)出故障信號(hào)。如果pass指示執(zhí)行時(shí)失敗,則管道中不會(huì)執(zhí)行其它任何傳遞,并且頂級(jí)調(diào)用PassManager::run將返回failure。
void MyOperationPass::runOnOperation()
{
// Signal
failure on a broken invariant.
if (some_broken_invariant)
return signalPassFailure();
}
pass管理器
以上各節(jié)介紹了pass的不同類型及其不變性。本節(jié)介紹PassManager的概念,以及如何將其用于配置和計(jì)劃pass管道。與pass管理相關(guān)的主要類別有兩個(gè),PassManager和和OpPassManager。?PassManager類作為頂層的入口點(diǎn),并包含用于整個(gè)管道的各種配置。OpPassManager用于調(diào)度類會(huì)將以嵌套的一個(gè)特定的水平上運(yùn)行。頂級(jí)?PassManager還用作OpPassManager。
OpPassManager
AnOpPassManager本質(zhì)上是要在特定類型的算子上執(zhí)行的過(guò)程的集合。此算子類型必須符合以下要求:
必須注冊(cè)并標(biāo)記?IsolatedFromAbove?。
預(yù)期傳遞不會(huì)修改正在處理的當(dāng)前算子或更高的算子。如果算子不是孤立的,則可能會(huì)無(wú)意間修改或遍歷不應(yīng)該執(zhí)行的算子的SSA使用列表。
將pass添加到pass管理器addPass。該pass必須是采用?op-specific與相同算子類型OpPassManager的op-agnosticpass,或者是pass。
一個(gè)OpPassManager通常被cretedOpPassManagerpassnest<>方法明確嵌套內(nèi)其它現(xiàn)有管道。此方法采用嵌套通行管理器將要算子的算子類型。在頂層,a?PassManager充當(dāng)OpPassManager。從這個(gè)意義上講,嵌套對(duì)應(yīng)?于?IR區(qū)域內(nèi)的?結(jié)構(gòu)嵌套?。
例如,以下content.mlir:
module {
spv.module “Logical”
“GLSL450” {
func @foo() {
…
}
}
}
具有以下嵌套結(jié)構(gòu):
module
spv.module
function
下面是構(gòu)造在上述結(jié)構(gòu)上運(yùn)行的管道的示例:
// Create
a top-level PassManager class. If an operation type is not
//
explicitly specific, the default is the builtin module operation.
PassManager
pm(ctx);
// Note:
We could also create the above PassManager this way.
PassManager
pm(ctx, /operationName=/“module”);
// Add a
pass on the top-level module operation.
pm.addPass(std::make_unique());
// Nest a
pass manager that operates on spirv.module operations nested
//
directly under the top-level module.
OpPassManager
&nestedModulePM = pm.nestspirv::ModuleOp();
nestedModulePM.addPass(std::make_unique());
// Nest a
pass manager that operates on functions within the nested SPIRV
// module.
OpPassManager
&nestedFunctionPM =
nestedModulePM.nest();
nestedFunctionPM.addPass(std::make_unique());
// Run the
pass manager on the top-level module.
ModuleOp m
= …;
if (failed(pm.run(m)))
… // One of the passes signaled a failure.
上面的過(guò)程管理器包含以下管道結(jié)構(gòu):
OpPassManager
MyModulePass
OpPassManagerspirv::ModuleOp
MySPIRVModulePass
OpPassManager
MyFunctionPass
然后,這些管道一次運(yùn)行一次。這意味著,例如,給定FuncOp上的一系列連續(xù)傳遞,它將在第一個(gè)函數(shù)上全部執(zhí)行,然后在第二個(gè)函數(shù)上全部執(zhí)行,依此類推,直到整個(gè)程序都pass傳遞為止。這提供了幾個(gè)好處:
這改善了編譯器的緩存行為,因?yàn)樗淮沃贿B接一個(gè)功能函數(shù),而不遍歷整個(gè)程序。
pass減少需要調(diào)度的作業(yè)數(shù)量以及提高每個(gè)作業(yè)的效率,這提高了多線程性能。整個(gè)函數(shù)管道可以在每個(gè)函數(shù)上異步運(yùn)行。
動(dòng)態(tài)pass管道
在某些情況下,在另一個(gè)遍歷中運(yùn)行一個(gè)遍歷管道可能是有用的,以允許基于正在運(yùn)行的當(dāng)前算子的某些不變性進(jìn)行配置或過(guò)濾。例如,?Inliner Pass?可能希望在進(jìn)行內(nèi)聯(lián)時(shí),運(yùn)行過(guò)程內(nèi)pass簡(jiǎn)化,以產(chǎn)生更好的成本模型,并提供更好的內(nèi)聯(lián)。為了實(shí)現(xiàn)這一點(diǎn),pass過(guò)程可以O(shè)pPassManagerpassLogicalResult Pass::runPipeline(OpPassManager &,
Operation *)方法對(duì)正在執(zhí)行的當(dāng)前算子或嵌套在當(dāng)前算子內(nèi)的任何算子進(jìn)行任意運(yùn)算。與頂級(jí)PassManager::run方法的結(jié)果類似,此方法返回動(dòng)態(tài)管道是成功還是失敗。下面是一個(gè)簡(jiǎn)單的示例:
void MyModulePass::runOnOperation()
{
ModuleOp module =
getOperation();
if (hasSomeSpecificProperty(module)) {
OpPassManager dynamicPM(“module”);
…; // Build the dynamic pipeline.
if (failed(runPipeline(dynamicPM, module)))
return signalPassFailure();
}
}
注意:盡管上面在runOnOperation方法中構(gòu)造了動(dòng)態(tài)管道?,但這不是必需的,并且應(yīng)盡可能緩存管道,因?yàn)镺pPassManager可以安全地復(fù)制該類。
每當(dāng)pass管道以嵌套方式運(yùn)行時(shí),即當(dāng)無(wú)法與主傳遞管道的其余部分一起靜態(tài)調(diào)度嵌套管道時(shí),都應(yīng)使用本節(jié)中描述的機(jī)制。更具體地說(shuō),PassManager通常不應(yīng)在內(nèi)構(gòu)造a?Pass。使用runPipeline還可以確保將所有分析,?設(shè)備?和其它與過(guò)程管理器相關(guān)的組件與正在執(zhí)行的動(dòng)態(tài)管道集成在一起。
實(shí)例特定的pass選項(xiàng)
MLIR提供了一種內(nèi)置的機(jī)制,用于指定配置其行為的選項(xiàng)。這些選項(xiàng)在遍歷構(gòu)造時(shí)針對(duì)遍歷的每個(gè)實(shí)例獨(dú)立地進(jìn)行解析。使用Option<>和?ListOption<>類定義選項(xiàng),并遵循?LLVM命令行?標(biāo)志定義規(guī)則。參見以下示例:
struct MyPass … {
/// Make
sure that we have a valid default constructor and copy constructor to
/// ensure
that the options are initialized properly.
MyPass() = default;
MyPass(const MyPass& pass) {}
/// Any
parameters after the description are forwarded to llvm:🆑:list and
///
llvm:🆑:opt respectively.
Option
exampleOption{*this, “flag-name”, llvm:🆑:desc("…")};
ListOption
exampleListOption{*this, “l(fā)ist-flag-name”,
llvm:🆑:desc("…")};
};
對(duì)于pass管道,PassPipelineRegistration模板采用其它模板參數(shù)作為可選的Option結(jié)構(gòu)定義。該結(jié)構(gòu)應(yīng)繼承mlir::PassPipelineOptions并包含所需的管道選項(xiàng)。使用PassPipelineRegistration時(shí),構(gòu)造函數(shù)現(xiàn)在使用帶有簽名的函數(shù),該函數(shù)void (OpPassManager &pm, const
MyPipelineOptions&)?應(yīng)構(gòu)造來(lái)自選項(xiàng)的傳遞,并將其傳遞給pm:
struct MyPipelineOptions : public PassPipelineOptions {
// The
structure of these options is the same as those for pass options.
Option
exampleOption{*this, “flag-name”, llvm:🆑:desc("…")};
ListOption
exampleListOption{*this, “l(fā)ist-flag-name”,
llvm:🆑:desc("…")};
};
void registerMyPasses() {
PassPipelineRegistration(
“example-pipeline”, “Run
an example pipeline.”,
[](OpPassManager &pm, const MyPipelineOptions &pipelineOptions) {
//
Initialize the pass manager.
});
}
傳遞統(tǒng)計(jì)信息
統(tǒng)計(jì)信息是跟蹤編譯器正在執(zhí)行的算子以及各種轉(zhuǎn)換的有效性的一種方式。通常,查看特定轉(zhuǎn)換對(duì)特定輸入有什么影響以及觸發(fā)頻率有多有用。傳遞統(tǒng)計(jì)信息特定于每個(gè)傳遞實(shí)例,從而可以查看在傳遞管道內(nèi)特定位置放置特定轉(zhuǎn)換的效果。例如,幫助回答諸如“如果我再次在這里運(yùn)行CSE會(huì)怎樣?”之類的問(wèn)題。
可以使用’Pass :: Statistic’類將統(tǒng)計(jì)信息添加到過(guò)程中。此類采用構(gòu)造函數(shù)自變量:父?jìng)鬟f,名稱和描述。此類的作用類似于算子無(wú)符號(hào)整數(shù),并且可以相應(yīng)地增加和更新。這些統(tǒng)計(jì)信息依賴于相同的基礎(chǔ)結(jié)構(gòu)?llvm::Statistic?,因此具有相似的使用約束。收集的統(tǒng)計(jì)信息可以pass管理器以?編程方式pass?轉(zhuǎn)儲(chǔ)?PassManager::enableStatistics;或pass-pass-statistics和?-pass-statistics-display在命令行上。
一個(gè)例子如下所示:
struct MyPass … {
/// Make
sure that we have a valid default constructor and copy constructor to
/// ensure
that the options are initialized properly.
MyPass() = default;
MyPass(const MyPass& pass) {}
/// Define
the statistic to track during the execution of MyPass.
Statistic exampleStat{this, “exampleStat”, “An
example statistic”};
void runOnOperation() {
…
// Update
the statistic after some invariant was hit.
++exampleStat;
…
}
};
收集的統(tǒng)計(jì)信息可以匯總為兩種類型的視圖:
管道視圖,模擬了pass管理器的結(jié)構(gòu),這是默認(rèn)視圖:
$ mlir-opt
-pass-pipeline=‘func(my-pass,my-pass)’ foo.mlir -pass-statistics
=-------------------------------------------------------------------------=
… Pass statistics
report …
=-------------------------------------------------------------------------=
‘func’ Pipeline
MyPass
(S) 15 exampleStat - An example statistic
VerifierPass
MyPass
(S)? 6
exampleStat - An example statistic
VerifierPass
VerifierPass
列表視圖匯總了特定遍歷所有實(shí)例的統(tǒng)計(jì)信息:
$ mlir-opt
-pass-pipeline=‘func(my-pass, my-pass)’ foo.mlir -pass-statistics
-pass-statistics-display=list
=-------------------------------------------------------------------------=
… Pass statistics
report …
=-------------------------------------------------------------------------=
MyPass
(S) 21 exampleStat - An example statistic
總結(jié)
以上是生活随笔為你收集整理的Pass Infrastructure基础架构(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 多级中间表示概述MLIR
- 下一篇: 算子规范化