Advice on distributed vector design and separation of memory model from algorithmic implementation in C++

Viewed 61

So, we are working on a C++ math application designed for distributed memory systems (so typically some supercomputer with homogeneous nodes) and I have the following problem:

Currently, we have a implementation of a distributed vector (in the math sense), which is a tree-like structure of our second local vector class: pretty much being just a std::vector with some operations on top. Both vectors are template classes and inherit from some abstract math vector interface. I wrote some quick code below.

template<typenname T>
class AbstractVector {

   public:
   T one_norm() const = 0;
   ...
}

template<typename T>
class LocalVector : public AbstractVector<T> {

   private:
   std::vector<T> storage;
   ...
   public:
   T one_norm() const;
   ...
}

template<typename T>
class DistributedVector : AbstractVector<T> {
   
   private:
   AbstractVector<T>* children;
   ...
   public:
   T one_norm() const;
   ...

}

Now this all works well until I want to save certain attributes associated with the entries of my numerical vectors - so I would have e.g. one numerical vector and one that does not allow for computations at all but is just sort-of a storage of something.

Since the distributed math vector directly implements both, its storage model and the abstract vector interface, I cannot just use it for some random type since most of the numerical operations would not be defined for that type (e.g. "+" and "-" and "*") and would also not make any sense. Best example might even be a DistributedVector<bool> which does not make sense in the math vector but is totally reasonable else.

I think the design flaw is exactly that the concept of the distributed storage and its math implementation are not separated from each other (like in the local vector where I have the storage std::vector and the wrapper around it).

My question is - what is the nicest way to do better?

My first idea:

Ok, separate the concerns, have some kind of a distributed version of the std::vector and use that in the distributed math-vector as storage. The distributed math-vector would thus just be some kind of wrapper - or rather a decorator (the design pattern that came to my mind here) and provide the additional functionality that a math distributed vector would need. Here I am not sure - should I let the math distributed vector inherit from both - the distributed storage and the abstract vector interface? Or is the nicer way similar to the local vector where the distributed math vector just owns a distributed storage and works on that?

Maybe there is also better design that I am missing, this is why I am asking here :)

I don't have any functional restrictions on the C++ standard I am using - but I my refactoring should not break everything possibly.

Thanks in advance!

0 Answers
Related