Skip to content

Commit b018699

Browse files
authored
Merge branch 'main' into test_backend_dynamic
2 parents b33e229 + 733dfac commit b018699

35 files changed

+1245
-510
lines changed

docs/AddCustomAccelerators.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ In general, onnx-mlir handles custom accelerators as pluggins which can be turne
55
Besides this document, [NNPA accelerator](../src/Accelerators/NNPA) can be used as an example that has been deployed in onnx-mlir.
66

77
## 1. Code folder
8+
89
In onnx-mlir, all code for an accelerator should be put inside a separate folder under `src/Accelerators`. Thus, the first step to support an accelerator is to create a folder for it inside `src/Accelerators`.
910

1011
The folder name will be used as the accelerator name in onnx-mlir. In particular, it is used to
@@ -15,22 +16,25 @@ The folder name will be used as the accelerator name in onnx-mlir. In particular
1516
The folder content is flexible depending on each accelerator. However, we recomment to follow the same structure as the root folder of `onnx-mlir` as much as possbile. This helps maintain the consitency across the whole project.
1617

1718
### 1.1 Build accelerators in onnx-mlir
18-
To build accelerators in onnx-mlir, use the cmake variable `ONNX_MLIR_ACCELERATORS` when building onnx-mlir. `ONNX_MLIR_ACCELERATORS` accepts a comma-separated list of accelerator names. For example,
19+
20+
To build accelerators in onnx-mlir, use the cmake variable `ONNX_MLIR_ACCELERATORS` when building onnx-mlir. `ONNX_MLIR_ACCELERATORS` accepts a semicolon-separated list of accelerator names. For example,
1921
```bash
2022
$ cd build
21-
$ cmake .. -DONNX_MLIR_ACCELERATORS=accel1,accel2
23+
$ cmake .. -DONNX_MLIR_ACCELERATORS=accel1;accel2
2224
```
2325

2426
### 1.2 Compile a model to run with selected accelerators.
25-
The compiler command `onnx-mlir` has an option, i.e. `--maccel`, to compile a model for selected accelerators. `--maccel` accepts a comma-separated list of accelerator names. For example,
27+
28+
The compiler command `onnx-mlir` has an option, i.e. `--maccel`, to compile a model for selected accelerators. For each accelerator add a `--maccel=accel_name` entry. For example,
2629

2730
```bash
28-
$ onnx-mlir --maccel=accel1,accel2 model.onnx
31+
$ onnx-mlir --maccel=accel1 --maccel=accel2 model.onnx
2932
```
3033

3134
Only built accelerators can be used with `--maccel`.
3235

3336
### 1.3 Run passes related to selected accelerators.
37+
3438
Passes defined by an accelerator can be run or tested via `onnx-mlir-opt` command by using option `--maccel` which is similar to `--maccel` in `onnx-mlir` (See Sec. [1.2](#1.2-compile-a-model-to-run-with-selected-accelerators)). For example, to call a pass `--optimize-data-layout` defined by accelerator `accel1`:
3539

3640
```bash
@@ -41,6 +45,24 @@ Only built accelerators can be used with `--maccel`.
4145

4246
## 2. Code integration
4347

48+
### 2.1 Macro
49+
50+
Each accelerator is required to define a few macros. These needs to be included in [onnx_mlir::accel::Accelerator](../src/Accelerators/Accelerator.hpp). These macros are:
51+
52+
1. `INSTRUMENTSTAGE_ENUM_<accel_name>`
53+
2. `INSTRUMENTSTAGE_CL_ENUM_<accel_name>`
54+
3. `PROFILEIR_CL_ENUM_<accel_name>`
55+
56+
Replace `<accel_name>` with the name of the accelerator, for example if your accelerator is named `ACCEL1` use:
57+
58+
```C
59+
#define INSTRUMENTSTAGE_ENUM_ACCEL1
60+
#define INSTRUMENTSTAGE_CL_ENUM_ACCEL1
61+
#define PROFILEIR_CL_ENUM_ACCEL1
62+
```
63+
64+
### 2.2 Dialects and passes
65+
4466
Writing code in MLIR typically involves desiging dialects and passes. So does supporting an accelerator. Thus, to integrate accelerator code into onnx-mlir is to register dialects and passes in onnx-mlir.
4567

4668
We provide a base class [onnx_mlir::accel::Accelerator](../src/Accelerators/Accelerator.hpp) from which users can define an inherited class and write hooks to register dialects and passes.

src/Builder/FrontendDialectTransformer.cpp

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ SUPPRESS_WARNINGS_POP
5151
#include <array>
5252
#include <fstream>
5353
#include <map>
54+
#include <sstream>
55+
#include <string>
5456
#include <unordered_map>
5557
#include <vector>
5658

@@ -450,6 +452,27 @@ class FrontendGenImpl {
450452
return attributes;
451453
}
452454

455+
// Generate a string vector from the dimParams option string
456+
void getInputDimParamsMapFromOption(std::string optionStr,
457+
std::map<int, std::string> &paramStrMap,
458+
std::string &paramStrForAllArgs) {
459+
std::stringstream paramStrStream(optionStr);
460+
std::string dimParamStr;
461+
while (std::getline(paramStrStream, dimParamStr, '|')) {
462+
size_t pos = dimParamStr.find(':');
463+
assert((pos > 0) && "invalid dimParams option string");
464+
int idx = stoi(dimParamStr.substr(0, pos));
465+
dimParamStr = dimParamStr.substr(pos + 1);
466+
std::replace(dimParamStr.begin(), dimParamStr.end(), '=', ':');
467+
if (idx < 0) // set all arguments
468+
paramStrForAllArgs = dimParamStr;
469+
else {
470+
paramStrMap[idx] = dimParamStr;
471+
}
472+
}
473+
return;
474+
}
475+
453476
/*!
454477
* An alternative graph importing procedure for importing ONNX subgraphs.
455478
* ONNX subgraphs, unlike the main computation graph, are imported as regions
@@ -490,6 +513,10 @@ class FrontendGenImpl {
490513
// See https://github.com/onnx/onnx/blob/main/docs/IR.md for more
491514
// information about dim_param.
492515
llvm::SmallVector<std::string, 4> inputDimParams, outputDimParams;
516+
std::map<int, std::string> inputDimParamsFromOption;
517+
std::string inputDimParamsFromOptionForAllArgs;
518+
getInputDimParamsMapFromOption(options_.dimParams, inputDimParamsFromOption,
519+
inputDimParamsFromOptionForAllArgs);
493520

494521
// Import the input tensor types that are not constant and not initialized.
495522
int inputIndex = 0;
@@ -500,7 +527,16 @@ class FrontendGenImpl {
500527
std::string dimParams = "";
501528
Type argTy = ImportType(input.type(), &dimParams);
502529
argTy = modelInputShaper_.reshape(inputIndex, argTy);
503-
if (!dimParams.empty())
530+
// For each input tensor, use either all dimensions by the compiler
531+
// option OR all dimensions in the original onnx model. Dimensions
532+
// from the option and the model in a single input tensor are not
533+
// merged.
534+
if (inputDimParamsFromOption.find(inputIndex) !=
535+
inputDimParamsFromOption.end())
536+
inputDimParams.emplace_back(inputDimParamsFromOption[inputIndex]);
537+
else if (!inputDimParamsFromOptionForAllArgs.empty())
538+
inputDimParams.emplace_back(inputDimParamsFromOptionForAllArgs);
539+
else if (!dimParams.empty())
504540
inputDimParams.emplace_back(dimParams);
505541

506542
argTypes.emplace_back(argTy);

src/Builder/FrontendDialectTransformer.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ struct ImportOptions {
5555
// - (arg0: tensor<3x4x5xf32>, arg1: tensor<10x5xf32>)
5656
//
5757
std::string shapeInformation = "";
58+
// Custom onnx.dim_params attributes for the graph inputs for specifying
59+
// relationship among their dynamic dimensions.
60+
// Its format is 'input_id:dim_id=sym,dim_id=sym,...|input_id:
61+
// dim_id=sym,dim_id=sym,...|input_id...'
62+
// E.g. An ONNX model has two dynamic inputs
63+
// - (arg0: tensor<?x5xf32>, arg1: tensor<?x5xf32>)
64+
// If we want to specify that the first unknown dimension of arg0 and the
65+
// first unknown dimension of arg1 are the same, we can assign the two
66+
// dimensions to the same symbol "batch" as follows.
67+
// - dimParams = '0:0=batch|1:0=batch'
68+
//
69+
std::string dimParams = "";
5870
// Directory to look for external data if any tensor has external
5971
// data location. If empty then external data is disabled.
6072
std::string externalDataDir = "";

src/Compiler/CompilerOptions.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ std::vector<std::string> onnxConstPropDisablePatterns; // common for both
4141
bool enableONNXHybridPass; // common for both
4242
std::vector<std::string> functionsToDecompose; // common for both
4343
std::string opsForCall; // common for both
44+
bool disableKrnlOpFusion; // common for both
4445
EmissionTargetType emissionTarget; // onnx-mlir only
4546
bool invokeOnnxVersionConverter; // onnx-mlir only
4647
bool preserveLocations; // onnx-mlir only
@@ -51,6 +52,7 @@ bool preserveMLIR; // onnx-mlir only
5152
bool useOnnxModelTypes; // onnx-mlir only
5253
int repeatOnnxTransform; // onnx-mlir only
5354
std::string shapeInformation; // onnx-mlir only
55+
std::string dimParams; // onnx-mlir only
5456
ModelSize modelSize; // onnx-mlir only
5557
bool storeConstantsToFile; // onnx-mlir only
5658
float constantsToFileTotalThreshold; // onnx-mlir only
@@ -82,6 +84,7 @@ std::vector<std::string> extraLibs; // onnx-mlir only
8284
ProfileIRs profileIR; // onnx-mlir only
8385
OptReport optReport; // onnx-mlir only
8486
bool useOldBufferization; // onnx-mlir only
87+
bool enableTiming; // onnx-mlir only
8588
bool split_input_file; // onnx-mlir-opt only
8689
bool verify_diagnostics; // onnx-mlir-opt only
8790
bool verify_passes; // onnx-mlir-opt only
@@ -200,6 +203,13 @@ static llvm::cl::list<std::string, std::vector<std::string>>
200203
llvm::cl::location(functionsToDecompose),
201204
llvm::cl::cat(OnnxMlirCommonOptions));
202205

206+
static llvm::cl::opt<bool, true> disableKrnlOpFusionOpt(
207+
"disable-krnl-op-fusion",
208+
llvm::cl::desc("disable op fusion in onnx-to-krnl pass (default=false)\n"
209+
"Set to 'true' if you want to disable fusion."),
210+
llvm::cl::location(disableKrnlOpFusion), llvm::cl::init(false),
211+
llvm::cl::cat(OnnxMlirCommonOptions));
212+
203213
static llvm::cl::opt<bool, true> disableRecomposeOptionOpt("disable-recompose",
204214
llvm::cl::desc("Disable recomposition of ONNX operations."),
205215
llvm::cl::location(disableRecomposeOption), llvm::cl::init(false),
@@ -281,6 +291,23 @@ static llvm::cl::opt<std::string, true> shapeInformationOpt("shapeInformation",
281291
llvm::cl::value_desc("value"), llvm::cl::location(shapeInformation),
282292
llvm::cl::cat(OnnxMlirOptions));
283293

294+
static llvm::cl::opt<std::string, true> dimParamsOpt("dimParams",
295+
llvm::cl::desc(
296+
"Custom onnx.dim_params attributes for the inputs of the ONNX model for"
297+
"specifying relationship among dynamic dimensions of the inputs.\n"
298+
"\"value\" is in the format of "
299+
"\"INPUT_ID1:D1=S1,D2=S2,...,Dn=Sn|INPUT_ID2:D1=T1,D2=T2,...Dn=Tn|"
300+
"...\" where \"INPUT_ID1, INPUT_ID2, ...\" are input indices "
301+
"(starting from 0 or being -1 for all input indices), and\n"
302+
"\"S1, S2, ...\" and \"T2, T2, ...\" are symbols to specify that same "
303+
"symbols have the same value. "
304+
"All dimensions of onnx.dim_params for a specified input index in "
305+
"the original onnx model are cleared and repalced by this option. "
306+
"onnx.dim_params for other input indices in the original onnx model "
307+
"are not cleared"),
308+
llvm::cl::value_desc("value"), llvm::cl::location(dimParams),
309+
llvm::cl::cat(OnnxMlirOptions));
310+
284311
// Default value is defined by the OnnxMlirEnvOptionName constant string
285312
// variable, but the default setting mechanism here cannot be used here as we
286313
// need to evaluate this value prior to the compiler options being set. Proper
@@ -546,6 +573,12 @@ static llvm::cl::opt<OptReport, true> optReportOpt("opt-report",
546573
clEnumVal(Simd, "Provide report on how SIMD is applied to ONNX ops.")),
547574
llvm::cl::init(OptReport::NoReport), llvm::cl::cat(OnnxMlirOptions));
548575

576+
static llvm::cl::opt<bool, true> enable_timing("enable-timing",
577+
llvm::cl::desc("Enable compile timing (default is false)\n"
578+
"Set to 'true' if you want to enable compile timing."),
579+
llvm::cl::location(enableTiming), llvm::cl::init(false),
580+
llvm::cl::cat(OnnxMlirOptions));
581+
549582
// Options for onnx-mlir-opt only
550583
static llvm::cl::opt<bool, true> split_input_file_opt("split-input-file",
551584
llvm::cl::desc("Split the input file into pieces and process each "

src/Compiler/CompilerOptions.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ extern std::vector<std::string> onnxConstPropDisablePatterns; // common for both
8484
extern bool enableONNXHybridPass; // common for both
8585
extern std::vector<std::string> functionsToDecompose; // common for both
8686
extern std::string opsForCall; // common for both
87+
extern bool disableKrnlOpFusion; // common for both
8788
extern EmissionTargetType emissionTarget; // onnx-mlir only
8889
extern bool invokeOnnxVersionConverter; // onnx-mlir only
8990
extern bool preserveLocations; // onnx-mlir only
@@ -94,6 +95,7 @@ extern bool preserveMLIR; // onnx-mlir only
9495
extern bool useOnnxModelTypes; // onnx-mlir only
9596
extern int repeatOnnxTransform; // onnx-mlir only
9697
extern std::string shapeInformation; // onnx-mlir only
98+
extern std::string dimParams; // onnx-mlir only
9799
extern ModelSize modelSize; // onnx-mlir only
98100
extern bool storeConstantsToFile; // onnx-mlir only
99101
extern float constantsToFileTotalThreshold; // onnx-mlir only
@@ -125,6 +127,7 @@ extern std::vector<std::string> extraLibs; // onnx-mlir only
125127
extern ProfileIRs profileIR; // onnx-mlir only
126128
extern OptReport optReport; // onnx-mlir only
127129
extern bool useOldBufferization; // onnx-mlir only
130+
extern bool enableTiming; // onnx-mlir only
128131
extern bool split_input_file; // onnx-mlir-opt only
129132
extern bool verify_diagnostics; // onnx-mlir-opt only
130133
extern bool verify_passes; // onnx-mlir-opt only

src/Compiler/CompilerUtils.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,16 @@
1515
#include "CompilerUtils.hpp"
1616

1717
#include <fstream>
18+
#include <memory>
1819
#include <regex>
1920

2021
#include "mlir/Dialect/Func/IR/FuncOps.h"
2122
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
2223
#include "mlir/Parser/Parser.h"
24+
#include "mlir/Pass/Pass.h"
2325
#include "mlir/Pass/PassManager.h"
2426
#include "mlir/Support/FileUtilities.h"
27+
#include "mlir/Support/Timing.h"
2528
#include "mlir/Target/LLVMIR/Dialect/Builtin/BuiltinToLLVMIRTranslation.h"
2629
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
2730
#include "mlir/Target/LLVMIR/Export.h"
@@ -35,6 +38,7 @@
3538
#include "llvm/Support/SourceMgr.h"
3639
#include "llvm/Support/TargetSelect.h"
3740
#include "llvm/Support/ToolOutputFile.h"
41+
#include "llvm/Support/raw_ostream.h"
3842
#include "llvm/Target/TargetMachine.h"
3943

4044
#include "src/Accelerators/Accelerator.hpp"
@@ -49,6 +53,8 @@
4953
using namespace mlir;
5054
using namespace onnx_mlir;
5155

56+
mlir::DefaultTimingManager timingManager;
57+
mlir::TimingScope rootTimingScope;
5258
namespace onnx_mlir {
5359

5460
// Make a function that forces preserving all files using the runtime arguments
@@ -327,6 +333,8 @@ std::string getTargetFilename(
327333
// Returns 0 on success, error code on failure.
328334
static int genLLVMBitcode(const mlir::OwningOpRef<ModuleOp> &module,
329335
std::string outputNameNoExt, std::string optimizedBitcodeNameWithExt) {
336+
auto llvmTiming = rootTimingScope.nest(
337+
"[onnx-mlir] Compiling MLIR module to LLVM Optimized Bitcode");
330338
std::error_code error;
331339

332340
// Write bitcode to a file.
@@ -397,7 +405,8 @@ static int genLLVMBitcode(const mlir::OwningOpRef<ModuleOp> &module,
397405
// Return 0 on success, error code on failure.
398406
static int genModelObject(
399407
std::string bitcodeNameWithExt, std::string &modelObjNameWithExt) {
400-
408+
auto objectTiming =
409+
rootTimingScope.nest("[onnx-mlir] Compiling LLVM Bitcode to Object File");
401410
std::string llcPath = getToolPath("llc");
402411
Command llvmToObj(/*exePath=*/llcPath);
403412
setXllcOption({"--code-model", modelSizeStr[modelSize]});
@@ -418,6 +427,8 @@ static int genModelObject(
418427
// Return 0 on success, error code on failure.
419428
static int genJniObject(const mlir::OwningOpRef<ModuleOp> &module,
420429
std::string jniSharedLibPath, std::string jniObjPath) {
430+
auto jniTiming =
431+
rootTimingScope.nest("[onnx-mlir] Compiling JNI Object File");
421432
Command ar(/*exePath=*/getToolPath("ar", true));
422433
int rc = ar.appendStr("x")
423434
// old version of ar does not support --output so comment out
@@ -436,7 +447,8 @@ static int genJniObject(const mlir::OwningOpRef<ModuleOp> &module,
436447
static int genSharedLib(std::string sharedLibNameWithExt,
437448
std::vector<std::string> opts, std::vector<std::string> objs,
438449
std::vector<std::string> libs, std::vector<std::string> libDirs) {
439-
450+
auto sharedLibTiming =
451+
rootTimingScope.nest("[onnx-mlir] Linking Shared Library");
440452
#ifdef _WIN32
441453
std::vector<std::string> outputOpt = {"/Fe:" + sharedLibNameWithExt};
442454
// link has to be before libpath since they need to be passed through to the
@@ -486,6 +498,7 @@ static int genSharedLib(std::string sharedLibNameWithExt,
486498
// Return 0 on success, error code on failure.
487499
static int genJniJar(const mlir::OwningOpRef<ModuleOp> &module,
488500
std::string modelSharedLibPath, std::string modelJniJarPath) {
501+
auto jniJarTiming = rootTimingScope.nest("[onnx-mlir] Creating JNI Jar");
489502
llvm::SmallString<8> libraryPath(getLibraryPath());
490503
llvm::sys::path::append(libraryPath, "javaruntime.jar");
491504
std::string javaRuntimeJarPath = llvm::StringRef(libraryPath).str();
@@ -623,6 +636,7 @@ int processInputFile(StringRef inputFilename, mlir::MLIRContext &context,
623636
options.useOnnxModelTypes = useOnnxModelTypes;
624637
options.invokeOnnxVersionConverter = invokeOnnxVersionConverter;
625638
options.shapeInformation = shapeInformation;
639+
options.dimParams = dimParams;
626640
options.allowSorting = allowSorting;
627641
options.externalDataDir = dirName(inputFilename);
628642
options.functionsToDecompose.insert(options.functionsToDecompose.end(),
@@ -879,6 +893,9 @@ static int emitOutput(mlir::OwningOpRef<ModuleOp> &module,
879893
int compileModule(mlir::OwningOpRef<ModuleOp> &module,
880894
mlir::MLIRContext &context, std::string outputNameNoExt,
881895
EmissionTargetType emissionTarget) {
896+
auto compileModuleTiming =
897+
rootTimingScope.nest("[onnx-mlir] Compiling Module using MLIR");
898+
882899
int rc = setupModule(module, context, outputNameNoExt);
883900
if (rc != CompilerSuccess)
884901
return rc;
@@ -904,10 +921,14 @@ int compileModule(mlir::OwningOpRef<ModuleOp> &module,
904921
heapLogFileame, reportHeapBefore, reportHeapAfter));
905922
}
906923
(void)mlir::applyPassManagerCLOptions(pm);
907-
mlir::applyDefaultTimingPassManagerCLOptions(pm);
924+
925+
if (enableTiming) {
926+
pm.enableTiming(compileModuleTiming);
927+
}
908928

909929
if (mlir::failed(pm.run(*module)))
910930
return CompilerFailure;
931+
compileModuleTiming.stop();
911932
return emitOutput(module, context, outputNameNoExt, pm, emissionTarget);
912933
}
913934

src/Compiler/CompilerUtils.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,17 @@
1818

1919
#include "mlir/IR/BuiltinOps.h"
2020
#include "mlir/IR/OwningOpRef.h"
21+
#include "mlir/Support/Timing.h"
2122
#include "llvm/ADT/StringRef.h"
2223
#include "llvm/Support/Path.h"
2324

2425
#include <optional>
2526
#include <string>
2627
#include <vector>
2728

29+
extern mlir::DefaultTimingManager timingManager;
30+
extern mlir::TimingScope rootTimingScope;
31+
2832
namespace onnx_mlir {
2933

3034
struct Command {

0 commit comments

Comments
 (0)