lumol icon indicating copy to clipboard operation
lumol copied to clipboard

Cache computed physical properties

Open Luthaf opened this issue 10 years ago • 2 comments

Universe properties (Forces, KineticEnergy, ...) can be expensive to compute. It would be nice to cache them.

But there are two difficult things in CS: naming and cache invalidation. Because these properties can be accessed at any point in the simulation, the Universe::step field is a very bad cache indicator. A better one will be harder to compute and use, so I will have to think wether this is worth the gain or not.

Luthaf avatar Oct 05 '15 19:10 Luthaf

A way to do that would be to wrap the particles array in a BorrowCounter<T> struct like

struct<T> BorrowCounter<T> {
    val: T,
    const_counter: usize,
    mut_counter: usize,
}

impl<T> BorrowCounter<T> {
     pub fn borrow(&self) -> &T {
         const_counter.wrapping_add(1);
         &self.val
     }

     pub fn borrow_mut(&mut self) -> &mut T {
         mut_counter.wrapping_add(1);
         &mut self.val
     }

    pub fn const_count(&self) -> usize {self.const_counter}

    pub fn mut_count(&self) -> usize {self.mut_counter}
}

Then BorrowCounter<T>::mut_count will be a good hash value.

Deref and like traits can help adding some syntactic sugar.

Luthaf avatar Nov 09 '15 13:11 Luthaf

The borrow counter introduced in ad1f1db0f4e5e62e35444d5909859508ec85c699 was then removed in 6468edb1cf674758cb22b8cc9bdf41cc10c9559c, but this is still desirable to have. Thus reopening the issue.

The best way I see to fix this is to have a cache caching hash | data pairs, where hash is the hash of the data used by the Compute algorithm. We could add a fn hash(&self, system: &System) -> Option<u64> to the Control trait, and then use this to know whether we need to recompute some data.

impl Compute for Forces {
    fn hash(&self, system: &System) -> Option<u64> {
          // hash positions and cell, but not velocities
         return Some(hash)
    }
}

struct System {
    // ....
    cache: struct {
        forces: struct {
            data: Vec<Vector3D>,
            hash: u64,
        }
    }
}

impl System {
    fn forces(&self) -> &[Vector3D] {
        if Forces.hash(self).unwrap() != self.cache.forces.hash {
            self.cache.forces.data = Forces.compute(&self)
        }
        return &self.cache.forces;
    } 
}

Luthaf avatar Oct 12 '17 14:10 Luthaf