forked from PaddlePaddle/Paddle
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add benchmark op. support executing region. add BenchmarkStats. (Padd…
- Loading branch information
Shibo Tao
authored
Mar 17, 2021
1 parent
960f283
commit 5702502
Showing
21 changed files
with
514 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
*~ | ||
*.swp | ||
*.swo | ||
*.swn | ||
*.pyc | ||
*.o | ||
*.a | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// CHECK-LABEL: @benchmark | ||
func @benchmark() { | ||
// CHECK-LABEL: BM:add.f32:Duration(ns) | ||
// CHECK-LABEL: BM:add.f32:Count: 3 | ||
// CHECK-LABEL: BM:add.f32:Time Min(ns) | ||
// CHECK-LABEL: BM:add.f32:Time 50%(ns) | ||
// CHECK-LABEL: BM:add.f32:Time 95%(ns) | ||
// CHECK-LABEL: BM:add.f32:Time 99%(ns) | ||
// CHECK-LABEL: BM:add.f32:CPU Min(ns) | ||
// CHECK-LABEL: BM:add.f32:CPU 50%(ns) | ||
// CHECK-LABEL: BM:add.f32:CPU 95%(ns) | ||
// CHECK-LABEL: BM:add.f32:CPU 99%(ns) | ||
// CHECK-LABEL: BM:add.f32:CPU utilization(percent) | ||
cinn.benchmark "add.f32"() duration_secs = 1, max_count = 3, num_warmup_runs = 3 | ||
{ | ||
%0 = cinn.constant.f32 1.0 | ||
%1 = cinn.constant.f32 2.0 | ||
%res = "cinn.add.f32"(%0, %1) : (f32, f32) -> f32 | ||
"cinn.print.f32"(%res) : (f32) -> () | ||
cinn.return %res : f32 | ||
} | ||
cinn.return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
#include "cinnrt/dialect/test_kernels.h" | ||
|
||
#include "mlir/IR/Builders.h" | ||
#include "mlir/IR/OpDefinition.h" | ||
#include "mlir/IR/OpImplementation.h" | ||
#include "mlir/IR/StandardTypes.h" | ||
#include "mlir/IR/TypeUtilities.h" | ||
|
||
namespace cinnrt::dialect { | ||
|
||
//===----------------------------------------------------------------------===// | ||
// BenchmarkOp | ||
//===----------------------------------------------------------------------===// | ||
|
||
// Parse the BenchmarkOp in the following format | ||
// cinn.benchmark "add.i32"(%c : i32, %d : f32) | ||
// max_count = 100, duration_secs = 1 { | ||
// ... | ||
// } | ||
|
||
static ParseResult parseBenchmarkOp(OpAsmParser &parser, OperationState &result) { | ||
StringAttr nameAttr; | ||
if (parser.parseAttribute(nameAttr, "name", result.attributes)) return failure(); | ||
|
||
// Parse the operands, e.g. (%c : i32, %d : f32) | ||
if (parser.parseLParen()) return failure(); | ||
|
||
SmallVector<OpAsmParser::OperandType, 4> operands; | ||
SmallVector<Type, 4> types; | ||
llvm::SMLoc type_loc = parser.getCurrentLocation(); | ||
|
||
if (parser.parseOptionalRParen()) { | ||
// Parse non-empty operands | ||
do { | ||
// Parse %c : i32, | ||
OpAsmParser::OperandType operand; | ||
Type type; | ||
|
||
if (parser.parseOperand(operand) || parser.parseColonType(type)) return failure(); | ||
|
||
operands.push_back(operand); | ||
types.push_back(type); | ||
|
||
} while (succeeded(parser.parseOptionalComma())); | ||
|
||
if (parser.parseRParen()) return failure(); | ||
} | ||
|
||
if (parser.resolveOperands(operands, types, type_loc, result.operands)) return failure(); | ||
|
||
// Parse the keyword attribute, e.g. max_count = 100, duration_secs = 1 | ||
do { | ||
StringRef attr; | ||
Attribute resultAttr; | ||
if (parser.parseKeyword(&attr) || parser.parseEqual() || | ||
parser.parseAttribute(resultAttr, parser.getBuilder().getIntegerType(32), attr, result.attributes)) | ||
return failure(); | ||
} while (succeeded(parser.parseOptionalComma())); | ||
|
||
// Set the default attribute num_warmup_runs to 1 if unset | ||
auto setDefaultAttrIfUnset = [&](const char *attr_name, int value) { | ||
bool found = | ||
llvm::any_of(result.attributes, [attr_name](const NamedAttribute &attr) { return attr.first == attr_name; }); | ||
if (!found) { | ||
IntegerAttr default_val = parser.getBuilder().getI32IntegerAttr(value); | ||
result.addAttribute(attr_name, default_val); | ||
} | ||
}; | ||
setDefaultAttrIfUnset("num_warmup_runs", 1); | ||
|
||
Region *target = result.addRegion(); | ||
return parser.parseRegion(*target, | ||
operands, | ||
types, | ||
/*enableNameShadowing=*/true); | ||
} | ||
|
||
// Print the BenchmarkOp in the following format | ||
// cinn.benchmark "add.i32"(%c : i32, %d : f32) | ||
// max_count = 100, duration_secs = 1 { | ||
// ... | ||
// } | ||
static void print(OpAsmPrinter &p, BenchmarkOp op) { | ||
p << "cinn.benchmark "; | ||
|
||
// Print the name attribute, e.g "add.i32" | ||
auto name_attr = op.getAttr("name"); | ||
p << name_attr; | ||
|
||
// Print the operands and types, e.g. (%c : i32, %d : f32) | ||
p << '('; | ||
llvm::interleaveComma(llvm::zip(op.getOperands(), op.getOperandTypes()), p, [&](const auto &it) { | ||
p << std::get<0>(it) << " : " << std::get<1>(it); | ||
}); | ||
p << ") "; | ||
|
||
bool need_comma = false; | ||
// Print the attributes, e.g. max_count = 100, duration_secs = 1 | ||
for (auto &name_attr : op.getAttrs()) { | ||
auto id = name_attr.first; | ||
if (id == "name") continue; | ||
if (need_comma) p << ", "; | ||
auto attr = name_attr.second; | ||
p << id << " = "; | ||
if (auto int_attr = attr.dyn_cast<IntegerAttr>()) { | ||
int_attr.getValue().print(p.getStream(), /*isSigned=*/false); | ||
} else { | ||
op.emitOpError("Unexpected attribute"); | ||
} | ||
need_comma = true; | ||
} | ||
p << ' '; | ||
|
||
// Print the region | ||
// Reuse the argument names provided to the op for the bbarg names within | ||
// the region. | ||
p.shadowRegionArgs(op.region(), op.getOperands()); | ||
p.printRegion(op.region(), /*printEntryBlockArgs=*/false); | ||
} | ||
|
||
static LogicalResult verify(BenchmarkOp op) { | ||
// Verify that the target benchmark region has exactly one return value. | ||
auto ®ion = op.region(); | ||
auto &last_op = region.front().back(); | ||
if (last_op.getName().getStringRef() != "cinn.return") { | ||
return op.emitOpError("missing return statement"); | ||
} | ||
if (last_op.getNumOperands() != 1) { | ||
return op.emitOpError("incorrect number of return values. One return value is expected"); | ||
} | ||
|
||
return success(); | ||
} | ||
|
||
#define GET_OP_CLASSES | ||
#include "cinnrt/dialect/test_kernels.cpp.inc" | ||
|
||
} // namespace cinnrt::dialect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#pragma once | ||
#include "mlir/IR/OpDefinition.h" | ||
#include "mlir/Interfaces/SideEffectInterfaces.h" | ||
|
||
namespace cinnrt::dialect { | ||
using namespace mlir; // NOLINT | ||
#define GET_OP_CLASSES | ||
#include "cinnrt/dialect/test_kernels.hpp.inc" | ||
} // namespace cinnrt::dialect |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Operation definitions for testing. | ||
|
||
#ifdef TEST_OPS | ||
#else | ||
#define TEST_OPS | ||
|
||
include "cinnrt/dialect/cinn_base.td" | ||
include "mlir/Interfaces/SideEffectInterfaces.td" | ||
|
||
// Base class for Test dialect ops. | ||
class Test_Op<string mnemonic, list<OpTrait> traits = []> : | ||
Op<CINN_Dialect, mnemonic, !listconcat(traits, [IsolatedFromAbove])> { | ||
|
||
// Each registered op in the Test namespace needs to provide all of a printer, | ||
// parser and verifier. | ||
let printer = [{ return cinnrt::dialect::print(p, *this); }]; | ||
let verifier = [{ return cinnrt::dialect::verify(*this); }]; | ||
let parser = [{ return cinnrt::dialect::parse$cppClass(parser, result); }]; | ||
} | ||
|
||
def BenchmarkOp : Test_Op<"benchmark"> { | ||
let summary = "benchmark operation"; | ||
let description = [{ | ||
The "cinn.benchmark" operation benchmarks the performance of an MLIR | ||
region by executing the given MLIR region repeatedly up to the | ||
`duratino_secs` seconds or `max_count` times. `num_warmup_runs` specifies | ||
the number of warm up runs to run the given MLIR region before the | ||
benchmark starts. | ||
|
||
The target MLIR region can take an arbitrary number of arguments and | ||
should return exactly one value. The arguments for the MLIR region are | ||
provided as the operands of the cinn.benchmark op. | ||
|
||
Example: | ||
cinn.benchmark "add.i32"(%c : i32, %d : f32) max_count = 100, duration_secs = 1 { | ||
// code for benchmarking | ||
... | ||
} | ||
|
||
cinn.benchmark "add.i32"(%c : i32) | ||
duration_secs = 1, | ||
max_count = 100, | ||
num_warmup_runs = 10 { | ||
// The MLIR code to be benchmarked goes here. | ||
// The following code benchmarks the cinn.add.i32 kernel. | ||
%x = cinn.add.i32 %c, %c | ||
// The benchmarked function needs to return exactly one value. | ||
cinn.return %x : i32 | ||
} | ||
}]; | ||
|
||
let regions = (region SizedRegion<1>:$region); | ||
|
||
let arguments = (ins | ||
Variadic<AnyType>, | ||
I32Attr:$duration_secs, | ||
I32Attr:$max_count, | ||
StrAttr:$name, | ||
DefaultValuedAttr<I32Attr, "1">:$num_warmup_runs | ||
); | ||
|
||
let results = (outs); | ||
} | ||
|
||
#endif // TEST_OPS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.