|
Uni20
Asynchronous tensor and runtime library.
|
Status: design note, not current API behavior. This note records the intended direction for ordinary Uni20 diagnostics and logging beyond the current trace.hpp macros.
Kernel dispatch has a narrower implemented diagnostic sink documented in ../architecture/kernel_dispatch.md. That sink reports backend selection and decline records only; it does not replace the general event/context/logging design described here.
This note predates the screen-display design in Screen Display Layer Plan. The display layer is the primary plan for human-facing terminal/Python progress output. This document remains useful for durable logging, structured events, async queueing, and sink routing concerns that overlap with display but should not make ordinary screen output feel like a heavyweight logging framework.
The existing trace/check/precondition macros are useful for local debugging, assertions, and emergency diagnostics, but they are not the right abstraction for normal warnings, progress messages, solver statistics, or long-running task logs.
As Uni20 becomes more asynchronous, direct writes to std::cout / std::cerr from library code will become increasingly fragile:
sys.stdout / sys.stderr capture will not reliably order with C++ stdio,The core rule should be: ordinary library code does not print. It emits diagnostics into a context.
Keep trace.hpp focused on correctness boundaries and emergency output:
PANIC, CHECK, PRECONDITION: abort-path diagnostics.ERROR / ERROR_IF: exception/error boundary diagnostics.Add a separate diagnostics/logging layer for:
The diagnostics layer should use the presentation layer only for rendering. It should not decide terminal glyphs, colors, wrapping, or ASCII fallback itself.
This is also separate from the async task-registry and Graphviz DAG debugging path. The DAG machinery answers structural runtime questions: which tasks exist, which buffers they await, where a dependency cycle or missing writer appears, and how to render that dependency graph for debugging.
The diagnostics/logging layer proposed here is for ordinary events emitted by library algorithms, including algorithms that happen to run inside async tasks. For example, a Krylov solver running asynchronously should be able to report iteration progress, convergence notices, stagnation warnings, and final statistics without writing directly to std::cout and without depending on the DAG debug renderer. Async task metadata can be attached to those events when it is useful, but the event is still solver/logging data rather than graph topology.
Introduce structured diagnostic events:
The exact payload representation can be decided later. The important point is that the event is structured at emission time and rendered only at the sink boundary.
Use named diagnostic contexts:
Likely built-in contexts:
Most contexts should be quiet by default. Warnings and important notices can go to the default terminal/Python sink; verbose progress/debug contexts should normally be disabled unless explicitly enabled.
Diagnostics should be routed through pluggable sinks:
sys.stdout / sys.stderr or warnings machinery,For Python, avoid direct C++ writes to stdout / stderr except for abort-path emergency diagnostics. A Python binding should install a Python-aware sink or drain events at safe points.
Async tasks should not generally render directly. They should emit events into a context-owned queue/buffer:
This gives deterministic ordering opportunities and avoids mixed C++/Python buffering problems. The first implementation can be simple: a mutex-protected queue plus explicit drain points. More sophisticated lock-free or per-task buffers can come later if needed.
Events emitted from async tasks should include task metadata early, even if the first renderer ignores it. A warning with a task id/name is much more useful than a loose line from an unknown worker thread.
Start with programmatic configuration:
Environment-based configuration can come later, for example:
The default should remain conservative: important warnings are visible, debug/progress spam is off.
Krylov and other iterative solvers should use this layer for optional progress and convergence reporting:
The same structured events can support terminal progress, test assertions, benchmark metadata, and Python callbacks without changing solver internals.
warnings module.