Skip to content

Fix the example and equivalent C code in the Loop's documentation.#2144

Closed
xykong58 wants to merge 5 commits intoonnx:mainfrom
xykong58:master
Closed

Fix the example and equivalent C code in the Loop's documentation.#2144
xykong58 wants to merge 5 commits intoonnx:mainfrom
xykong58:master

Conversation

@xykong58
Copy link
Copy Markdown
Contributor

  • 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.

Comment thread docs/Operators.md
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;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.)

Copy link
Copy Markdown
Collaborator

@wschin wschin Jul 2, 2019

Choose a reason for hiding this comment

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

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.

@gramalingam
Copy link
Copy Markdown
Contributor

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

Comment thread docs/Operators.md
) {
%my_local = Add(%a, %b)
%b_out = Sub(%a, %b)
%my_local = Add(%a, %b_in)
Copy link
Copy Markdown
Collaborator

@wschin wschin Jul 2, 2019

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

@skottmckay skottmckay Jul 17, 2019

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[](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)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Jul 24, 2019

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ linkerzhang
❌ xykong58
You have signed the CLA already but the status is still pending? Let us recheck it.

@postrational postrational added the topic: operator Issues related to ONNX operators label Aug 22, 2019
@prasanthpul prasanthpul added this to the 1.6 milestone Sep 9, 2019
@gramalingam
Copy link
Copy Markdown
Contributor

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.

@ebarsoum ebarsoum modified the milestones: 1.6, 1.7 Sep 16, 2019
@xykong58
Copy link
Copy Markdown
Contributor Author

@gramalingam
Enough discussions on the issue, sounds like it is better to create a new PR for updating the document.

@gramalingam gramalingam mentioned this pull request Sep 19, 2019
@chinhuang007 chinhuang007 removed this from the 1.7 milestone Feb 27, 2020
@gramalingam
Copy link
Copy Markdown
Contributor

Closing this PR since PR #2337 covered this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: operator Issues related to ONNX operators

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants