Skip to content

Calling run() multiple times #30

@B-Lorentz

Description

@B-Lorentz

If I understand correctly, ascent is't a 'differential datalog'-style implementation, but is optimized for batch processing.
The API does however allow .run() to be called multiple times, so users will eventually do it.
I did a little experiment:

use std::time::Instant;

use ascent::ascent;

fn main() {
    ascent!{
        #![measure_rule_times]
        relation x(u64,u64);
        relation y(u64,u64);
        y(i,n) <-- x(i,n), x(i,n+100);
        x(i,n+200) <-- y(i,n), if *n < 400000;  
    }
    let mut prog = AscentProgram::default();
    fn time(prog: &mut AscentProgram, title: &str) {
        let start = Instant::now();
        prog.run();
        println!("{:?} {:?}", prog.x.len(), prog.y.len());
        println!("{}", prog.scc_times_summary());
        println!("{}: {:?}",title, start.elapsed());
    }
    prog.x = vec![(0, 1,), (0, 101,)];
    time(&mut prog, "Initial run");

    prog.x.push((1,1,));    
    time(&mut prog,"Add of non-consequential fact");

    prog.x.push((1,101,));
    time(&mut prog,"Add of consequential fact");

    let mut prog = AscentProgram::default();
    prog.x = vec![(0, 1,), (0, 101,), (1,1,), (1,101)];
    time(&mut prog,"Full rerun");
}

The output is:

4002 4001
scc 0 time: 1.436391002s
  some of rule times: 1.42136186s
  rule x <-- y_indices_none_delta, if ⋯
    time: 4.024887ms
  rule y <-- x_indices_none_delta, x_indices_0_1_total+delta
    time: 2.227919ms
  rule y <-- x_indices_none_total, x_indices_0_1_delta
    time: 1.415109054s
-----------------------------------------

Initial run: 1.436422348s
4003 4001
scc 0 time: 1.443135223s
  some of rule times: 1.42810157s
  rule x <-- y_indices_none_delta, if ⋯
    time: 5.573965ms
  rule y <-- x_indices_none_delta, x_indices_0_1_total+delta
    time: 7.418424ms
  rule y <-- x_indices_none_total, x_indices_0_1_delta
    time: 1.415109181s
-----------------------------------------

Add of non-consequential fact: 9.375828ms
8004 8002
scc 0 time: 11.459918911s
  some of rule times: 11.423892339s
  rule x <-- y_indices_none_delta, if ⋯
    time: 12.857089ms
  rule y <-- x_indices_none_delta, x_indices_0_1_total+delta
    time: 17.993869ms
  rule y <-- x_indices_none_total, x_indices_0_1_delta
    time: 11.393041381s
-----------------------------------------

Add of consequential fact: 10.019436059s
8004 8002
scc 0 time: 3.073175727s
  some of rule times: 3.047507618s
  rule x <-- y_indices_none_delta, if ⋯
    time: 7.811237ms
  rule y <-- x_indices_none_delta, x_indices_0_1_total+delta
    time: 4.606486ms
  rule y <-- x_indices_none_total, x_indices_0_1_delta
    time: 3.035089895s
-----------------------------------------

Full rerun: 3.073211278s

It seems to me that:

  • running after adding to the input relation sometimes (my second run), does a lot less work than a full rerun.
  • at other times, when a lot of new facts were implied by the new fact, it does more work than a full rerun.

While (as I expected), removing facts from relations isn't supported.

 ascent!{
        struct A;
        relation x(u64);
        relation y(u64);
        y(n) <-- x(n);
    }
    let mut prog = A::default();
    prog.x = vec![(1,), (2,)];
    prog.run();
    println!("{:?}", prog.y);
    prog.x = vec![(1,)];
    prog.run();
    println!("{:?}", prog.y)

produces
[(1,), (2,)]
[(1,), (2,)]

My question is, would it be possible to either:

  • add some support for incrmentalized computation, so that you could indicate 'I've added facts to this relation' and 'I've removed facts from this relation', causing some of the indices to be recomputed?
  • prevent the user from calling .run() multiple times, by making run take ownership of the program instead of taking it by mutable reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions