-
Notifications
You must be signed in to change notification settings - Fork 173
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
Conversation
dda12a2
to
9f59f9d
Compare
@@ -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) |
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 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 |
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 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
}
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.
Nice find, I am glad you looked into this because this conflict would be pretty annoying
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. Also, we may need to rename the names in fetch_list in case that these memory-shared variables are fetched.
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.
The new update has considered the rename of graph 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.
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. |
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.
Thanks for fixing my horrible English haha I realized this after I had pushed it.
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.
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): |
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.
Great function! Great documentation.
fluid/utils.py
Outdated
return self.inputs, self.attrs, self.outputs | ||
|
||
|
||
get_op_io_info = UniqOpIOs() |
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 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
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.
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): |
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.
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'] |
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.
Very nice
fluid/utils.py
Outdated
|
||
return inputs, attrs, outputs | ||
class UniqOpIOs(): | ||
"""Return input/output information for an operator, and resolve potential |
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.
Nice find, I am glad you looked into this because this conflict would be pretty annoying
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.
Thanks!
fluid/utils.py
Outdated
return self.inputs, self.attrs, self.outputs | ||
|
||
|
||
get_op_io_info = UniqOpIOs() |
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.
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 |
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. 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. |
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.
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, |
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.
See here
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.
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
)?
@sidgoyal78 Thanks for the review. Yes, when loading parameters, we need |
update run all cases script
Resolve #31, see the validation results in #32
Resolve #34, please also review #33