-
Notifications
You must be signed in to change notification settings - Fork 84
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
Loop operator #853
Loop operator #853
Conversation
…phX into inline_subgraph_try_removing_subgraph
… into inline_subgraph
…MIGraphX into inline_subgraph
… into loop_operator
…MIGraphX into inline_subgraph
… into loop_operator
… into inline_subgraph
… into loop_operator
… into loop_operator
… into loop_operator
src/include/migraphx/op/loop.hpp
Outdated
|
||
void append(const std::vector<argument>& iter_state, | ||
const std::vector<argument>& concatenated_outputs, | ||
const int iter) const |
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.
Dont make a value parameter const
.
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.
fixed
src/include/migraphx/run_loop.hpp
Outdated
module_ref&, const std::unordered_map<std::string, argument>&)>& run) | ||
{ | ||
auto get_output_index = [](const std::string& name) { | ||
std::string out_prefix = "#output_"; |
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 naming of output indices as #output_
is specific to the GPU backend. Other backends could name them differently. Why do you need to check for the output params? Maybe this should added to the loop_model, maybe a function like std::map<std::string, int> get_output_params(const module& m)
?
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.
moved this to the gpu implementation
src/include/migraphx/run_loop.hpp
Outdated
if(loc != std::string::npos) | ||
{ | ||
int index = std::stoi(name.substr(loc + out_prefix.size())); | ||
return index; |
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.
It says there is no coverage here. There are other places where there is no coverage in this file we should probably add unit tests for. I assume there is no coverage because output params are only used by the GPU backend. Perhaps, we can create mock loop_model and some fake output params to check with the unit tests.
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, this part of code only applied to the GPU implementation.
src/onnx/onnx_parser.cpp
Outdated
pmod_insts_bkup[ins_p.first] = instructions[ins_p.first]; | ||
} | ||
instructions[ins_p.first] = ins_p.second; | ||
} |
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.
What is this doing? Is this to handle parameter shadowing? I thought shadowing is not permitted by ONNX spec from Nodes:
The graph MUST use single static assignment for all node outputs, which means that all node output names MUST be unique within a graph. In the case of a nested subgraph, a node output name MUST be distinct from the names from the outer scopes that are visible in the nested subgraph.
Is that an incorrect interpretation? Do you see onnx models that are shadowing params and constants?
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 have another scenario that subgraph and parent graph have parameters with the same name. In this case, when we parse the subgraph, the instruction (stored in the mem var instructions
corresponding to the parameter in the subgraph will overwrite that of the parent graph. After parsing subgraph returns, if we do not restore the parameter of the parent graph and and the parent graph uses this parameter as input for some other operators, inputs of the operator are the parameter of the subgraph.
In this scenario, the name is not output of any node, so the above specification does not apply, and there is no specification saying parent graph and subgraph cannot use the same name as parameter names. The only thing I read from the notes is:
In nested subgraphs used as attribute values, users MUST NOT use the same name as both a subgraph initializer and subgraph input unless the corresponding op's specification explicitly allows it.
but this does not apply, either.
I got the example with the above scenario some time ago online, but I cannot find it anymore. Also, when I created the onnx file from the script, no error is reported.
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.
@pfultz2 Changed accordingly and added a unit test for the run loop. Could you please take a look again? Thanks
src/targets/gpu/device/fill.cpp
Outdated
namespace gpu { | ||
namespace device { | ||
|
||
void fill(hipStream_t stream, const argument& result, const unsigned long& val) |
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.
Pass val
by value.
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.
fixed
src/targets/gpu/lowering.cpp
Outdated
auto cpu_cond = | ||
mod->insert_instruction(ins, make_op("hip::copy_from_gpu"), inputs.at(1)); | ||
auto synced_max_iter = | ||
mod->insert_instruction(ins, make_op("hip::sync_stream"), cpu_max_iter); |
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.
Shouldn't this take both cpu_max_iter
and cpu_cond
as inputs? So it will sync the stream after copying both variables?
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.
fixed
test/ref_ops_test.cpp
Outdated
@@ -2439,6 +2439,100 @@ TEST_CASE(logsoftmax_test_axis_3) | |||
EXPECT(migraphx::verify_range(results_vector, s)); | |||
} | |||
|
|||
TEST_CASE(loop_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.
Can we put the ref loop unit tests in a seperate cpp file?
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.
changed
test/ref_ops_test.cpp
Outdated
} | ||
|
||
return res; | ||
}; |
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 it would be better to make this a regular function and make all the test cases seperate TEST_CASE
cases in the test suite. This will make it easier to debug in the future as we can just run one test case(instead of all of them).
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.
changed
src/onnx/onnx_parser.cpp
Outdated
if(contains(instructions, name)) | ||
{ | ||
MIGRAPHX_THROW("module \"" + mod->name() + "\" has parameter name \"" + name + | ||
"\" existing in paraent graph!"); |
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.
parent
.
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.
Sorry, fixed. Thanks!
test/run_loop_test.cpp
Outdated
return migraphx::shape(ins_out_shapes); | ||
} | ||
|
||
struct test_loop |
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.
Couldn't this inherit from ref_loop
then just override get_output_params
?
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.
changed
…GraphX into loop_operator
…GraphX into loop_operator
This PR is for the implementation of the Loop operator for opset version 13.
Notes: 1) Default max iteration number is 10 if no max iteration number is provided
2) To change the max iter number, a user can set the max_loop_iterations in the onnx_option struct when parsing a model.
3) The returned shape of the scan output is from the max_loop_iterations even the actual loop num is less than that. This issue also applies to other operators like NonZero and NonMaxSuppression. A issue #948 is created to track this and to be resolved later.