Skip to content

Commit e560009

Browse files
authored
Update doc loop op (onnx#2337)
* Clarify example in Loop documentation * Regenerate op documentation * generate op documentation * Address PR review comment * Address PR feedback * Update defs.cc * Update Changelog.md * Update Operators.md
1 parent 2891e14 commit e560009

File tree

4 files changed

+127
-67
lines changed

4 files changed

+127
-67
lines changed

docs/Changelog.md

+42-22
Original file line numberDiff line numberDiff line change
@@ -11630,15 +11630,15 @@ This version of the operator has been available since version 11 of the default
1163011630
}
1163111631

1163211632
graph body-net (
11633-
%i[INT32, scalar]
11634-
%keepgoing[BOOL, scalar]
11635-
%b[INT32, scalar]
11633+
%i[INT32, scalar] // iteration number
11634+
%keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
11635+
%b_in[INT32, scalar] // incoming value of loop-carried-dependency b
1163611636
) {
11637-
%my_local = Add(%a, %b)
11638-
%b_out = Sub(%a, %b)
11639-
%keepgoing_out = Greater(%my_local, %b_out)
11640-
%user_defined_vals = Add(%b, %b)
11641-
return %keepgoing_out, %b_out, %user_defined_vals
11637+
%my_local = Add(%a, %b_in)
11638+
%b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
11639+
%keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
11640+
%user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
11641+
return %keepgoing_out, %b_out, %user_defined_val
1164211642
}
1164311643

1164411644
*Sample equivalent C code*
@@ -11653,29 +11653,49 @@ This version of the operator has been available since version 11 of the default
1165311653
const int max_trip_count = 10; // Analogous to input M
1165411654
int user_defined_vals[]; // Imagine this is resizable
1165511655
/* End implicitly-defined code */
11656-
for (int i=0; i < max_trip_count && keepgoing; ++i) {
11656+
/* initialize loop-carried variables and scan-output variables */
11657+
bool keepgoing_out = keepgoing
11658+
int b_out = b
11659+
11660+
for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
11661+
/* Implicitly-defined code: bind actual parameter values
11662+
to formal parameter variables of loop-body */
11663+
bool keepgoing_in = keepgoing_out;
11664+
bool b_in = b_out;
11665+
1165711666
/* User-defined code (loop body) */
11658-
int my_local = a + b; // Reading values in the enclosing scope is fine
11659-
b = a - b; // writes fine if we specify b as a loop-carried dependency
11660-
keepgoing = my_local > b; // keepgoing is a loop-carried dependency
11661-
user_defined_vals[i] = b + b;
11667+
int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
11668+
b_out = a - b_in;
11669+
keepgoing_out = my_local > b_out;
11670+
user_defined_val = b_in + b_in; // b_in and b_out are different variables
1166211671
/* End user-defined code */
11672+
11673+
/* Implicitly defined-code */
11674+
user_defined_vals[i] = user_defined_val // accumulate scan-output values
1166311675
}
11664-
// my_local = 123; // Can't do this. my_local was defined in the the body
11676+
// int t = my_local; // Can't do this. my_local is not accessible here.
1166511677

11666-
// These below values are live-out from the loop and therefore accessible
11667-
b_out; user_defined_vals; keepgoing_out;
11678+
// The values below are bound to the output variables of the loop and therefore accessible
11679+
// b_out; user_defined_vals; keepgoing_out;
1166811680
}
1166911681

1167011682
There are several things of note in this code snippet:
1167111683

11672-
1) Values from the enclosing scope (i.e. variable a here) are in scope and can
11684+
1) Values from the enclosing scope (i.e. variable "a" here) are in scope and can
1167311685
be referenced in the inputs of the loop.
11674-
2) Any variables which you wish to make available in the enclosing scope (i.e.
11675-
the variables b and keepgoing) must be declared as either loop-carried
11676-
dependencies (both at the op inputs and output and at the body net input and
11677-
output) or scan_outputs.
11678-
3) Values created in the body cannot be accessed in the enclosing scope.
11686+
2) Any values computed in the loop body that needs to be used in a subsequent
11687+
iteration or after the loop are modelled using a pair of variables in the loop-body,
11688+
consisting of an input variable (eg., b_in) and an output variable (eg., b_out).
11689+
These are referred to as loop-carried dependences. The loop operation node
11690+
supplies the input value of the input variable for the first iteration, and
11691+
returns the output value of the output variable produced by the final
11692+
iteration.
11693+
3) Scan_output variables are used to implicitly concatenate values computed across
11694+
all the iterations. In the above example, the value of user_defined_val computed
11695+
over all iterations are concatenated and returned as the value of user_defined_vals
11696+
after the loop.
11697+
4) Values created in the body cannot be accessed in the enclosing scope,
11698+
except using the mechanism described above.
1167911699

1168011700
Note that the semantics of this op support "diagonal" or "wavefront" execution.
1168111701
(See Step 3 here for an example:

docs/Operators.md

+42-22
Original file line numberDiff line numberDiff line change
@@ -7511,15 +7511,15 @@ expect(node, inputs=[x], outputs=[y],
75117511
}
75127512

75137513
graph body-net (
7514-
%i[INT32, scalar]
7515-
%keepgoing[BOOL, scalar]
7516-
%b[INT32, scalar]
7514+
%i[INT32, scalar] // iteration number
7515+
%keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
7516+
%b_in[INT32, scalar] // incoming value of loop-carried-dependency b
75177517
) {
7518-
%my_local = Add(%a, %b)
7519-
%b_out = Sub(%a, %b)
7520-
%keepgoing_out = Greater(%my_local, %b_out)
7521-
%user_defined_vals = Add(%b, %b)
7522-
return %keepgoing_out, %b_out, %user_defined_vals
7518+
%my_local = Add(%a, %b_in)
7519+
%b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
7520+
%keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
7521+
%user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
7522+
return %keepgoing_out, %b_out, %user_defined_val
75237523
}
75247524

75257525
*Sample equivalent C code*
@@ -7534,29 +7534,49 @@ expect(node, inputs=[x], outputs=[y],
75347534
const int max_trip_count = 10; // Analogous to input M
75357535
int user_defined_vals[]; // Imagine this is resizable
75367536
/* End implicitly-defined code */
7537-
for (int i=0; i < max_trip_count && keepgoing; ++i) {
7537+
/* initialize loop-carried variables and scan-output variables */
7538+
bool keepgoing_out = keepgoing
7539+
int b_out = b
7540+
7541+
for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
7542+
/* Implicitly-defined code: bind actual parameter values
7543+
to formal parameter variables of loop-body */
7544+
bool keepgoing_in = keepgoing_out;
7545+
bool b_in = b_out;
7546+
75387547
/* User-defined code (loop body) */
7539-
int my_local = a + b; // Reading values in the enclosing scope is fine
7540-
b = a - b; // writes fine if we specify b as a loop-carried dependency
7541-
keepgoing = my_local > b; // keepgoing is a loop-carried dependency
7542-
user_defined_vals[i] = b + b;
7548+
int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
7549+
b_out = a - b_in;
7550+
keepgoing_out = my_local > b_out;
7551+
user_defined_val = b_in + b_in; // b_in and b_out are different variables
75437552
/* End user-defined code */
7553+
7554+
/* Implicitly defined-code */
7555+
user_defined_vals[i] = user_defined_val // accumulate scan-output values
75447556
}
7545-
// my_local = 123; // Can't do this. my_local was defined in the the body
7557+
// int t = my_local; // Can't do this. my_local is not accessible here.
75467558

7547-
// These below values are live-out from the loop and therefore accessible
7548-
b_out; user_defined_vals; keepgoing_out;
7559+
// The values below are bound to the output variables of the loop and therefore accessible
7560+
// b_out; user_defined_vals; keepgoing_out;
75497561
}
75507562

75517563
There are several things of note in this code snippet:
75527564

7553-
1) Values from the enclosing scope (i.e. variable a here) are in scope and can
7565+
1) Values from the enclosing scope (i.e. variable "a" here) are in scope and can
75547566
be referenced in the inputs of the loop.
7555-
2) Any variables which you wish to make available in the enclosing scope (i.e.
7556-
the variables b and keepgoing) must be declared as either loop-carried
7557-
dependencies (both at the op inputs and output and at the body net input and
7558-
output) or scan_outputs.
7559-
3) Values created in the body cannot be accessed in the enclosing scope.
7567+
2) Any values computed in the loop body that needs to be used in a subsequent
7568+
iteration or after the loop are modelled using a pair of variables in the loop-body,
7569+
consisting of an input variable (eg., b_in) and an output variable (eg., b_out).
7570+
These are referred to as loop-carried dependences. The loop operation node
7571+
supplies the input value of the input variable for the first iteration, and
7572+
returns the output value of the output variable produced by the final
7573+
iteration.
7574+
3) Scan_output variables are used to implicitly concatenate values computed across
7575+
all the iterations. In the above example, the value of user_defined_val computed
7576+
over all iterations are concatenated and returned as the value of user_defined_vals
7577+
after the loop.
7578+
4) Values created in the body cannot be accessed in the enclosing scope,
7579+
except using the mechanism described above.
75607580

75617581
Note that the semantics of this op support "diagonal" or "wavefront" execution.
75627582
(See Step 3 here for an example:

onnx/defs/controlflow/defs.cc

+42-22
Original file line numberDiff line numberDiff line change
@@ -482,15 +482,15 @@ C-style code:
482482
}
483483
484484
graph body-net (
485-
%i[INT32, scalar]
486-
%keepgoing[BOOL, scalar]
487-
%b[INT32, scalar]
485+
%i[INT32, scalar] // iteration number
486+
%keepgoing_in[BOOL, scalar] // incoming loop-termination-condition; not used
487+
%b_in[INT32, scalar] // incoming value of loop-carried-dependency b
488488
) {
489-
%my_local = Add(%a, %b)
490-
%b_out = Sub(%a, %b)
491-
%keepgoing_out = Greater(%my_local, %b_out)
492-
%user_defined_vals = Add(%b, %b)
493-
return %keepgoing_out, %b_out, %user_defined_vals
489+
%my_local = Add(%a, %b_in)
490+
%b_out = Sub(%a, %b_in) // outgoing value of loop-carried-dependency b
491+
%keepgoing_out = Greater(%my_local, %b_out) // outgoing loop-termination-condition
492+
%user_defined_val = Add(%b_in, %b_in) // scan-output value to be accumulated
493+
return %keepgoing_out, %b_out, %user_defined_val
494494
}
495495
496496
*Sample equivalent C code*
@@ -505,29 +505,49 @@ C-style code:
505505
const int max_trip_count = 10; // Analogous to input M
506506
int user_defined_vals[]; // Imagine this is resizable
507507
/* End implicitly-defined code */
508-
for (int i=0; i < max_trip_count && keepgoing; ++i) {
508+
/* initialize loop-carried variables and scan-output variables */
509+
bool keepgoing_out = keepgoing
510+
int b_out = b
511+
512+
for (int i=0; i < max_trip_count && keepgoing_out; ++i) {
513+
/* Implicitly-defined code: bind actual parameter values
514+
to formal parameter variables of loop-body */
515+
bool keepgoing_in = keepgoing_out;
516+
bool b_in = b_out;
517+
509518
/* User-defined code (loop body) */
510-
int my_local = a + b; // Reading values in the enclosing scope is fine
511-
b = a - b; // writes fine if we specify b as a loop-carried dependency
512-
keepgoing = my_local > b; // keepgoing is a loop-carried dependency
513-
user_defined_vals[i] = b + b;
519+
int my_local = a + b_in; // Reading value "a" from the enclosing scope is fine
520+
b_out = a - b_in;
521+
keepgoing_out = my_local > b_out;
522+
user_defined_val = b_in + b_in; // b_in and b_out are different variables
514523
/* End user-defined code */
524+
525+
/* Implicitly defined-code */
526+
user_defined_vals[i] = user_defined_val // accumulate scan-output values
515527
}
516-
// my_local = 123; // Can't do this. my_local was defined in the the body
528+
// int t = my_local; // Can't do this. my_local is not accessible here.
517529
518-
// These below values are live-out from the loop and therefore accessible
519-
b_out; user_defined_vals; keepgoing_out;
530+
// The values below are bound to the output variables of the loop and therefore accessible
531+
// b_out; user_defined_vals; keepgoing_out;
520532
}
521533
522534
There are several things of note in this code snippet:
523535
524-
1) Values from the enclosing scope (i.e. variable a here) are in scope and can
536+
1) Values from the enclosing scope (i.e. variable "a" here) are in scope and can
525537
be referenced in the inputs of the loop.
526-
2) Any variables which you wish to make available in the enclosing scope (i.e.
527-
the variables b and keepgoing) must be declared as either loop-carried
528-
dependencies (both at the op inputs and output and at the body net input and
529-
output) or scan_outputs.
530-
3) Values created in the body cannot be accessed in the enclosing scope.
538+
2) Any values computed in the loop body that needs to be used in a subsequent
539+
iteration or after the loop are modelled using a pair of variables in the loop-body,
540+
consisting of an input variable (eg., b_in) and an output variable (eg., b_out).
541+
These are referred to as loop-carried dependences. The loop operation node
542+
supplies the input value of the input variable for the first iteration, and
543+
returns the output value of the output variable produced by the final
544+
iteration.
545+
3) Scan_output variables are used to implicitly concatenate values computed across
546+
all the iterations. In the above example, the value of user_defined_val computed
547+
over all iterations are concatenated and returned as the value of user_defined_vals
548+
after the loop.
549+
4) Values created in the body cannot be accessed in the enclosing scope,
550+
except using the mechanism described above.
531551
532552
Note that the semantics of this op support "diagonal" or "wavefront" execution.
533553
(See Step 3 here for an example:

third_party/pybind11

Submodule pybind11 updated 130 files

0 commit comments

Comments
 (0)