Is your feature request related to a problem? Please describe.
Currently ORT does not set any shape inference function for fused nodes. That is, we see in the createSchema function:
static std::unique_ptr<ONNX_NAMESPACE::OpSchema> CreateSchema(const Graph& graph,
const IndexedSubGraph& nodes_to_fuse) {
const auto* meta_def = nodes_to_fuse.GetMetaDef();
auto op_schema = onnxruntime::make_unique<ONNX_NAMESPACE::OpSchema>();
op_schema->SetName(meta_def->name);
op_schema->SetDomain(meta_def->domain);
op_schema->SetDoc(meta_def->doc_string);
op_schema->SinceVersion(meta_def->since_version);
int i = 0;
for (auto& input : meta_def->inputs) {
auto input_arg = graph.GetNodeArg(input);
// inputs must have a type. can be inferred for outputs.
ORT_ENFORCE(input_arg->Type() != nullptr);
op_schema->Input(i, input, "", *input_arg->Type());
++i;
}
i = 0;
for (auto& output : meta_def->outputs) {
auto output_arg = graph.GetNodeArg(output);
op_schema->Output(i, output, "", *output_arg->Type());
++i;
}
op_schema->Finalize();
return op_schema;
}
that because TypeAndShapeInferenceFunction is not explicitly set, it falls back to the default. While this doesn't cause an issue for inference, it prevents the allocator from reusing buffers since it has less information to work with. Instead for these fused nodes I think it would be better to define a shape inference function that is the composition of the inference functions for the nodes of the subgraph to be fused. For instance, consider a simple example of fusing a Conv + Relu node. The shape inference for this fused subgraph would run shape inference for Conv, take the resulting output TensorShape, and feed that as input to shape inference for Relu.
Implementing this might be a little bit involved because ONNX seems to require all shape inference to be mediated by an InferenceContext. That is, one cannot directly pass in input TensorShapeProtos to the shape inference function and get an output TensorShapeProto. Thus to implement, I suppose you'll have to subclass InferenceContext so that we have direct access to the TensorShapeProtos. Then the fused shape inference function can be defined by simulating the inference via our subclassed InferenceContext.
At the very least, an option should be exposed to the user to manually define a shape inference function in the meta_def which will be applied to the op_schema created for the fused node.
EDIT: I submitted a PR (#7007) to at least allow a custom shape inference function to be set. And now that I think about it more, letting the fused inference function be the composition of the individual nodes' inference functions only works if all attributes from each node are present for the fused node – so we'd want to allow the inference function to be manually set anyway.
Is your feature request related to a problem? Please describe.
Currently ORT does not set any shape inference function for fused nodes. That is, we see in the
createSchemafunction:that because
TypeAndShapeInferenceFunctionis not explicitly set, it falls back to the default. While this doesn't cause an issue for inference, it prevents the allocator from reusing buffers since it has less information to work with. Instead for these fused nodes I think it would be better to define a shape inference function that is the composition of the inference functions for the nodes of the subgraph to be fused. For instance, consider a simple example of fusing a Conv + Relu node. The shape inference for this fused subgraph would run shape inference for Conv, take the resulting output TensorShape, and feed that as input to shape inference for Relu.Implementing this might be a little bit involved because ONNX seems to require all shape inference to be mediated by an
InferenceContext. That is, one cannot directly pass in inputTensorShapeProtosto the shape inference function and get an outputTensorShapeProto. Thus to implement, I suppose you'll have to subclassInferenceContextso that we have direct access to theTensorShapeProtos. Then the fused shape inference function can be defined by simulating the inference via our subclassedInferenceContext.At the very least, an option should be exposed to the user to manually define a shape inference function in the
meta_defwhich will be applied to the op_schema created for the fused node.EDIT: I submitted a PR (#7007) to at least allow a custom shape inference function to be set. And now that I think about it more, letting the fused inference function be the composition of the individual nodes' inference functions only works if all attributes from each node are present for the fused node – so we'd want to allow the inference function to be manually set anyway.