mercredi 27 février 2019

Efficient multi-row vector

I need an efficient implementation of a vector with multiple rows, each having the same number of columns, which is not too ugly in C++. Currently I have the following:

class BaseVector {
protected: // variables
  int64_t _capacity;
  int64_t _nColumns;

protected:
  template<typename taItem> void Allocate(taItem * &p, const int64_t nItems) {
    p = static_cast<taItem*>(MemPool::Instance().Acquire(sizeof(taItem)*nItems));
    if (p == nullptr) {
      __debugbreak();
    }
  }
  template<typename taItem> void Reallocate(taItem * &p, const int64_t newCap) {
    taItem *np;
    Allocate(np, newCap);
    Utils::AlignedNocachingCopy(np, p, _nColumns * sizeof(taItem));
    MemPool::Instance().Release(p, _capacity * sizeof(taItem));
    p = np;
  }
  // Etc for Release() operation

public:
  explicit BaseVector(const int64_t initCap) : _capacity(initCap), _nColumns(0) { }
  void Clear() { _nColumns = 0; }
  int64_t Size() const { return _nColumns; }
};

class DerivedVector : public BaseVector {
    __m256d *_pRowA;
    __m256i *_pRowB;
    uint64_t *_pRowC;
    uint8_t *_pRowD;
    // Etc. for other rows
public:
    DerivedVector(const int64_t nColumns) : BaseVector(nColumns) {
        Allocate(_pRowA, nColumns);
        Allocate(_pRowB, nColumns);
        Allocate(_pRowC, nColumns);
        Allocate(_pRowD, nColumns);
        // Etc. for the other rows
    }
    void IncSize() {
        if(_nColumns >= _capacity) {
            const int64_t newCap = _capacity + (_capacity >> 1) + 1;
            Reallocate(_pRowA, newCap);
            Reallocate(_pRowB, newCap);
            Reallocate(_pRowC, newCap);
            Reallocate(_pRowD, newCap);
            // Etc. for other rows
            _capacity = newCap;
        }
        _nColumns++; 
    }
    ~DerivedVector() {
        // Call here the Release() operation for all rows
    }
};

The problem with this approach is that there can be 30 rows, so I have to type manually (and repeat myself) 30 times Allocate, 30 times Reallocate, 30 times Release, etc.

So is there a way in C++ to keep this code DRY and fast? I am ok with macros, but not heavy polymorphism in each access to a cell in the vector because this would kill performance.

Aucun commentaire:

Enregistrer un commentaire