Skip to main content

run_async

Function run_async 

Source
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());