Skip to content

ublas_feature0007_distributed

Nasos edited this page May 28, 2013 · 10 revisions

This is the ublas distributed project for GSOC 2013.

Planned interface:

Initialization:

using   std::make_shared;
using   namespace boost;
using   namespace boost::numeric;

If using more than one controllers:

// Setup the mpi environmnet and a comminucator
auto    env =   make_shared<mpi::environment>( argc, argv );
auto    world = make_shared< mpi::communicator >( );

// Setup an ublas::distriburted controller
auto  cntrl =   make_shared<ublas::distributed::controller>( env, world ); 

If using only one controller:

auto  cntrl = make_shared<ublas::distributed::controller>(); 

Basic interface:

Local access:

ublas::distributed::vector<double>  a( cntrl, 20000 ), b( cntrl, 20000 ), c( cntrl, 20000 );

for (auto i = 0; i !=a.local_size(); i++) 
    b[i] = 2 * b.global(i) ; // operator[] fetches only local elements

for (auto i = 0; i !=a.local_size(); i++) 
    c[i] = 3 * c.global(i) ; // global(i) returns the global index of the local index i

a = 2 * b + 4 * c; // This will execute immediately on all processors. 

Local and global access:

// operator () is a lazy operator and fetches global elements
// Such operations are cached and will be executed upon flushing the controller

// Fetch to a POD
double v;
fetch( a(3), v );   //operator () is a lazy operator and fetches global elements 

// Fetch to a local vector
ublas::vector<double> d(20000);
for (auto i = 0; i!=100; i++) 
   d[ i ] = a( rand() % a.size() ); // The local element i will be set to the value of a random element

cntrl.flush()   // this will set v to a(3) and fill d with a random sequence of elements of a 

Other interface elements:

// Choosing distribution policy:

ublas::distributed::vector<double, ublas::distributed::cyclic>   e( cntrl, 20000); // The default policy is block 

Conceptual implementation:

/! The controller deals with lazy communication operations dispatch.
class controller {
    explicit controller() {
        if ( !mpi::environment::initialized() )
            // throw() // Some MPI implementations can be initialized without arguments. We don't allow that atm

        env_ =      make_shared< mpi::environment >( ); // The mpi environment will have be already initialized
        world_ =    make_shared< mpi::communicator >( );
    }

    controller(int &, char **&, bool = true) {
        if ( !mpi::environment::initialized() ) { // TODO Race issues here? Maybe request from boost::mpi init to be atomic
            env =       make_shared<mpi::environment>( argc, argv );
        } else {
           // throw(); // Cannot initialize with provided arguments, already initialized
        }
       world_ =    make_shared< mpi::communicator >( );
    }

    std::shared_ptr< mpi::environment > environment()   { return env_; }

    std::shared_ptr< mpi::world >       communicator()  { return comm_; }

private:
    std::shared_ptr< mpi::environment >     env_;
    std::shared_ptr< mpi::communicator >    comm_;
};