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
+25-33Lines changed: 25 additions & 33 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -307,12 +307,10 @@ Inline declarations can also be used outside of assignments for creating non-dif
307
307
in
308
308
```
309
309
310
-
For `%op`, the declaration is allowed anywhere. If there is a `~config` function parameter used inside the extension scope, for example as `fun ~config ... -> ...` or a more specific example `let%op mlp ~config x = ...`, the scope of an inline-declared tensor is no longer the full scope of the extension point. Instead, the tensor is defined right underneath the introduction of the `~config` parameter: `fun ~config -> let <definitions of the inline-declared tensors> in ...`. The config value passed to the generated code must be a record with at least a field `label : string list`. The inline-declared tensor that's defined under a `~config` parameter is defined as `TDSL.param ~more_label:config.label ...`Example showing two param tensors declared inline, including `config.label` in their labels:
310
+
For `%op`, the declaration is allowed anywhere. If there is a unit `()`parameter in the function, the scope of inline-declared tensors is delimited at that parameter. The tensors are defined right after the unit parameter. If there is a labeled parameter with label `label` before the unit parameter (e.g., `~label`), the inline-declared tensors will use that parameter (which should be of type `string list`) to enrich their labels. Example showing two param tensors declared inline, with scope delimited by `()` and labels enriched by the `label` parameter:
311
311
312
312
```ocaml
313
-
type mlp_layer_config = { label : string list; hid_dim : int }
314
-
315
-
let%op mlp_layer ~config x = relu ({ w } * x + { b; o = [ config.hid_dim ] })
313
+
let%op mlp_layer ~label ~hid_dim () x = relu ({ w } * x + { b; o = [ hid_dim ] })
316
314
```
317
315
318
316
## Using OCANNL's generalized einsum notation
@@ -418,13 +416,15 @@ This syntax used to be very important, because comments in assignments are used
418
416
419
417
### Name from binding
420
418
421
-
When an extension point is applied to a let-binding, e.g. `let%op mlp_layer ~config x = relu ({ w } * x + { b; o = [ 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.
419
+
When an extension point is applied to a let-binding, e.g. `let%op mlp_layer ~label ~hid_dim () x = relu ({ w } * x + { b; o = [ 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.
420
+
421
+
The example `let%op mlp_layer ~label ~hid_dim () x = relu ({ w } * x + { b; o = [ hid_dim ] })` also illustrates providing additional string list to populate the label of the tensor: `label` must be of type `string list`.
422
422
423
423
### Label from function argument
424
424
425
425
The resulting (primary) tensor's label will also have incorporated the label of the input argument, if any. In our example, the resulting `mlp_layer` tensor will also include the label of the actually applied `x`.
426
426
427
-
Note that we do not include `config.label`, even if `config` is available, because the actually applied input argument will typically have more specific information.
427
+
Note that we do not include separate config labels, because the actually applied input argument will typically have more specific information.
@@ -449,59 +449,51 @@ A very simple example from [micrograd_demo: Micrograd README basic example](test
449
449
450
450
### Lifting of the applications of config arguments: if an error, refactor your code
451
451
452
-
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 = relu ({ w } * x + { b; o = [ config.hid_dim ] })` translates as:
452
+
If you recall, inline declared param tensors get lifted out of functions to be defined at the point of a unit `()` parameter. Our example `let%op mlp_layer ~label ~hid_dim () x = relu ({ w } * x + { b; o = [ hid_dim ] })` translates as:
453
453
454
454
```ocaml
455
-
let mlp_layer ~config =
456
-
let w = TDSL.param ~more_label:config.label "w" ()
457
-
and b = TDSL.param ~more_label:config.label ~output_dims:[ config.hid_dim ] "b" () in
455
+
let mlp_layer ~label ~hid_dim () =
456
+
let w = TDSL.param ~more_label:label "w" ()
457
+
and b = TDSL.param ~more_label:label ~output_dims:[ hid_dim ] "b" () in
458
458
fun x -> TDSL.O.(relu (w * x + b))
459
459
```
460
460
461
461
For this to work properly, when employing such network blocks, their params also need to be introduced at the right moment. Therefore, the `%op` syntax ensures that this example:
462
462
463
463
```ocaml
464
-
type tlp_config = { label : string list; dim1 : int; dim2 : int; dim3 : int }
List.foldi hid_dims ~init:x ~f:(fun i x hid_dim ->
485
+
mlp_layer ~label:[ "L" ^ Int.to_string i ] ~hid_dim () x)
492
486
```
493
487
494
488
The attempted lifting breaks because of the escaping variables `i` and `hid_dim`. This reminds us to rewrite the example, ensuring the proper introduction of params:
495
489
496
490
```ocaml
497
-
type mlp_config = { label : string list; hid_dims : int list }
0 commit comments