Skip to content

WIP: ConcurrentCache for thread-safe caching of data

Summary

A caching data-structure is added. It is thread-safe and allows to configure the locality of the data (thread local or global).

Motivation

In several places of e.g. finite-element code cache is a route to performance, e.g. caching of quadrature rules, caching of evaluation of local basis function or gradient of local basis functions. This caching needs to associate a key to the stored values, where the key identifies uniquely the data that is cached. For quadrature rules, the key could be a tuple of (GeometryType, order, QuadratureType), for local basis evaluations a combination of GeometryType and QuadratureRule or local coordinates is possible.

The stored data needs to be initialized, e.g. the quadrature points and weights need to be stored in a container, or the local basis must be evaluated at the quadrature points or the given coordinates. And, this initialization should be performed only once. When you call get() on the cache the key and an initializer functor must be provided. This functor is evaluated only once to create a new data element.

Each specific cache needs to store the ConcurrentCache with a unique Key or Data type to distinguish different caches.

Example

Caching shape-function values of coordinates for a fixed LocalBasisType could be implemented in the following way:

template <class LocalBasisType>
class LocalBasisCache
{
  using Traits = typename LocalBasisType::Traits;
  using DomainType = typename Traits::DomainType;
  using RangeType = typename Traits::RangeType;

  struct Key : std::tuple<unsigned int, DomainType>
  {
    using std::tuple<unsigned int, DomainType>::tuple;
    friend std::size_t hash_value(Key const& t) { /* ... */ }
    friend bool operator==(Key const& lhs, Key const& rhs) { /* ... */ }
  };

public:
  using ShapeValues = std::vector<RangeType>;

  template <class Element>
  static ShapeValues const& evaluateFunction(LocalBasisType const& localBasis, 
                                             Element const& element, 
                                             DomainType const& local)
  {
    Key key{{element.type().id(),local}};
    return ShapeValuesCache::get(key, [&](Key const&)
    {
      ShapeValues data;
      localBasis.evaluateFunction(local, data);
      return data;
    });
  }

private:
  using ShapeValuesCache = ConcurrentCache<Key, ShapeValues>;
};

DUNE_DEFINE_HASH(DUNE_HASH_TEMPLATE_ARGS(class LocalBasisType), DUNE_HASH_TYPE(typename LocalBasisCache<LocalBasisType>::Key))

Discussion

  • Add policy for TBB concurrent_has_map?

TODO:

  • Fix thread_local policy to call functor only if necessary.
Edited by Simon Praetorius

Merge request reports