-
Notifications
You must be signed in to change notification settings - Fork 66
Add New Metadata and Pattern Features #2271
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add New Metadata and Pattern Features #2271
Conversation
import onnx | ||
|
||
from onnxscript import ir | ||
from onnxscript import rewriter |
Check notice
Code scanning / CodeQL
Unused import Note
#else: | ||
# vp_outputs = builder.__getattr__(node.op_type)(*ninputs) |
Check notice
Code scanning / CodeQL
Commented-out code Note
|
||
return ReplacementPatternGraph(g) | ||
|
||
def get_iterator_index(self): |
Check notice
Code scanning / CodeQL
Explicit returns mixed with implicit (fall through) returns Note
# Skip the (all) Activation inputs (have been swapped to beginning of the list) | ||
for index in range(activations, len(nodes[0].inputs)): | ||
inputs = [] | ||
producers = [] |
Check notice
Code scanning / CodeQL
Unused local variable Note
cinput = LoopBody.function.inputs[index] | ||
noutput = vdisconnect(copy.copy(cinput)) | ||
noutput._uses = {} | ||
update_node_outputs = False |
Check notice
Code scanning / CodeQL
Unused local variable Note
inputs.add(ninput) | ||
elif any(ninput is init for init in node.graph.initializers): | ||
initializers.add(ninput) | ||
elif ninput.producer() == None: |
Check notice
Code scanning / CodeQL
Testing equality to None Note
@@ -0,0 +1,190 @@ | |||
import pytest |
Check notice
Code scanning / CodeQL
Unused import Note test
import ast | ||
|
||
import onnx | ||
from onnxscript import script |
Check notice
Code scanning / CodeQL
Unused import Note test
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed unused import
# for rule in tracer.best_matches_map: | ||
# matches = tracer.best_matches_map[rule] | ||
# for match in matches: | ||
# print(f'Reason: {match.match_result.reason}') | ||
# print(f'root_node: {match.root_node}') | ||
# pdb.set_trace() |
Check notice
Code scanning / CodeQL
Commented-out code Note test
# for node in ir.traversal.RecursiveGraphIterator(mypipeline_model.graph): | ||
# if node.domain == '': | ||
# print(node) |
Check notice
Code scanning / CodeQL
Commented-out code Note test
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2271 +/- ##
==========================================
- Coverage 70.16% 61.98% -8.18%
==========================================
Files 198 201 +3
Lines 24846 25456 +610
Branches 2670 2779 +109
==========================================
- Hits 17432 15779 -1653
- Misses 6496 8824 +2328
+ Partials 918 853 -65 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lintrunner found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
else: | ||
return self.class_metadata[depth] | ||
|
||
class PytorchHierarchyNode: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is useful! Let me see how we can provide the functionality to users.
def append_output_to_node(node, output): | ||
output._producer = node | ||
output._index = node.outputs[-1]._index + 1 | ||
node._outputs = (*node._outputs, output) | ||
node._num_outputs = len(node._outputs) | ||
|
||
def prepend_output_to_node(node, output): | ||
output._producer = node | ||
output._index = 0 | ||
for outp in node._outputs: | ||
outp._index += 1 | ||
node._outputs = (output, *node._outputs) | ||
node._num_outputs = len(node._outputs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add this to node so there is no need to modify internal states
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In fact we recommend creating new nodes if you want to update inputs and outputs. This way invariance of the graph is maintained. You may consider accumulating the inputs and outputs into two lists before constructing the node.
Ident = ir.Node(domain='', | ||
op_type='Identity', | ||
inputs = [cinput], | ||
outputs = [noutput], | ||
num_outputs =1) | ||
LoopBody.function.append(Ident) | ||
|
||
#Add Output to Function Call Nodes | ||
for i,node in enumerate(nodes): | ||
output_copy = copy.copy(noutput) | ||
|
||
#preserve single_assignment | ||
output_copy.name += f'_{i}' | ||
append_output_to_node(node,output_copy) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to collect all outputs before constructing the node?
vmap[input] = ValuePattern(input.name) | ||
|
||
for init in graph.initializers: | ||
vmap[init] = ValuePattern(init.name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like you want to map constants and initializers to unconstrained variables in the pattern? I wonder if it would make sense to map them to "Constants" in the pattern that require a matching contstant-value in the graph for a successful match? That makes reasonable, at least for simple and small constants. If it should be abstracted, wouldn't it be better for the user themselves to do that explicitly by mapping them to graph inputs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Thanks for this suggestion. I think we should do this. This would provide a good level of control for the user.
ninputs.append(vmap[ninput]) | ||
|
||
#if len(node.outputs) > 1: | ||
vp_outputs = builder.__getattr__(node.op_type)(*ninputs,_domain=node.domain, _outputs=len(node.outputs)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, the attributes of the node are abstracted away, and not matched?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. We ought to match the attributes. I'll make these changes.
node._outputs = (output, *node._outputs) | ||
node._num_outputs = len(node._outputs) | ||
|
||
def prepend_input_to_node(node, input): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modifying private fields is not recommended. I would consider initializing a new node
golden_results = ort_run_graph(args.filename, input_dict, outputs[0].name) | ||
|
||
|
||
LoopBody = LoopBodyTemplate(args.patternfilename) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LoopBody = LoopBodyTemplate(args.patternfilename) | |
loop_body = LoopBodyTemplate(args.patternfilename) |
note: always use snake_case for variable names
return [output, used_output] | ||
|
||
|
||
def bGraphView(name, nodes): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: snake case for function names. Is this build_graph_view
?
usage.add("EXTERNAL") | ||
return usage | ||
|
||
def find_subgraph_inputs(nodes): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function is useful. I wonder if we should put it in ir.convenience https://github.com/onnx/ir-py/blob/main/src/onnx_ir/_convenience/__init__.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As well as the one below for outputs and bGraphView
This PR will add new metadata and pattern features.