Skip to content

Commit 69a280f

Browse files
danieldkshadeMe
andauthored
Add with_signpost_interval layer (#711)
* Add with_signpost_interval layer This layer wraps a layer, adding macOS interval signposts for the forward and backward pass. These intervals can then be visualized in the macOS Instruments.app timeline. * Fix reference in api-layers.md Co-authored-by: Madeesh Kannan <[email protected]> * End message is optional since signpost 0.0.3 * with_signpost_interval: also wrap init callback * docs: we wrap init as well * Add documentation fixes Suggested by @svlandeg. Co-authored-by: Madeesh Kannan <[email protected]>
1 parent 42b73c9 commit 69a280f

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

thinc/api.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
from .layers import with_reshape, with_getitem, strings2arrays, list2array
4141
from .layers import list2ragged, ragged2list, list2padded, padded2list, remap_ids
4242
from .layers import array_getitem, with_cpu, with_debug, with_nvtx_range
43+
from .layers import with_signpost_interval
4344
from .layers import tuplify
4445

4546
from .layers import reduce_first, reduce_last, reduce_max, reduce_mean, reduce_sum

thinc/compat.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,13 @@
7878
h5py = None
7979

8080

81+
try: # pragma: no cover
82+
import os_signpost
83+
84+
has_os_signpost = True
85+
except ImportError:
86+
os_signpost = None
87+
has_os_signpost = False
88+
89+
8190
has_gpu = has_cupy_gpu or has_torch_mps_gpu

thinc/layers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
from .with_getitem import with_getitem
7272
from .with_debug import with_debug
7373
from .with_nvtx_range import with_nvtx_range
74+
from .with_signpost_interval import with_signpost_interval
7475

7576

7677
__all__ = [
@@ -128,5 +129,6 @@
128129
"with_flatten",
129130
"with_debug",
130131
"with_nvtx_range",
132+
"with_signpost_interval",
131133
"remap_ids",
132134
]
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
from typing import Optional, Callable, Any, Tuple, TypeVar
2+
3+
from ..compat import has_os_signpost, os_signpost
4+
from ..model import Model
5+
6+
7+
_ModelT = TypeVar("_ModelT", bound=Model)
8+
9+
10+
def with_signpost_interval(
11+
layer: _ModelT,
12+
signposter: "os_signpost.Signposter",
13+
name: Optional[str] = None,
14+
) -> _ModelT:
15+
"""Wraps any layer and marks the init, forward and backprop phases using
16+
signpost intervals for macOS Instruments profiling
17+
18+
By default, the name of the layer is used as the name of the range,
19+
followed by the name of the pass.
20+
"""
21+
if not has_os_signpost:
22+
raise ValueError(
23+
"with_signpost_interval layer requires the 'os_signpost' package"
24+
)
25+
26+
name = layer.name if name is None else name
27+
28+
orig_forward = layer._func
29+
orig_init = layer.init
30+
31+
def forward(model: Model, X: Any, is_train: bool) -> Tuple[Any, Callable]:
32+
with signposter.use_interval(f"{name} forward"):
33+
layer_Y, layer_callback = orig_forward(model, X, is_train=is_train)
34+
35+
def backprop(dY: Any) -> Any:
36+
with signposter.use_interval(f"{name} backprop"):
37+
return layer_callback(dY)
38+
39+
return layer_Y, backprop
40+
41+
def init(_model: Model, X: Any, Y: Any) -> Model:
42+
if orig_init is not None:
43+
with signposter.use_interval(f"{name} init"):
44+
return orig_init(layer, X, Y)
45+
else:
46+
return layer
47+
48+
layer.replace_callbacks(forward, init=init)
49+
50+
return layer

website/docs/api-layers.md

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,8 @@ https://github.com/explosion/thinc/blob/master/thinc/layers/reduce_last.py
835835
</inline-list>
836836

837837
Pooling layer that reduces the dimensions of the data by selecting the maximum
838-
value for each feature. A `ValueError` is raised if any element in `lengths`
839-
is zero.
838+
value for each feature. A `ValueError` is raised if any element in `lengths` is
839+
zero.
840840

841841
| Argument | Type | Description |
842842
| ----------- | -------------------------------- | -------------------------- |
@@ -1531,6 +1531,45 @@ model.initialize()
15311531
https://github.com/explosion/thinc/blob/master/thinc/layers/with_nvtx_range.py
15321532
```
15331533

1534+
### with_signpost_interval {#with_signpost_interval tag="function" new="8.1.1"}
1535+
1536+
<inline-list>
1537+
1538+
- **Input:** <tt>Any</tt>
1539+
- **Output:** <tt>Any</tt>
1540+
1541+
</inline-list>
1542+
1543+
Layer that wraps any layer and marks the init, forward and backprop passes as a
1544+
(macOS) signpost interval. This can be helpful when profiling the performance of
1545+
a layer using macOS
1546+
[Instruments.app](https://help.apple.com/instruments/mac/current/). Use of this
1547+
layer requires that the
1548+
[`os-signpost`](https://github.com/explosion/os-signpost) package is installed.
1549+
1550+
```python
1551+
### Example
1552+
from os_signpost import Signposter
1553+
from thinc.api import Linear, with_signpost_interval
1554+
1555+
signposter = Signposter("com.example.my_subsystem",
1556+
Signposter.Category.DynamicTracing)
1557+
1558+
model = with_signpost_interval(Linear(2, 5), signposter)
1559+
model.initialize()
1560+
```
1561+
1562+
| Argument | Type | Description |
1563+
| ------------ | --------------------------------- | ------------------------------------------------------------------------------- |
1564+
| `layer` | <tt>Model</tt> | The layer to wrap. |
1565+
| `signposter` | <tt>os_signposter.Signposter</tt> | `Signposter` object to log the interval with. |
1566+
| `name` | <tt>Optional[str]</tt> | Optional name for the wrapped layer. Defaults to the name of the wrapped layer. |
1567+
| **RETURNS** | <tt>Model</tt> | The wrapped layer. |
1568+
1569+
```python
1570+
https://github.com/explosion/thinc/blob/master/thinc/layers/with_signpost_interval.py
1571+
```
1572+
15341573
---
15351574

15361575
## Wrappers {#wrappers}

0 commit comments

Comments
 (0)