Fix the example and equivalent C code in the Loop's documentation.#2144
Fix the example and equivalent C code in the Loop's documentation.#2144
Conversation
xykong58
commented
Jun 29, 2019
- Change the formal parameter names to be different from the actual to avoid confusion.
- Fix the equivalent C code so that the C code is semantically equal to the ONNX code.
| b_out = a - b; // writes fine if we specify b as a loop-carried dependency | ||
| keepgoing = my_local > b_out; // keepgoing is a loop-carried dependency | ||
| user_defined_vals[i] = b + b; | ||
| b = b_out; |
There was a problem hiding this comment.
With b_out, b inside the loop body can probably be removed. I personally like changing b_out below to b or adding b_out=b right after this loop.
There was a problem hiding this comment.
I think we can use "b" uniformly inside the loop, and add b_out=b after the loop. (See suggested change to the ONNX example discussed above.)
There was a problem hiding this comment.
Look like we need to add keepgoing_out = keepgoing right after the loop too. In addition, we need modify the description of
graph body-net (
%i[INT32, scalar]
…
accordingly.
|
Please note that the documentation is generated. The op-definition in the defs file will need to be updated. See step 5 of https://github.com/onnx/onnx/blob/master/docs/AddNewOp.md … The op definition is in https://github.com/onnx/onnx/blob/master/onnx/defs/controlflow/defs.cc |
| ) { | ||
| %my_local = Add(%a, %b) | ||
| %b_out = Sub(%a, %b) | ||
| %my_local = Add(%a, %b_in) |
There was a problem hiding this comment.
It looks not smooth. The value of b_in may change from iteration to iteration, so adding an Assignment to update b is closer to the sementic. @gramalingam any comment to the style change? I feel it will slightly change the original design.
If we use b in each iteration, it means b_out is not accessible until the last iteration is finished and the last b_in is assigned to b_out. Nevertheless, in the original design, b_out looks like an alias of b, so they are available at the same time.
There was a problem hiding this comment.
I removed the changes to operator.md, and made the changes to the comments in defs.cc as suggested.
One issue is that the "Loop" documentation does not specify the semantics for
zero-trip, i.e., if the loop body is not executred, what will be the outputs. I modified the equivalent C code to make the outputs hold the values of the initial, and Scan-outputs will still be uninitialized.
There was a problem hiding this comment.
In the zero-trip case, I think it's correct to have the outputs hold the initial values for the loop carried dependencies as I don't think they should be dropped due to having zero iterations.
I'd describe the 'scan_outputs' as being empty rather than uninitialized. Outside of the scope of the C example, but the shape returned for a scan_output in the zero-trip case should have at least one dimension with a value of 0 in the first dimension as that represents the number of iterations, and downstream nodes should be able to assume that dimension exists.
There was a problem hiding this comment.
However the C example seems flawed in that there's no good way to represent what is happening in the graph example.
a and b are outer scope values, and there's a new scope for the loop implementation where b_in is provided as a parameter and b_out is a return value. there's no equivalent to that setup with a 'for' loop and that's where it gets confusing.
Would the following be better?
void loop_func()
{
/* User-defined code (enclosing scope) */
int a = 3, b = 6;
bool keepgoing = true; // Analogous to input cond
/* End user-defined code */
/* Implicitly-defined code */
const int max_trip_count = 10; // Analogous to input M
int user_defined_vals[]; // Imagine this is resizable
/* End implicitly-defined code */
/* initialize values that will be passed around during each iteration of the loop.
also handles zero loop case */
bool keepgoing_out = keepgoing; // condition
int b_out = b; // loop carried dependency
for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
/* implicitly-defined code */
int b_in = b_out;
int keepgoing_in = keepgoing_out;
/* User-defined code (loop body) */
int my_local = a + b; // Reading values in the enclosing scope is fine
b_out = a - b_in; // writes fine as b_out is the output value of the loop-carried dependency
keepgoing_out = my_local > b_out;
int user_defined_val = b_in + b_in;
/* End user-defined code */
/*implicitly-defined code */
user_defined_vals[i] = user_defined_val;
}
// my_local = 123; // Can't do this. my_local was defined in the the body
// These below values are live-out from the loop and therefore accessible
// b_out; keepgoing_out; user_defined_vals;
// and user_defined_vals are concated output
}
| int user_defined_vals[]; // Imagine this is resizable | ||
| /* End implicitly-defined code */ | ||
| int b_out = b; | ||
| bool keepgoing_out = keepgoing; |
There was a problem hiding this comment.
My personal preference would be to put the above two lines (assignments to b_out and keepgoing_out) after the loop. There needs to be only one "loop-carried" version of each variable, and those seem to be "b" and "keepgoing". Technically, both have the same effect, so this is just a minor nitpick.
| user_defined_vals[i] = b + b; | ||
| /* End user-defined code */ | ||
|
|
||
| // loop-carried definitions are passed as inputs to next iteration. |
There was a problem hiding this comment.
[](start = 0, length = 1)
nit: tab
| %b_out = Sub(%a, %b_in) | ||
| %keepgoing_out = Greater(%my_local, %b_out) | ||
| %user_defined_vals = Add(%b, %b) | ||
| %user_defined_vals = Add(%b_in, %b_in) |
There was a problem hiding this comment.
I think this should be called user_defined_val. It's in the Loop implementation not the loop body that these get aggregated (one item per loop iteration) and returned as the user_defined_vals output.
|
|
|
Scott's suggestions look good to me (distinguishing "implicit code" and "explicit code" etc.). Is this PR still active? Can @xykong58 address these comments? If not, I can create a new PR to update the documentation. |
|
@gramalingam |
|
Closing this PR since PR #2337 covered this. |