Skip to content

[PR] Shape Inference for Fused Nodes #7006

Description

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

feature requestrequest for unsupported feature or enhancement

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions