blob: 6e07d5ff18f030c51cac94951047e38e97e2dfa8 [file] [log] [blame]
#include <c10/test/util/Macros.h>
#include <gtest/gtest.h>
#include "caffe2/core/common.h"
#include "caffe2/core/logging.h"
#include "caffe2/opt/bound_shape_inferencer.h"
#include "caffe2/utils/proto_utils.h"
using namespace caffe2;
namespace {
ShapeInfo makeTensorInfo(
const std::vector<TensorBoundShape::DimType>& t,
const std::vector<int64_t>& dims,
TensorProto::DataType dtype = TensorProto_DataType_FLOAT,
bool quantized = false) {
ShapeInfo info;
info.setDimType(t);
TensorShape& shape = info.shape;
for (const auto d : dims) {
shape.add_dims(d);
}
shape.set_data_type(dtype);
if (quantized) {
info.is_quantized = true;
info.q_info.scale.clear();
info.q_info.scale.push_back(1);
info.q_info.offset.clear();
info.q_info.offset.push_back(0);
info.q_info.axis = 1;
}
return info;
}
void verifyShapeInfo(
const ShapeInfoMap& info,
const std::string& name,
const std::vector<TensorBoundShape::DimType>& t,
const std::vector<int64_t>& dims,
TensorProto::DataType dtype = TensorProto_DataType_FLOAT,
bool quantized = false) {
LOG(INFO) << "Checking " << name;
const auto it = info.find(name);
ASSERT_TRUE(it != info.end());
const auto& shape_info = it->second;
EXPECT_EQ(shape_info.getDimType(), t);
const auto& shape = shape_info.shape;
ASSERT_EQ(shape.dims_size(), dims.size());
for (unsigned i = 0; i < dims.size(); ++i) {
EXPECT_EQ(dims[i], shape.dims(i));
}
EXPECT_EQ(shape.data_type(), dtype);
EXPECT_EQ(shape_info.is_quantized, quantized);
}
} // namespace
TEST(BoundShapeInference, SparseLengthsSum) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSum", "", {"Weights", "Data", "Lengths"}, {"Out"}, {}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Weights",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1000, 16}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Weights",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{1000, 16});
verifyShapeInfo(
out_shape,
"Data",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT64);
verifyShapeInfo(
out_shape,
"Lengths",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
}
TEST(BoundShapeInference, SparseLengthsSumSparseLookup) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSumSparseLookup",
"",
{"Indices", "Lengths", "Remapping", "Weights"},
{"IndicesOut", "LengthsOut", "WeightsOut"},
{}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Remapping",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT},
{1000},
TensorProto_DataType_INT32));
BoundShapeSpec spec(20, 1000);
shape_map.emplace(
"Indices",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT32));
shape_map.emplace(
"Weights",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_FLOAT));
shape_map.emplace(
"Lengths",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"WeightsOut",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_FLOAT);
verifyShapeInfo(
out_shape,
"IndicesOut",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"LengthsOut",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
}
TEST(BoundShapeInference, SparseLengthsSumFused8BitRowwise) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSumFused8BitRowwise",
"",
{"Weights", "Data", "Lengths"},
{"Out"},
{}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Weights",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1000, 58},
TensorProto_DataType_INT8));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Weights",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{1000, 58},
TensorProto_DataType_INT8);
verifyShapeInfo(
out_shape,
"Data",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT64);
verifyShapeInfo(
out_shape,
"Lengths",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
}
TEST(BoundShapeInference, SparseLengthsSum8BitRowwiseSparse) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSum8BitRowwiseSparse",
"",
{"Weights", "Data", "Lengths", "Mapping"},
{"Out"},
{}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Weights",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1000, 58},
TensorProto_DataType_INT8));
shape_map.emplace(
"Mapping",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT},
{2000},
TensorProto_DataType_INT32));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Weights",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{1000, 58},
TensorProto_DataType_INT8);
verifyShapeInfo(
out_shape,
"Mapping",
{TensorBoundShape_DimType_CONSTANT},
{2000},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Data",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT64);
verifyShapeInfo(
out_shape,
"Lengths",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
}
TEST(BoundShapeInference, SparseLengthsSumFused4BitRowwise) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSumFused4BitRowwise",
"",
{"Weights", "Data", "Lengths"},
{"Out"},
{}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Weights",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1000, 54},
TensorProto_DataType_INT8));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Weights",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{1000, 54},
TensorProto_DataType_INT8);
verifyShapeInfo(
out_shape,
"Data",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT64);
verifyShapeInfo(
out_shape,
"Lengths",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 100});
}
TEST(BoundShapeInference, LengthsRangeFill) {
NetDef net;
net.add_op()->CopyFrom(
CreateOperatorDef("LengthsRangeFill", "", {"X"}, {"Y"}, {}));
net.add_op()->CopyFrom(CreateOperatorDef("Copy", "", {"Y"}, {"Z"}, {}));
ShapeInfoMap shape_map;
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"X",
{TensorBoundShape_DimType_BATCH},
{spec.max_batch_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Y",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT32);
verifyShapeInfo(
out_shape,
"Z",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX_DEFAULT},
{spec.max_batch_size * spec.max_seq_size},
TensorProto_DataType_INT32);
}
TEST(BoundShapeInference, ConstantFill) {
NetDef net;
net.add_op()->CopyFrom(
CreateOperatorDef("ConstantFill", "", {"X"}, {"Y"}, {}));
ShapeInfoMap shape_map;
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
shape_map.emplace(
"X",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH,
TensorBoundShape_DimType_CONSTANT},
{20, 1024}));
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Y",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{20, 1024},
TensorProto_DataType_FLOAT);
}
// https://github.com/pytorch/pytorch/issues/40861
TEST(BoundShapeInference, DISABLED_ON_WINDOWS(Reshape)) {
NetDef net;
std::vector<int> new_shape{-1, 8};
std::vector<int> new_shape2{2, 8};
net.add_op()->CopyFrom(
CreateOperatorDef("FC", "", {"X0", "W0", "B0"}, {"X1"}, {}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Reshape",
"",
{"X1"},
{"Y1", "old_shape"},
{MakeArgument<std::vector<int>>("shape", new_shape)}));
// Cannot infer shape for this one because input/output shape doesn't match
net.add_op()->CopyFrom(CreateOperatorDef(
"Reshape",
"",
{"X1"},
{"Y2", "old_shape2"},
{MakeArgument<std::vector<int>>("shape", new_shape2)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"W0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 1024}));
shape_map.emplace(
"B0", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {16}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"X0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 1024});
verifyShapeInfo(
out_shape,
"X1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
verifyShapeInfo(
out_shape,
"Y1",
{TensorBoundShape_DimType_BATCH,
TensorBoundShape_DimType_CONSTANT}, // TODO
{spec.max_batch_size * 16 / 8, 8});
EXPECT_TRUE(out_shape.find("Y2") == out_shape.end());
}
TEST(BoundShapeInference, ConcatMissingInput) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Concat",
"",
{"I0", "I1"},
{"Cout", "split_info"},
{MakeArgument<int>("axis", 1), MakeArgument<int>("add_axis", 1)}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"I0",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"I0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"Cout",
{TensorBoundShape_DimType_BATCH,
TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 2, 60});
}
#ifdef USE_PYTORCH_QNNPACK
// See https://github.com/pytorch/pytorch/issues/35544
TEST(
BoundShapeInference,
DISABLED_ON_WINDOWS(Int8QuantizeInferInputBackwards)) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Int8Quantize",
"",
{"I0"},
{"Cout", "split_info"},
{MakeArgument<int>("Y_zero_point", 0),
MakeArgument<float>("Y_scale", 0.05)}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Int8FC",
"",
{"Cout", "W0", "B0"},
{"Y"},
{MakeArgument<int>("Y_zero_point", 0),
MakeArgument<float>("Y_scale", 0.05)}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"W0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 101},
TensorProto_DataType_INT8,
true));
shape_map.emplace(
"B0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT},
{16},
TensorProto_DataType_INT32,
true));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"I0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 101});
verifyShapeInfo(
out_shape,
"Cout",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 101},
TensorProto_DataType_UINT8,
true);
verifyShapeInfo(
out_shape,
"Y",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16},
TensorProto_DataType_UINT8,
true);
}
#endif /* USE_PYTORCH_QNNPACK */
TEST(BoundShapeInference, ConcatInferInputBackwards) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Concat",
"",
{"I0", "I1"},
{"Cout", "split_info"},
{MakeArgument<int>("axis", 1)}));
net.add_op()->CopyFrom(
CreateOperatorDef("FCTransposed", "", {"Cout", "W0", "B0"}, {"Y"}, {}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"I0",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60}));
shape_map.emplace(
"W0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{101, 16}));
shape_map.emplace(
"B0", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {16}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"I0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"Cout",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 101});
verifyShapeInfo(
out_shape,
"Y",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
verifyShapeInfo(
out_shape,
"I1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 101 - 60});
}
TEST(BoundShapeInference, ElementwiseInferInputBackwards) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Mul", "", {"I0", "I1"}, {"Out"}, {MakeArgument<int>("broadcast", 1)}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Add",
"",
{"I00", "I11"},
{"Outt"},
{MakeArgument<int>("broadcast", 1)}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"Out",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60}));
shape_map.emplace(
"Outt",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"I0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"I1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"I00",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
verifyShapeInfo(
out_shape,
"I11",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
}
TEST(BoundShapeInference, ElementwiseOp) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Mul", "", {"I0", "I1"}, {"Out"}, {MakeArgument<int>("broadcast", 1)}));
net.add_op()->CopyFrom(CreateOperatorDef("Mul", "", {"I3", "I4"}, {"Out3"}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Add",
"",
{"I00", "I11"},
{"Outt"},
{MakeArgument<int>("broadcast", 1)}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"I0",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60}));
shape_map.emplace(
"I00",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50}));
shape_map.emplace(
"I3",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 40}));
shape_map.emplace(
"I4",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 40}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"I1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60});
verifyShapeInfo(
out_shape,
"I11",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
verifyShapeInfo(
out_shape,
"Outt",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 50});
verifyShapeInfo(
out_shape,
"Out3",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 40});
}
TEST(BoundShapeInference, Bucketize) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Bucketize",
"",
{"In"},
{"Out"},
{MakeArgument<std::vector<float>>("boundaries", {1.0, 2.0})}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"In",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Out",
{TensorBoundShape_DimType_BATCH_OF_FEATURE_MAX, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 60},
TensorProto_DataType_INT32);
}
TEST(BoundShapeInference, Split) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Split", "", {"X"}, {"Y0", "Y1"}, {MakeArgument<int>("axis", 1)}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Split",
"",
{"X"},
{"Y2", "Y3", "Y4"},
{MakeArgument<int>("axis", 1),
MakeArgument<std::vector<int>>("split", {4, 30, 14})}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Split",
"",
{"X1"},
{"Y5", "Y6"},
{MakeArgument<int>("axis", 1), MakeArgument<int>("add_axis", 1)}));
BoundShapeSpec spec(20, 1000);
ShapeInfoMap shape_map;
shape_map.emplace(
"X",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48}));
shape_map.emplace(
"X1",
makeTensorInfo(
{TensorBoundShape_DimType_BATCH,
TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 2, 48}));
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"X",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48});
verifyShapeInfo(
out_shape,
"X1",
{TensorBoundShape_DimType_BATCH,
TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 2, 48});
verifyShapeInfo(
out_shape,
"Y0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48 / 2});
verifyShapeInfo(
out_shape,
"Y1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48 / 2});
verifyShapeInfo(
out_shape,
"Y2",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 4});
verifyShapeInfo(
out_shape,
"Y3",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 30});
verifyShapeInfo(
out_shape,
"Y4",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 14});
verifyShapeInfo(
out_shape,
"Y5",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48});
verifyShapeInfo(
out_shape,
"Y6",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 48});
}
#ifdef USE_PYTORCH_QNNPACK
// https://github.com/pytorch/pytorch/issues/41471
TEST(BoundShapeInference, DISABLED_ON_WINDOWS(FC)) {
NetDef net;
net.add_op()->CopyFrom(
CreateOperatorDef("FC", "", {"X0", "W0", "B0"}, {"Out0"}, {}));
net.add_op()->CopyFrom(
CreateOperatorDef("FCTransposed", "", {"X1", "W1", "B1"}, {"Out1"}, {}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Int8FC", "", {"X2", "W2", "B2", "quant_param"}, {"Out2"}, {}));
ShapeInfoMap shape_map;
shape_map.emplace(
"W0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 1024}));
shape_map.emplace(
"B0", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {16}));
shape_map.emplace(
"W1",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 1024}));
shape_map.emplace(
"B1", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {1024}));
shape_map.emplace(
"W2",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 1024}));
shape_map.emplace(
"B2", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {16}));
shape_map.emplace(
"quant_param", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {1}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"X0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 1024});
verifyShapeInfo(
out_shape,
"Out0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
verifyShapeInfo(
out_shape,
"X1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
verifyShapeInfo(
out_shape,
"Out1",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 1024});
verifyShapeInfo(
out_shape,
"X2",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 1024},
TensorProto_DataType_UINT8,
true);
verifyShapeInfo(
out_shape,
"Out2",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16},
TensorProto_DataType_UINT8,
true);
}
#endif /* USE_PYTORCH_QNNPACK */
TEST(BoundShapeInference, FC3D) {
NetDef net;
net.add_op()->CopyFrom(
CreateOperatorDef("FC", "", {"X0", "W0", "B0"}, {"Out0"}, {}));
ShapeInfoMap shape_map;
shape_map.emplace(
"W0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 1, 1024}));
shape_map.emplace(
"B0", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {16}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"X0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 1024});
verifyShapeInfo(
out_shape,
"Out0",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 16});
}
TEST(BoundShapeInference, Quantization) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"FloatToFused8BitRowwiseQuantized", "", {"w"}, {"Out_w"}, {}));
ShapeInfoMap shape_map;
shape_map.emplace(
"w",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{16, 64}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"Out_w",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{16, 72},
TensorProto_DataType_UINT8);
}
TEST(BoundShapeInference, Tile) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Tile",
"",
{"blob"},
{"blob_tile"},
{MakeArgument<int>("tiles", 32),
MakeArgument<int>("axis", 0),
MakeArgument<int>("dynamic", 1)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"blob",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"blob_tile",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{32, 16});
BoundShapeSpec spec2(8, 1000);
BoundShapeInferencer eng2(spec2);
eng2.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape2 = eng2.shape_info();
verifyShapeInfo(
out_shape2,
"blob_tile",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{8, 16});
}
TEST(BoundShapeInference, Combo0) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSum", "", {"Weights0", "Data0", "Lengths0"}, {"EB0"}, {}));
net.add_op()->CopyFrom(CreateOperatorDef(
"SparseLengthsSum", "", {"Weights1", "Data1", "Lengths1"}, {"EB1"}, {}));
net.add_op()->CopyFrom(CreateOperatorDef(
"Concat",
"",
{"EB0", "EB1"},
{"Cout", "split_info"},
{MakeArgument<int>("axis", 1), MakeArgument<int>("add_axis", 1)}));
net.add_op()->CopyFrom(CreateOperatorDef(
"BatchMatMul",
"",
{"Cout", "Cout"},
{"Bout"},
{MakeArgument<int>("trans_b", 1)}));
net.add_op()->CopyFrom(
CreateOperatorDef("Flatten", "", {"Bout"}, {"Fout"}, {}));
net.add_op()->CopyFrom(
CreateOperatorDef("BatchGather", "", {"Fout", "Indices"}, {"Gout"}, {}));
ShapeInfoMap shape_map;
shape_map.emplace(
"Weights0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1000, 16}));
shape_map.emplace(
"Weights1",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{20000, 16}));
shape_map.emplace(
"Indices", makeTensorInfo({TensorBoundShape_DimType_CONSTANT}, {2}));
BoundShapeSpec spec(20, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
LOG(INFO) << eng.PrintShapeInfo();
verifyShapeInfo(
out_shape,
"Gout",
{TensorBoundShape_DimType_BATCH, TensorBoundShape_DimType_CONSTANT},
{spec.max_batch_size, 2});
}
TEST(BoundShapeInference, Softmax) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Softmax",
"",
{"input"},
{"output"},
{MakeArgument<int>("axis", 1)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{1, 16});
}
TEST(BoundShapeInference, LpNorm) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"LpNorm",
"",
{"input"},
{"output"},
{MakeArgument<int>("p", 1)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT},
{1});
}
TEST(BoundShapeInference, Transpose) {
NetDef net;
std::vector<int> axes{1, 0};
net.add_op()->CopyFrom(CreateOperatorDef(
"Transpose",
"",
{"input"},
{"output"},
{MakeArgument<std::vector<int>>("axes", axes)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{1, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{16, 1});
}
TEST(BoundShapeInference, Clip) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Clip",
"",
{"input"},
{"output"},
{MakeArgument<int>("min", 10.0), MakeArgument<int>("max", 20.0)}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{8, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{8, 16});
}
TEST(BoundShapeInference, Mean) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Mean",
"",
{"input0", "input1", "input2"},
{"output"}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{8, 16}));
shape_map.emplace(
"input1",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{8, 16}));
shape_map.emplace(
"input2",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT,
TensorBoundShape_DimType_CONSTANT},
{8, 16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT, TensorBoundShape_DimType_CONSTANT},
{8, 16});
}
TEST(BoundShapeInference, Div) {
NetDef net;
net.add_op()->CopyFrom(CreateOperatorDef(
"Div",
"",
{"input0", "input1"},
{"output"}));
ShapeInfoMap shape_map;
shape_map.emplace(
"input0",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT},
{16}));
shape_map.emplace(
"input1",
makeTensorInfo(
{TensorBoundShape_DimType_CONSTANT},
{16}));
BoundShapeSpec spec(32, 1000);
BoundShapeInferencer eng(spec);
eng.InferBoundShapeAndType(net, shape_map, nullptr);
const auto& out_shape = eng.shape_info();
verifyShapeInfo(
out_shape,
"output",
{TensorBoundShape_DimType_CONSTANT},
{16});
}