Import all initialized tensors as dense constants (#30)

* Import initialized tensor as dense attribute

* Import all initialize tensors as dense constants

* Remove unintentional code

* Fix value attribute format in shape inference tests of reshape

* Readd rank check for reshape's shape inference

* Remove a redundant variable

Co-authored-by: Gheorghe-Teodor Bercea <gt.bercea@gmail.com>
This commit is contained in:
Tung D. Le 2020-03-17 00:17:28 +09:00 committed by GitHub
parent c46880d5c6
commit d86591d61a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 32 deletions

View File

@ -129,10 +129,16 @@ mlir::Value InitializedTensorMapping::EmitInitializerForInputTensor(
// Initializer for input. // Initializer for input.
onnx::TensorProto initializer = GetInitializedTensor(name); onnx::TensorProto initializer = GetInitializedTensor(name);
// Tensor dimensions.
llvm::ArrayRef<int64_t> tensorDims(initializer.dims().data(),
initializer.dims().size());
// Emit ConstantOp and record the mapping between the input and // Emit ConstantOp and record the mapping between the input and
// the constant value. // the constant value.
mlir::ArrayAttr constantArrayAttribute; // Create value attribute.
mlir::DenseElementsAttr constantDenseAttribute;
mlir::Type elementType; mlir::Type elementType;
mlir::ShapedType tensorType;
int length; int length;
switch (initializer.data_type()) { switch (initializer.data_type()) {
case (onnx::TensorProto::FLOAT): { case (onnx::TensorProto::FLOAT): {
@ -141,8 +147,9 @@ mlir::Value InitializedTensorMapping::EmitInitializerForInputTensor(
std::vector<float> arrayAttrInitializer( std::vector<float> arrayAttrInitializer(
typeArray, typeArray + length); typeArray, typeArray + length);
llvm::ArrayRef<float> array(typeArray, length); llvm::ArrayRef<float> array(typeArray, length);
constantArrayAttribute = builder.getF32ArrayAttr(array);
elementType = builder.getF32Type(); elementType = builder.getF32Type();
tensorType = mlir::RankedTensorType::get(tensorDims, elementType);
constantDenseAttribute = mlir::DenseElementsAttr::get(tensorType, array);
break; break;
} }
case (onnx::TensorProto::INT32): { case (onnx::TensorProto::INT32): {
@ -151,8 +158,9 @@ mlir::Value InitializedTensorMapping::EmitInitializerForInputTensor(
std::vector<int32_t> arrayAttrInitializer( std::vector<int32_t> arrayAttrInitializer(
typeArray, typeArray + length); typeArray, typeArray + length);
llvm::ArrayRef<int32_t> array(typeArray, length); llvm::ArrayRef<int32_t> array(typeArray, length);
constantArrayAttribute = builder.getI32ArrayAttr(array);
elementType = builder.getIntegerType(32); elementType = builder.getIntegerType(32);
tensorType = mlir::RankedTensorType::get(tensorDims, elementType);
constantDenseAttribute = mlir::DenseElementsAttr::get(tensorType, array);
break; break;
} }
case (onnx::TensorProto::INT64): { case (onnx::TensorProto::INT64): {
@ -161,25 +169,16 @@ mlir::Value InitializedTensorMapping::EmitInitializerForInputTensor(
std::vector<int64_t> arrayAttrInitializer( std::vector<int64_t> arrayAttrInitializer(
typeArray, typeArray + length); typeArray, typeArray + length);
llvm::ArrayRef<int64_t> array(typeArray, length); llvm::ArrayRef<int64_t> array(typeArray, length);
constantArrayAttribute = builder.getI64ArrayAttr(array);
elementType = builder.getIntegerType(64); elementType = builder.getIntegerType(64);
tensorType = mlir::RankedTensorType::get(tensorDims, elementType);
constantDenseAttribute = mlir::DenseElementsAttr::get(tensorType, array);
break; break;
} }
} }
// Create empty sparse_value attribute. // Create ConstantOp for dense array.
llvm::ArrayRef<int64_t> array;
auto sparseValueAttribute = builder.getI64ArrayAttr(array);
// Create value attribute.
llvm::ArrayRef<int64_t> tensorDims(initializer.dims().data(),
initializer.dims().size());
mlir::Type tensorType =
mlir::RankedTensorType::get(tensorDims, elementType);
return builder.create<mlir::ONNXConstantOp>( return builder.create<mlir::ONNXConstantOp>(
loc, tensorType, sparseValueAttribute, loc, tensorType, nullptr, constantDenseAttribute);
constantArrayAttribute);
} }
} // namespace onnf } // namespace onnf

View File

@ -274,8 +274,12 @@ private:
int expectedNumResults = -1) { int expectedNumResults = -1) {
std::vector<mlir::Value> inputs; std::vector<mlir::Value> inputs;
for (const auto &item : node.input()) for (const auto &item : node.input())
if (frontend_symbols_.ContainKey(legalize_name(item))) if (initializedTensors.ContainKey(legalize_name(item))) {
inputs.push_back(initializedTensors.EmitInitializerForInputTensor(
UnknownLoc(), builder_, legalize_name(item)));
} else if (frontend_symbols_.ContainKey(legalize_name(item))) {
inputs.push_back(frontend_symbols_.GetTensorByOnnxName(item)); inputs.push_back(frontend_symbols_.GetTensorByOnnxName(item));
}
buildOutputAndOperation<T>(node, inputs, expectedNumOperands, buildOutputAndOperation<T>(node, inputs, expectedNumOperands,
expectedNumResults); expectedNumResults);
@ -287,7 +291,7 @@ private:
for (int i = 0; i < node.input().size(); ++i) { for (int i = 0; i < node.input().size(); ++i) {
item = node.input()[i]; item = node.input()[i];
// For the second argument, check if there exists an initializer. // For the second argument, check if there exists an initializer.
if (i == 1 && initializedTensors.ContainKey(legalize_name(item))) { if (initializedTensors.ContainKey(legalize_name(item))) {
inputs.push_back( inputs.push_back(
initializedTensors.EmitInitializerForInputTensor( initializedTensors.EmitInitializerForInputTensor(
UnknownLoc(), builder_, legalize_name(item))); UnknownLoc(), builder_, legalize_name(item)));
@ -412,8 +416,9 @@ private:
// * maintain a list of the defined graph // * maintain a list of the defined graph
llvm::SmallVector<mlir::Type, 4> arg_types; llvm::SmallVector<mlir::Type, 4> arg_types;
// Import the input tensor types that are not constant. // Import the input tensor types that are not constant and not initialized.
for (const auto &input : graph.input()) for (const auto &input : graph.input())
if (!initializedTensors.ContainKey(legalize_name(input.name())))
arg_types.emplace_back(ImportInputTensorType(input)); arg_types.emplace_back(ImportInputTensorType(input));
// Create the main function. // Create the main function.
@ -438,8 +443,9 @@ private:
// Map graph inputs to entry block arguments. // Map graph inputs to entry block arguments.
for (int i = 0; i < graph.input().size(); ++i) for (int i = 0; i < graph.input().size(); ++i)
ImportInputTensorSymbol( if (!initializedTensors.ContainKey(
graph.input()[i], entryBlock.getArguments()[i]); legalize_name(graph.input()[i].name())))
ImportInputTensorSymbol(graph.input()[i], entryBlock.getArguments()[i]);
// Create a NoneTyped constant to be used for optional operation inputs // Create a NoneTyped constant to be used for optional operation inputs
// which are not used. // which are not used.

View File

@ -876,12 +876,18 @@ void ONNXReshapeOp::inferShapes() {
SmallVector<int64_t, 2> dims(outputRank, -1); SmallVector<int64_t, 2> dims(outputRank, -1);
if (constantOp) { if (constantOp) {
// Cast attribute to ArrayAttr. DenseElementsAttr valueAttribute =
ArrayAttr valueAttribute = constantOp.valueAttr().dyn_cast<ArrayAttr>(); constantOp.valueAttr().dyn_cast<DenseElementsAttr>();
if (!valueAttribute)
emitError("ArrayAttr expected");
if (ArrayAttrSize(valueAttribute) != outputRank) if (!valueAttribute)
emitError("DenseElementsAttr expected");
// Get dims from valueAttribute.
auto valueIt = valueAttribute.getValues<IntegerAttr>().begin();
for (int i=0; i<outputRank; ++i)
dims[i] = (*valueIt++).cast<IntegerAttr>().getInt();
if (valueIt != valueAttribute.getValues<IntegerAttr>().end())
emitError("Constant value must have same rank as output"); emitError("Constant value must have same rank as output");
int64_t numberOfDynamicInputs = 0; int64_t numberOfDynamicInputs = 0;
@ -889,7 +895,6 @@ void ONNXReshapeOp::inferShapes() {
int64_t dynamicValueIndex = -1; int64_t dynamicValueIndex = -1;
for (int i=0; i<outputRank; ++i) { for (int i=0; i<outputRank; ++i) {
// Set output dimension. // Set output dimension.
dims[i] = ArrayAttrIntVal(valueAttribute, i);
if (dims[i] == 0) if (dims[i] == 0)
dims[i] = inputTensorTy.getShape()[i]; dims[i] = inputTensorTy.getShape()[i];

View File

@ -435,7 +435,7 @@ func @test_reshape_dynamic(%arg0 : tensor<5x5x1x32xf32>, %arg1 : tensor<4xi32>)
} }
func @test_reshape_1(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> { func @test_reshape_1(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> {
%0 = "onnx.Constant"() {sparse_value = [], value = [5, 5, 16, 2] } : () -> tensor<4xi32> %0 = "onnx.Constant"() {value = dense<[5, 5, 16, 2]> : tensor<4xi32> } : () -> tensor<4xi32>
%1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<4xi32>) -> tensor<*xf32> %1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<4xi32>) -> tensor<*xf32>
"std.return"(%1) : (tensor<*xf32>) -> () "std.return"(%1) : (tensor<*xf32>) -> ()
@ -445,7 +445,7 @@ func @test_reshape_1(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> {
} }
func @test_reshape_2(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> { func @test_reshape_2(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> {
%0 = "onnx.Constant"() {sparse_value = [], value = [-1, 16, 2] } : () -> tensor<3xi32> %0 = "onnx.Constant"() {value = dense<[-1, 16, 2]> : tensor<3xi32> } : () -> tensor<3xi32>
%1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<3xi32>) -> tensor<*xf32> %1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<3xi32>) -> tensor<*xf32>
"std.return"(%1) : (tensor<*xf32>) -> () "std.return"(%1) : (tensor<*xf32>) -> ()
@ -455,7 +455,7 @@ func @test_reshape_2(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> {
} }
func @test_reshape_3(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> { func @test_reshape_3(%arg0 : tensor<5x5x1x32xf32>) -> tensor<*xf32> {
%0 = "onnx.Constant"() {sparse_value = [], value = [-1, 0, 2] } : () -> tensor<3xi32> %0 = "onnx.Constant"() {value = dense<[-1, 0, 2]> : tensor<3xi32> } : () -> tensor<3xi32>
%1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<3xi32>) -> tensor<*xf32> %1 = "onnx.Reshape"(%arg0, %0) : (tensor<5x5x1x32xf32>, tensor<3xi32>) -> tensor<*xf32>
"std.return"(%1) : (tensor<*xf32>) -> () "std.return"(%1) : (tensor<*xf32>) -> ()