You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: lib/syntax_extensions.md
+8-8Lines changed: 8 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,7 +25,7 @@
25
25
26
26
## Preliminaries
27
27
28
-
OCANNL, and Arrayjit specifically, is built around a fixed number of numeric operations, declared in `arrayjit/ops.ml`. We assign operators to many of the operations, inventing new operators. For example, Rectified Linear Unit `Relu` operation, which computes `f(x) = max(0,x)`, gets the operator `!/`, and the ReLU-Gate `Relu_gate` operation, which computes `f(x,y) = if x > 0.0 then y else 0.0`, gets the operator `-?/`. These built-in numeric operations are used to construct assignments (`Assignments.t`). The syntax `%cd` is needed to build assignments concisely. On the other hand, while the syntax `%op` helps build tensors (`Tensor.t`), they can be expressed concisely in pure OCaml. Unlike for assignments, the building blocks for tensor expressions are easy to extend. The meaningful basic ones are provided in `lib/operation.ml`.
28
+
OCANNL, and Arrayjit specifically, is built around a fixed number of numeric operations, declared in `arrayjit/ops.ml`. We assign operators to many of the operations, inventing new operators. For example, Rectified Linear Unit `Relu` operation, which computes `f(x) = max(0,x)`, gets the operator `?/`, and the ReLU-Gate `Relu_gate` operation, which computes `f(x,y) = if x > 0.0 then y else 0.0`, gets the operator `-?/`. These built-in numeric operations are used to construct assignments (`Assignments.t`). The syntax `%cd` is needed to build assignments concisely. On the other hand, while the syntax `%op` helps build tensors (`Tensor.t`), they can be expressed concisely in pure OCaml. Unlike for assignments, the building blocks for tensor expressions are easy to extend. The meaningful basic ones are provided in `lib/operation.ml`.
29
29
30
30
In OCANNL, we call a tensor that is prohibited from propagating gradients, does not have a gradient node nor backprop code, a _non-differentiable tensor_. Accordingly we can call the "plain" tensors with a gradient node _differentiable tensors_. Expressions in the `%cd` syntax will sometimes build new non-differentiable tensors as components of assignments (they will never build new differentiable tensors). The syntax extensions make the following assumption:
31
31
@@ -44,7 +44,7 @@ The extension points open `NTDSL.O`, resp. `TDSL.O`, for the scope of the extens
44
44
let hid_dim = 8 in
45
45
let w = Tensor.param "w" in
46
46
let b = Tensor.param ~output_dims:[ hid_dim ] "b" in
47
-
let layer x = TDSL.O.( !/(w * x + b) ) in
47
+
let layer x = TDSL.O.( ?/(w * x + b) ) in
48
48
...
49
49
```
50
50
@@ -54,15 +54,15 @@ Since `TDSL.O` is opened for the scope of an extension point `%op`:
54
54
let hid_dim = 8 in
55
55
let w = Tensor.param "w" in
56
56
let b = Tensor.param ~output_dims:[ hid_dim ] "b" in
57
-
let%op layer x = !/(w * x + b) in
57
+
let%op layer x = ?/(w * x + b) in
58
58
...
59
59
```
60
60
61
61
Using [inline declarations](#inline-declarations), this becomes more concise:
62
62
63
63
```ocaml
64
64
let hid_dim = 8 in
65
-
let%op mlp_layer x = !/("w" * x + "b" hid_dim) in
65
+
let%op mlp_layer x = ?/("w" * x + "b" hid_dim) in
66
66
...
67
67
```
68
68
@@ -163,7 +163,7 @@ For `%op`, the declaration is allowed anywhere. If there is a `~config` function
163
163
```ocaml
164
164
type mlp_layer_config = { label : string list; hid_dim : int }
165
165
166
-
let%op mlp_layer ~config x = !/ ("w" * x + "b" config.hid_dim)
166
+
let%op mlp_layer ~config x = ?/ ("w" * x + "b" config.hid_dim)
167
167
```
168
168
169
169
## Using OCANNL's generalized einsum notation
@@ -210,7 +210,7 @@ type Assignments.t =
210
210
211
211
### Name from binding
212
212
213
-
When an extension point is applied to a let-binding, e.g. `let%op mlp_layer ~config x = !/ ("w" * x + "b" config.hid_dim)`, it uses the name of the binding (`mlp_layer` in the example) for the label of the primary tensor created by the extension, if any. This is why the resulting layer tensor in the example has its label starting with `"mlp_layer"`. If the extension is over a semicolon-separated sequence of expressions, the primary tensor can only be in the last component of the sequence, other syntax constructs are handled analogously.
213
+
When an extension point is applied to a let-binding, e.g. `let%op mlp_layer ~config x = ?/ ("w" * x + "b" config.hid_dim)`, it uses the name of the binding (`mlp_layer` in the example) for the label of the primary tensor created by the extension, if any. This is why the resulting layer tensor in the example has its label starting with `"mlp_layer"`. If the extension is over a semicolon-separated sequence of expressions, the primary tensor can only be in the last component of the sequence, other syntax constructs are handled analogously.
214
214
215
215
### Label from function argument
216
216
@@ -222,7 +222,7 @@ Note that we do not include `config.label`, even if `config` is available, becau
222
222
223
223
In the `%op` syntax, when a tuple follows an inline declaration of a tensor (i.e. a string literal), the tuple is passed to specify the output axes in the tensor definition (via the `~output_dims` argument).
224
224
225
-
When it is an integer, an identifier, or a record field dereference following an inline declaration, this expression specifies the single output axis in the tensor definition. You can see an example above in this document: `let%op mlp_layer ~config x = !/ ("w" * x + "b" config.hid_dim)`.
225
+
When it is an integer, an identifier, or a record field dereference following an inline declaration, this expression specifies the single output axis in the tensor definition. You can see an example above in this document: `let%op mlp_layer ~config x = ?/ ("w" * x + "b" config.hid_dim)`.
226
226
227
227
If it is a list expression following an inline declaration, the expression is parsed as an [N-dimensional array constant](#numeric-and-n-dimensional-array-literals), and used to initialize the value tensor node of the defined tensor. A very simple example from [micrograd_demo: Micrograd README basic example](test/micrograd_demo.ml):
228
228
@@ -233,7 +233,7 @@ If it is a list expression following an inline declaration, the expression is pa
233
233
234
234
### Lifting of the applications of `~config` arguments: if it's an error, refactor your code
235
235
236
-
If you recall, inline declared param tensors get lifted out of functions except for the function `fun ~config ->`, where they get defined. Our example `let%op mlp_layer ~config x = !/ ("w" * x + "b" config.hid_dim)` translates as:
236
+
If you recall, inline declared param tensors get lifted out of functions except for the function `fun ~config ->`, where they get defined. Our example `let%op mlp_layer ~config x = ?/ ("w" * x + "b" config.hid_dim)` translates as:
0 commit comments