Skip to content
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

Enhance batch_norm_op & rename output args sharing names with inputs #30

Merged
merged 10 commits into from
Apr 26, 2018

Conversation

kuke
Copy link

@kuke kuke commented Apr 24, 2018

Resolve #31, see the validation results in #32
Resolve #34, please also review #33

@@ -84,7 +84,7 @@ def convert(args):
# TODO(kuke): deal with the corner case that vars in
# different blocks have the same name
node_proto = ops.node_maker[op.type](operator=op,
scope=inference_scope)
block=block)
Copy link
Author

Choose a reason for hiding this comment

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

In batch_norm_op, we need to know the shape of input data, which is non-persistable, so here block is needed.

fluid/utils.py Outdated

return inputs, attrs, outputs
class UniqOpIOs():
"""Return input/output information for an operator, and resolve potential
Copy link
Author

@kuke kuke Apr 24, 2018

Choose a reason for hiding this comment

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

In Fluid Program, inputs and outputs may share the same name to optimize memory utility. Changes here are going to solve this problem. E.g., relu_op in ResNet50

  ops {
    inputs {
      parameter: "X"
      arguments: "batch_norm_33.tmp_2"
    }
    outputs {
      parameter: "Out"
      arguments: "batch_norm_33.tmp_2"
    }
    type: "relu"
    attrs {
      name: "use_mkldnn"
      type: BOOLEAN
      b: false
    }
    is_target: false
  }

Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice find, I am glad you looked into this because this conflict would be pretty annoying

Copy link
Author

Choose a reason for hiding this comment

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

Yes. Also, we may need to rename the names in fetch_list in case that these memory-shared variables are fetched.

Copy link
Author

Choose a reason for hiding this comment

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

The new update has considered the rename of graph outputs.

Copy link
Collaborator

@varunarora varunarora left a comment

Choose a reason for hiding this comment

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

Great stuff @kuke!

# is unnecessary.
# and not provided in the list of inputs, we move on to the next
# expected input. If not, we make sure it the expected input is
# provided, or that it is unnecessary.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for fixing my horrible English haha I realized this after I had pushed it.

Copy link
Author

Choose a reason for hiding this comment

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

Aha. Your comments are great, just have minor typos :-)

@@ -113,6 +114,27 @@ def create_var(block, name, np_list, var_proto):
return var_dict


def create_tensor(np_value, place):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Great function! Great documentation.

fluid/utils.py Outdated
return self.inputs, self.attrs, self.outputs


get_op_io_info = UniqOpIOs()
Copy link
Collaborator

Choose a reason for hiding this comment

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

So is this a object initialized for the entire program? Slightly uncommon pattern to do an initializer this way. Did you do it because you didn't want to change the get_op_io_info calls everywhere? I think it might be a good idea to initialize a class object to make these calls in place of this pattern

Copy link
Author

Choose a reason for hiding this comment

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

Oh. Initialize get_op_io_info in this way mainly because we have a variable self._all_renamed_outputs here to store all the renamed outputs in the program, and the class UniqOpIOs can only be initialized once. Of course, we can make the variable static:

class UniqOpIOs():
    _all_renamed_outputs = {}
    
    def __init__():
        ...
    def __call__():
        ...

And get_op_io_info will be initialized like that:

get_op_io_info = UniqOpIOs()
inputs, attrs, outputs = get_op_io_info(op)

One more line code will be inserted whenever get_op_io_info is used. What do you think?

fluid/utils.py Outdated
self._all_renamed_outputs = {}
self._renamed_cnt = 0

def get_new_name(self, arg):
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nicely done!

x_shape = block.vars[inputs['X'][0]].shape
reshape_node = None
if len(x_shape) == 2:
reshaped_x = [inputs['X'][0] + '@reshape_0']
Copy link
Collaborator

Choose a reason for hiding this comment

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

Very nice

fluid/utils.py Outdated

return inputs, attrs, outputs
class UniqOpIOs():
"""Return input/output information for an operator, and resolve potential
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice find, I am glad you looked into this because this conflict would be pretty annoying

Copy link
Author

@kuke kuke left a comment

Choose a reason for hiding this comment

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

Thanks!

fluid/utils.py Outdated
return self.inputs, self.attrs, self.outputs


get_op_io_info = UniqOpIOs()
Copy link
Author

Choose a reason for hiding this comment

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

Oh. Initialize get_op_io_info in this way mainly because we have a variable self._all_renamed_outputs here to store all the renamed outputs in the program, and the class UniqOpIOs can only be initialized once. Of course, we can make the variable static:

class UniqOpIOs():
    _all_renamed_outputs = {}
    
    def __init__():
        ...
    def __call__():
        ...

And get_op_io_info will be initialized like that:

get_op_io_info = UniqOpIOs()
inputs, attrs, outputs = get_op_io_info(op)

One more line code will be inserted whenever get_op_io_info is used. What do you think?

fluid/utils.py Outdated

return inputs, attrs, outputs
class UniqOpIOs():
"""Return input/output information for an operator, and resolve potential
Copy link
Author

Choose a reason for hiding this comment

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

Yes. Also, we may need to rename the names in fetch_list in case that these memory-shared variables are fetched.

# is unnecessary.
# and not provided in the list of inputs, we move on to the next
# expected input. If not, we make sure it the expected input is
# provided, or that it is unnecessary.
Copy link
Author

Choose a reason for hiding this comment

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

Aha. Your comments are great, just have minor typos :-)

@@ -577,8 +623,9 @@ def xor_op():
# Need to continue the mapping below.
'': 'ConvTranspose',
'': 'DepthToSpace',
'depthwise_conv2d': conv2d_op,
Copy link
Author

Choose a reason for hiding this comment

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

See here

Copy link
Collaborator

@sidgoyal78 sidgoyal78 left a comment

Choose a reason for hiding this comment

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

I think this looks pretty good. Thanks for the PR
Do you think there will be a case where we will actually be needing scope (in addition to block)?

@kuke
Copy link
Author

kuke commented Apr 26, 2018

@sidgoyal78 Thanks for the review. Yes, when loading parameters, we need scope to fetch the value of each tensor. But in the conversion of operators, we just need to know the static information of vars, inputs and outputs, so block is enough.

@kuke kuke merged commit 486b871 into PaddlePaddle:develop Apr 26, 2018
Zeref996 pushed a commit to Zeref996/Paddle2ONNX that referenced this pull request Aug 24, 2021
update run all cases script
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants