Status
The status is the central record of what a run is doing. Code anywhere in the
backend reports the work it is doing to it as named tasks with optional progress.
Every record logged under icegraph is routed
through it as well, before going on to the configured logging handlers as usual.
Callbacks and anything else holding the status can subscribe to status streams.
Usage
The status occupies the top-level status slot. Every option has a default, so the
slot can be left out.
status:
profile_flops: true
Services, components and the policy reach it through status on their context.
To report active work:
status = self._ctx.status
with status.task("Indexing shards", total=len(paths)) as task:
for path in paths:
...
task.advance()
# or, equivalently, for a plain loop
for path in status.track(paths, "Indexing shards"):
...
Measuring a stream of batches, as the engines do for each split:
throughput = status.throughput("train")
for batch in throughput.iterate(loader):
with throughput.step(batch):
...
throughput.stats() # samples/s, batches/s, FLOP/s, fraction of time waiting on data
Following it from a callback:
from icegraph.engine.status import TaskEvent, LogEvent, EventKind
class MyCallback(TrainerCallback):
def on_status(self, ctx):
event = ctx.event
if isinstance(event, TaskEvent) and event.kind is EventKind.FINISHED:
print(event.task.name, event.task.elapsed)
elif isinstance(event, LogEvent):
print(event.entry.levelname, event.entry.message)
icegraph.ui.StatusView and icegraph.ui.LogView render the running tasks and the
recent logs for Rich displays.
How it works
Tasks. A task opened while another is open on the same thread becomes its child, so the running tasks form a tree, e.g. Starting up containing Building components containing Indexing shards. Used as a context manager, a task finishes on exit or fails if an exception escapes it, and either way its timing is logged. Every start, update, finish and failure is sent to listeners. Listeners that raise are logged and unsubscribed so a broken display cannot stop the work it reports on.
Logs. The status installs a handler on the icegraph logger, so every record any
module logs reaches it, is kept as a LogEntry, and is sent to listeners as a
LogEvent. The status’s own messages, such as each
task’s completion and timing, take the same path. What reaches the status is whatever
the logging configuration lets through, so call configure_logging before building
the engine. Reconfiguring logging afterwards removes the handler.
Throughput. iterate reports the wait for a stream’s first batch as a task, which
covers worker startup and the first buffer fill, and meters time blocked on the loader.
step counts samples and batches. On the stream’s first batch, it counts FLOPs with
torch’s FlopCounterMode, later batch FLOPs are computed by scaling this value using node count. Only
matmul-like operations are counted, not scatter aggregation. Rates are taken over each
meter’s last window updates.
The status is per process. Loader workers receive a copy with no listeners, nothing recorded and no logging handler, so work they do is not reported back to the main process.
Configuration
Option |
Description |
Type |
Default |
|---|---|---|---|
|
Log entries kept for inspection. |
int |
|
|
Updates each meter keeps to compute its rate. |
int |
|
|
Count FLOPs on the first batch of each throughput stream to report FLOP/s. |
bool |
|