Commit e883abef authored by KLOCZKO Thibaud's avatar KLOCZKO Thibaud
Browse files

Enhance dtkDistributedArray to improve both API and performance.

parent 562e4e88
......@@ -19,13 +19,7 @@ set(${PROJECT_NAME}_HEADERS
dtkDistributed.h
dtkDistributedArray.h
dtkDistributedArray.tpp
dtkDistributedArrayHandler.h
dtkDistributedArrayHandler.tpp
dtkDistributedArrayItem.h
dtkDistributedCommunicator.h
dtkDistributedContainer.h
dtkDistributedContainerIndexed.h
dtkDistributedContainerSequence.h
dtkDistributedMapper.h
dtkDistributedPolicy.h
dtkDistributedSettings
......
#include "dtkDistributed.h"
#include "dtkDistributedCommunicator.h"
#include "dtkDistributedContainer.h"
#include "dtkDistributedMapper.h"
#include "dtkDistributedSettings.h"
......@@ -14,61 +14,238 @@
#pragma once
#include "dtkDistributedContainerIndexed.h"
#include "dtkDistributedContainerSequence.h"
#include "dtkDistributedArrayHandler.h"
#include "dtkDistributedArrayItem.h"
#include "dtkDistributedMapper.h"
#include "dtkDistributedWorker.h"
class dtkDistributedMapper;
class dtkDistributedWorker;
// /////////////////////////////////////////////////////////////////
// dtkDistributedContainer interface
// /////////////////////////////////////////////////////////////////
class dtkDistributedContainer
{
public:
virtual ~dtkDistributedContainer(void) { ; }
public:
virtual void setMode(const dtkDistributed::Mode& mode) = 0;
};
// /////////////////////////////////////////////////////////////////
// dtkDistributedArray interface
// /////////////////////////////////////////////////////////////////
template<typename T> class dtkDistributedArray : public dtkDistributedContainerIndexed<T>, public dtkDistributedContainerSequence<T>
template<typename T> class dtkDistributedArray : public dtkDistributedContainer
{
public:
inline dtkDistributedArray(const qlonglong& count, dtkDistributedWorker *worker);
inline ~dtkDistributedArray(void);
public:
inline void setMode(const dtkDistributed::Mode& mode);
class handler
{
protected:
friend class dtkDistributedArray<T>;
qlonglong buffer_count;
T *buffer;
public:
inline handler(dtkDistributedArray<T>& array) : buffer(0), buffer_count(0) {;}
inline virtual ~handler(void) {;}
public:
inline virtual bool empty(void) const { return !buffer_count; }
inline virtual qlonglong count(void) const { return buffer_count; }
inline virtual void setAt(const qlonglong& index, const T& value) { buffer[index] = value; }
inline virtual T at(const qlonglong& index) const { return buffer[index]; }
inline virtual T first(void) const { return buffer[0]; }
inline virtual T last(void) const { return buffer[buffer_count-1]; }
};
friend class handler;
public:
inline void clear(void);
public:
inline bool empty(void) const;
private:
class global_handler : public handler
{
friend class dtkDistributedArray<T>;
using dtkDistributedArray<T>::handler::buffer;
dtkDistributedMapper *m_mapper;
dtkDistributedCommunicator *m_comm;
qlonglong m_count;
qlonglong m_wid;
qlonglong buffer_id;
public:
global_handler(dtkDistributedArray<T>& array) : handler(array) {;}
~global_handler(void) {;}
public:
inline bool empty(void) const { return !m_count; }
inline qlonglong count(void) const { return m_count; }
inline void setAt(const qlonglong& index, const T& value)
{
qint32 owner = static_cast<qint32>(m_mapper->owner(index));
qlonglong pos = m_mapper->globalToLocal(index);
m_comm->put(owner, pos, &(const_cast<T&>(value)), buffer_id);
}
inline T at(const qlonglong& index) const
{
qint32 owner = static_cast<qint32>(m_mapper->owner(index));
qlonglong pos = m_mapper->globalToLocal(index);
if (m_wid == owner) {
return buffer[pos];
} else {
T temp;
m_comm->get(owner, pos, &temp, buffer_id);
return temp;
}
}
inline T first(void) const { return this->at(0); }
inline T last(void) const { return this->at(m_count-1); }
};
friend class global_handler;
public:
inline qlonglong count(void) const;
class item
{
friend class dtkDistributedArray<T>::iterator;
dtkDistributedArray<T>::handler *h;
qlonglong id;
public:
inline item(void) : h(0), id(0) {;}
inline item(dtkDistributedArray<T>::handler *handler, const qlonglong& index) : h(handler), id(index) {;}
inline item(const item& o) : h(o.h), id(o.id) {;}
inline ~item(void) {;}
public:
inline item& operator = (const item& o) { h = o.h; id = o.id; return *this; }
public:
inline T operator * (void) const { return h->at(id); }
inline item& operator = (const T& value) { h->setAt(id, value); return *this; }
inline item& operator += (const T& value) { h->setAt(id, h->at(id) + value); return *this; }
inline item& operator -= (const T& value) { h->setAt(id, h->at(id) - value); return *this; }
inline item& operator *= (const T& value) { h->setAt(id, h->at(id) * value); return *this; }
inline item& operator /= (const T& value) { h->setAt(id, h->at(id) / value); return *this; }
inline bool operator == (const item &o) const { return id == o.id; }
inline bool operator != (const item &o) const { return id != o.id; }
inline bool operator < (const item &o) const { return id < o.id; }
inline bool operator > (const item &o) const { return id > o.id; }
inline bool operator <= (const item &o) const { return id <= o.id; }
inline bool operator >= (const item &o) const { return id >= o.id; }
private:
item& operator ++ (void) { ++id; return *this; }
item& operator -- (void) { --id; return *this; }
item operator ++ (int) { ++id; return item(h, id-1); }
item operator -- (int) { --id; return item(h, id+1); }
};
friend class item;
class iterator
{
friend class const_iterator;
item it;
public:
inline iterator(void) : it(item()) {;}
inline iterator(dtkDistributedArray<T>::handler *handler, const qlonglong& index = 0) : it(handler, index) {;}
inline iterator(const iterator& o) : it(o.it) {;}
inline ~iterator(void) {;}
public:
inline iterator& operator = (const iterator& o) { it = o.it; }
public:
inline item operator * (void) const { return it; }
inline item operator [] (qlonglong j) const { return item(it.h, it.id + j); }
inline bool operator == (const iterator &o) const { return it == o.it; }
inline bool operator != (const iterator &o) const { return it != o.it; }
inline bool operator < (const iterator &o) const { return it < o.it; }
inline bool operator > (const iterator &o) const { return it > o.it; }
inline bool operator <= (const iterator &o) const { return it <= o.it; }
inline bool operator >= (const iterator &o) const { return it >= o.it; }
inline iterator& operator ++ (void) { ++it; return *this; }
inline iterator operator ++ (int) { ++it; return iterator(it.h, it.id-1); }
inline iterator& operator -- (void) { --it; return *this; }
inline iterator operator -- (int) { --it; return iterator(it.h, it.id+1); }
inline iterator& operator += (qlonglong j) { it.id += j; return *this; }
inline iterator& operator -= (qlonglong j) { it.id -= j; return *this; }
inline iterator operator + (qlonglong j) const { return iterator(it.h, it.id + j); }
inline iterator operator - (qlonglong j) const { return iterator(it.h, it.id - j); }
inline qlonglong operator - (const iterator& o) const { return it.id - o.it.id; }
};
friend class iterator;
public:
inline void set(const qlonglong& index, const T& value);
class const_iterator
{
const dtkDistributedArray<T>::handler *h;
qlonglong id;
public:
inline const_iterator(void) : h(0), id(0) {;}
inline const_iterator(const dtkDistributedArray<T>::handler *handler, const qlonglong& index = 0) : h(handler), id(index) {;}
inline const_iterator(const const_iterator& o) : h(o.h), id(o.id) {;}
explicit inline const_iterator(const iterator& o) : h(o.h), id(o.id) {;}
inline ~const_iterator(void) {;}
public:
inline const_iterator& operator = (const const_iterator& o) { h = o.h; id = o.id; }
public:
inline T operator * (void) const { return h->at(id); }
inline T operator [] (qlonglong j) const { return h->at(id + j); }
inline bool operator == (const const_iterator &o) const { return id == o.id; }
inline bool operator != (const const_iterator &o) const { return id != o.id; }
inline bool operator < (const const_iterator &o) const { return id < o.id; }
inline bool operator > (const const_iterator &o) const { return id > o.id; }
inline bool operator <= (const const_iterator &o) const { return id <= o.id; }
inline bool operator >= (const const_iterator &o) const { return id >= o.id; }
inline const_iterator& operator ++ (void) { ++id; return *this; }
inline const_iterator operator ++ (int) { ++id; return const_iterator(h, id-1); }
inline const_iterator& operator -- (void) { --id; return *this; }
inline const_iterator operator -- (int) { --id; return const_iterator(h, id+1); }
inline const_iterator& operator += (qlonglong j) { id += j; return *this; }
inline const_iterator& operator -= (qlonglong j) { id -= j; return *this; }
inline const_iterator operator + (qlonglong j) const { return const_iterator(h, id + j); }
inline const_iterator operator - (qlonglong j) const { return const_iterator(h, id - j); }
inline qlonglong operator - (const const_iterator& o) const { return id - o.id; }
};
friend class const_iterator;
public:
inline T at(const qlonglong& index) const;
private:
void initialize(void);
public:
inline T first(void) const;
inline T last(void) const;
inline void setMode(const dtkDistributed::Mode& mode);
public:
inline dtkDistributedArrayItem<T> operator [] (const qlonglong& index);
inline bool empty(void) const { return m_handler->empty(); }
inline qlonglong count(void) const { return m_handler->count(); }
inline void setAt(const qlonglong& index, const T& value) { m_handler->setAt(index, value); }
inline T at(const qlonglong& index) const { return m_handler->at(index); }
inline T first(void) const { return m_handler->first(); }
inline T last(void) const { return m_handler->last(); }
inline item itemAt(const qlonglong& index) { return item(m_handler, index); }
inline item operator [] (const qlonglong& index) { return item(m_handler, index); }
public:
inline dtkDistributedIterator<T> iterator(void);
inline iterator begin(void) { return iterator(m_handler, 0); }
inline const_iterator begin(void) const { return const_iterator(m_handler, 0); }
inline const_iterator cbegin(void) const { return const_iterator(m_handler, 0); }
inline const_iterator constBegin(void) const { return const_iterator(m_handler, 0); }
inline iterator end(void) { return iterator(m_handler, this->count()); }
inline const_iterator end(void) const { return const_iterator(m_handler, this->count()); }
inline const_iterator cend(void) const { return const_iterator(m_handler, this->count()); }
inline const_iterator constEnd(void) const { return const_iterator(m_handler, this->count()); }
public:
inline qlonglong localToGlobal(const qlonglong& index);
public:
dtkDistributedArrayHandler<T> *m_handler;
friend class dtkDistributedArrayHandler<T>;
handler *m_handler;
handler m_local_handler;
global_handler m_global_handler;
private:
qlonglong m_count;
qlonglong m_wid;
qlonglong buffer_id;
qlonglong buffer_count;
private:
T *buffer;
private:
dtkDistributedMapper *m_mapper;
dtkDistributedWorker *m_worker;
dtkDistributedCommunicator *m_comm;
};
// ///////////////////////////////////////////////////////////////////
......
......@@ -12,10 +12,9 @@
*
*/
//#prama once
#include "dtkDistributed.h"
#include "dtkDistributedArrayItem.h"
#include "dtkDistributedMapper.h"
#include "dtkDistributedWorker.h"
class dtkDistributedCommunicator;
......@@ -23,79 +22,61 @@ class dtkDistributedCommunicator;
//
// /////////////////////////////////////////////////////////////////
template<typename T> dtkDistributedArray<T>::dtkDistributedArray(const qlonglong& count, dtkDistributedWorker *worker) : m_handler(new dtkDistributedArrayHandler<T>(this, count, worker))
template<typename T> dtkDistributedArray<T>::dtkDistributedArray(const qlonglong& count, dtkDistributedWorker *worker) : m_handler(0), m_local_handler(*this), m_global_handler(*this), m_wid(worker->wid()), m_count(count), m_mapper(new dtkDistributedMapper), m_worker(worker), m_comm(worker->communicator())
{
this->initialize();
}
template<typename T> dtkDistributedArray<T>::~dtkDistributedArray(void)
{
if (m_handler)
delete m_handler;
}
m_comm->deallocate(m_wid, buffer_id);
template <typename T> void dtkDistributedArray<T>::setMode(const dtkDistributed::Mode& mode)
{
switch(mode) {
case dtkDistributed::Local:
m_handler->setLocalMode();
break;
case dtkDistributed::Global:
m_handler->setGlobalMode();
break;
default:
m_handler->setGlobalMode();
break;
}
}
template<typename T> void dtkDistributedArray<T>::clear(void)
{
return m_handler->clear();
}
template<typename T> bool dtkDistributedArray<T>::empty(void) const
{
return m_handler->empty();
}
m_worker->unrecord(this);
template<typename T> qlonglong dtkDistributedArray<T>::count(void) const
{
return m_handler->count();
if (m_mapper)
delete m_mapper;
}
template<typename T> void dtkDistributedArray<T>::set(const qlonglong& index, const T& value)
template<typename T> void dtkDistributedArray<T>::initialize(void)
{
m_handler->set(index, value);
}
m_worker->record(this);
this->setMode(dtkDistributed::mode());
template<typename T> T dtkDistributedArray<T>::at(const qlonglong& index) const
{
return m_handler->at(index);
}
m_mapper->setMapping(m_count, m_comm->size());
buffer_count = m_mapper->count(m_wid);
buffer_id = m_worker->containerId(this);
template<typename T> T dtkDistributedArray<T>::first(void) const
{
return m_handler->first();
}
buffer = static_cast<T*>(m_comm->allocate(buffer_count, sizeof(T), m_wid, buffer_id));
template<typename T> T dtkDistributedArray<T>::last(void) const
{
return m_handler->last();
}
m_local_handler.buffer_count = buffer_count;
m_local_handler.buffer = buffer;
template<typename T> dtkDistributedArrayItem<T> dtkDistributedArray<T>::operator [] (const qlonglong& index)
{
return dtkDistributedArrayItem<T>(this, index);
m_global_handler.m_count = m_count;
m_global_handler.m_wid = m_wid;
m_global_handler.buffer_id = buffer_id;
m_global_handler.buffer_count = buffer_count;
m_global_handler.buffer = buffer;
m_global_handler.m_mapper = m_mapper;
m_global_handler.m_comm = m_comm;
}
template<typename T> dtkDistributedIterator<T> dtkDistributedArray<T>::iterator(void)
template <typename T> void dtkDistributedArray<T>::setMode(const dtkDistributed::Mode& mode)
{
return m_handler->iterator();
switch(mode) {
case dtkDistributed::Local:
m_handler = &m_local_handler;
break;
case dtkDistributed::Global:
m_handler = &m_global_handler;
break;
default:
m_handler = &m_global_handler;
break;
}
}
template<typename T> qlonglong dtkDistributedArray<T>::localToGlobal(const qlonglong& index)
template<typename T> qlonglong dtkDistributedArray<T>::localToGlobal(const qlonglong& index)
{
return m_handler->localToGlobal(index);
return m_mapper->localToGlobal(index, m_wid);
}
/* dtkDistributedArrayHandler.h ---
*
* Author: Thibaud Kloczko
* Created: 2013 Mon Feb 18 10:24:22 (+0100)
*/
/* Commentary:
*
*/
/* Change log:
*
*/
#pragma once
template <typename T> class dtkDistributedArray;
template <typename T> class dtkDistributedArrayHandler;
class dtkDistributedCommunicator;
class dtkDistributedMapper;
class dtkDistributedWorker;
// /////////////////////////////////////////////////////////////////
//
// /////////////////////////////////////////////////////////////////
template <typename T> class dtkDistributedArrayHandler
{
public:
inline dtkDistributedArrayHandler(dtkDistributedArray<T> *array, const qlonglong& count, dtkDistributedWorker *worker);
inline ~dtkDistributedArrayHandler(void);
public:
void initialize(void);
public:
inline void setLocalMode(void);
inline void setGlobalMode(void);
public:
inline void clear(void);
inline bool empty(void) const;
inline qlonglong count(void) const;
public:
inline void set(const qlonglong& index, const T& value);
public:
inline T at(const qlonglong& index) const;
public:
inline T first(void) const;
inline T last(void) const;
public:
inline dtkDistributedIterator<T> iterator(void);
public:
inline qlonglong localToGlobal(const qlonglong& index);
// /////////////////////////////////////////////////////////////////
protected:
typedef void (dtkDistributedArrayHandler<T>::*clearMethodPointer)(void);
typedef bool (dtkDistributedArrayHandler<T>::*emptyMethodPointer)(void) const;
typedef qlonglong (dtkDistributedArrayHandler<T>::*countMethodPointer)(void) const;
protected:
clearMethodPointer clearMethod;
emptyMethodPointer emptyMethod;
countMethodPointer countMethod;
protected:
void clearLocal(void) { qDebug() << "I am locally cleared"; }
void clearGlobal(void) { qDebug() << "I am globally cleared"; }
bool emptyLocal(void) const { return !static_cast<bool>(m_buffer_count); }
bool emptyGlobal(void) const { return !static_cast<bool>(m_count); }
qlonglong countLocal(void) const { return m_buffer_count; }
qlonglong countGlobal(void) const { return m_count; }
// /////////////////////////////////////////////////////////////////
protected:
typedef void (dtkDistributedArrayHandler<T>::*setMethodPointer)(const qlonglong& index, const T& value);
typedef T (dtkDistributedArrayHandler<T>::*atMethodPointer)(const qlonglong& index) const;
typedef T (dtkDistributedArrayHandler<T>::*atLimitMethodPointer)(void) const;
protected:
setMethodPointer setMethod;
atMethodPointer atMethod;
atLimitMethodPointer firstMethod;
atLimitMethodPointer lastMethod;
protected:
void setLocal(const qlonglong& index, const T& value) { m_buffer[index]= value; }
void setGlobal(const qlonglong& index, const T& value);
T atLocal(const qlonglong& index) const { return m_buffer[index]; }
T atGlobal(const qlonglong& index) const;
T firstLocal(void) const { return *(m_buffer); }
T firstGlobal(void) const { return this->atGlobal(0); }
T lastLocal(void) const { return *(m_buffer + m_buffer_count - 1); }
T lastGlobal(void) const { return this->atGlobal(m_count - 1); }
// /////////////////////////////////////////////////////////////////
private:
qlonglong m_wid;
qlonglong m_count;
qlonglong m_buffer_id;
qlonglong m_buffer_count;
T *m_buffer;
// /////////////////////////////////////////////////////////////////
private:
dtkDistributedMapper *m_mapper;
dtkDistributedWorker *m_worker;
dtkDistributedCommunicator *m_comm;
private:
friend class dtkDistributedArray<T>;
dtkDistributedArray<T> *m_array;
};
// ///////////////////////////////////////////////////////////////////
// dtkDistributedIteratorArrayLocal interface
// ///////////////////////////////////////////////////////////////////
template<typename T> class dtkDistributedIteratorArrayPrivate : public dtkDistributedIteratorPrivate<T>
{
public:
dtkDistributedArrayHandler<T>& h;
qlonglong id;
public:
inline dtkDistributedIteratorArrayPrivate(dtkDistributedArrayHandler<T>& handler) : h(handler), id(0) {;}
inline ~dtkDistributedIteratorArrayPrivate(void) {;}
public:
inline void toFirst(void) { id = 0; }
inline void toLast(void) { id = h.count(); }
inline void toNext(void) { ++id; }
inline void toPrevious(void) { --id; }
public:
inline bool hasNext(void) { return ( id < h.count() ); }
inline bool hasPrevious(void) { return ( id > 0); }
public:
inline qlonglong index(void) { return id; }
public:
inline T current(