Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

lib: update operator resolve #108

Merged
merged 10 commits into from
Mar 22, 2019
Merged

Conversation

fs-eire
Copy link
Contributor

@fs-eire fs-eire commented Mar 14, 2019

This change updates the behavior how to resolve a Graph.Node to an Operator in a session's initialization stage.

  • Change the IR version check to support IR version 4
  • Enable opset version check
  • Replace the switch-case based resolve to a data driven resolve
  • Allows opset version selector (currently support exact match and range match, eg. 7, 7+)

lib/backend.ts Outdated
@@ -32,10 +33,9 @@ export interface SessionHandler {
/**
* Resolves the operator from the name; backend specific
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think the comment would be - resolve the operator from the name and the opset version ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will fix

['Less', '', '7+', () => new binaryOps.WebGLBinaryOp(NUMBER_TYPES, binaryOps.glslLess(), undefined, 'bool')],
['Log', '', '6+', () => new unaryOps.WebGLUnaryOp(FLOAT_TYPES, unaryOps.glslLog())],
['MatMul', '', '1+', () => new WebGLMatMul()],
['MaxPool', '', '1-7', () => new WebGLMaxPool()], // TODO: support new attributes for MaxPool-8 and MaxPool-10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developer-centric question - I am guessing the way we support different versions of an op (where there is majority overlap across versions) is we just extend the current working class and override appropriate methods so as to align with the new spec ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are 2 ways.
one is to extend the existing implementation, if the new version is compatible with the old one according to the spec. (eg. add a new optional attribute, whose default value is the same of the old behavior)
one is to have different implementation, if the new version has a different behavior, or it is necessary to do so due to performance concern.

}

/**
* Domain of an opset, it can be an empty string(default value, represent for ai.onnx), or 'ai.onnx.ml'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the domain be ai.onnx OR default value (empty string) to represent the ai.onnx domain ?

Copy link
Contributor Author

@fs-eire fs-eire Mar 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

empty string means ai.onnx as in domain. the string 'ai.onnx' is not a valid value here

lib/opset.ts Outdated
}
}
}
throw new TypeError(`cannot resolve operator '${opType}'`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can error thrown also mention requested opset version of the operator cannot be resolved ?

['And', '', '7+', () => new CpuBinaryOp(['bool'], (e1, e2) => (e1 && e2))],
['ArgMax', '', '1+', () => new CpuArgMax()],
['Asin', '', '7+', () => new unaryOps.CpuUnaryOp(NUMBER_TYPES, unaryOps.asin)],
['Atan', '', '7+', () => new unaryOps.CpuUnaryOp(NUMBER_TYPES, unaryOps.atan)],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How were the ResolveRules created for the very first time? How can we make sure it is accurate? Do we need to maintain any script(s) used to generate them ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a pain point. one possible way is to grab more test cases from other place.

meanwhile, I am writing a script to generate the operator support table from data (to replace /docs/operators.md). that helps but still not a guarantee of 100% accuracy.

@hariharans29
Copy link
Member

At a high level, the changes look okay.

Looking at the build failures it looks to me that there might be issues concerning the array of ResolveRule that have been generated for each backend (or some bug in matchSelector() and/or resolveOperator() which I am sure can be ironed out). My only concern is the general accuracy of these set of ResolveRule for each backend.

@fs-eire
Copy link
Contributor Author

fs-eire commented Mar 20, 2019

At a high level, the changes look okay.
Looking at the build failures it looks to me that there might be issues concerning the array of ResolveRule that have been generated for each backend (or some bug in matchSelector() and/or resolveOperator() which I am sure can be ironed out). My only concern is the general accuracy of these set of ResolveRule for each backend.

I think the final solution is to make sure we have a good test coverage. Maybe we can leverage some test cases from onnxruntime.

['Atan', '', '7+', () => new unaryOps.CpuUnaryOp(NUMBER_TYPES, unaryOps.atan)],
['AveragePool', '', '7+', () => new CpuAveragePool()],
['BatchNormalization', '', '7+', () => new CpuBatchNormalization()],
['Ceil', '', '6+', () => new unaryOps.CpuUnaryOp(NUMBER_TYPES, unaryOps.ceil)],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, how can we ensure potentially a bad commit that could have conflicting operator resolves possible ?

For example, Ceil 6+ could be mapped to an op, let's say Ceil 10 has has a different op implementation, but the developer forgets to change 6+ to 6-9. In that case, multiple op resolves are possible.

One way is to run a script at check-in time but we will have to maintain that...

['Sqrt', '', '6+', () => new unaryOps.CpuUnaryOp(NUMBER_TYPES, unaryOps.sqrt)],
['Squeeze', '', '1+', () => new CpuSqueeze()],
['Sub', '', '7+', () => new CpuBinaryOp(NUMBER_TYPES, (e1, e2) => (e1 - e2))],
['Sum', '', '6+', () => new CpuSum()], // TODO: support multidirectional broadcast for Sum-8
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to throw exception when it looks like broadcasting support maybe required in the implementation (since it support 6+) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the exception is thrown anyway. currently it will be thrown due to checkInput failure. the only difference is the error message

@hariharans29
Copy link
Member

hariharans29 commented Mar 22, 2019

There are a couple of nits left out from being resolved/addressed-

  1. comment update in backend.ts
  2. update error message in opset.ts to indicate that the opset version of the operator cannot be resolved (as opposed to the generic - operator could not be resolved which might be misleading to anyone who looks at the code base and finds implementation for that operator (from an earlier opset))

@fs-eire fs-eire merged commit 563dbd6 into microsoft:master Mar 22, 2019
@fs-eire fs-eire deleted the operators-resolve branch March 22, 2019 21:09
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants