pub async fn run_async<A, H: AsyncHandler>(h: H, m: Model<A>) -> (A, Trace)Expand description
Execute a probabilistic model with an asynchronous handler.
The asynchronous counterpart of run: the
same walk over the same model, dispatching each effect to the matching
AsyncHandler method and awaiting it before the continuation runs, then
awaiting AsyncHandler::finish. It returns the model’s final value and
the accumulated trace.
- Sequential: a run awaits its sites one at a time, in program order, since the next site is not known until the current one has its value. Concurrency comes from running many models at once.
- Stack-safe: like
run(FG-19), an explicit loop rather than recursion, so the stack depth of every poll is independent of the number of sites, whether or not the handler suspends. - Executor-agnostic: it is a plain future; fugue depends on no async runtime.
- Cancellable: dropping the future stops the run at the site it is
waiting on; the handler is dropped without
AsyncHandler::finish.
The future is Send when the handler, its method futures and A are; see
AsyncHandler.
Example:
let model = || {
sample(addr!("x"), Normal::new(0.0, 1.0).unwrap())
.bind(|x| observe(addr!("y"), Normal::new(x, 0.1).unwrap(), 1.2).map(move |_| x))
};
let rt = tokio::runtime::Builder::new_current_thread().build().unwrap();
let mut rng = StdRng::seed_from_u64(123);
let (x, trace) = rt.block_on(run_async(
FromSync(PriorHandler { rng: &mut rng, trace: Trace::default() }),
model(),
));
// Exactly what the synchronous interpreter gives from the same seed
let mut rng = StdRng::seed_from_u64(123);
let (x_sync, trace_sync) = runtime::handler::run(
PriorHandler { rng: &mut rng, trace: Trace::default() },
model(),
);
assert_eq!(x, x_sync);
assert_eq!(trace.total_log_weight(), trace_sync.total_log_weight());