music-1.2.1/ 0000755 0005140 0005140 00000000000 14412627307 007634 5 0000000 0000000 music-1.2.1/src/ 0000755 0005140 0005140 00000000000 14412627306 010422 5 0000000 0000000 music-1.2.1/src/temporal.cc 0000644 0005140 0005140 00000036660 14372254427 012514 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/temporal.hh" // Must be included first on BG/L
//#define MUSIC_DEBUG
#if MUSIC_USE_MPI
#include "music/setup.hh"
namespace MUSIC
{
TemporalNegotiator::TemporalNegotiator (Setup* setup) :
setup_ (setup), negotiationBuffer (NULL)
{
nApplications_ = setup_->applicationMap ()->size ();
nAllConnections = 0;
nodes = new TemporalNegotiatorGraph (setup_->timebase (), nApplications_,
setup_->applicationColor ());
}
TemporalNegotiator::~TemporalNegotiator ()
{
delete nodes;
freeNegotiationData (negotiationBuffer);
// Free negotiation communicator in application leaders
if (negotiationComm != MPI_COMM_NULL)
MPI_Comm_free (&negotiationComm);
MPI_Group_free (&applicationLeaders);
MPI_Group_free (&groupWorld);
}
void
TemporalNegotiator::separateConnections (
std::vector* connections)
{
for (std::vector::iterator c = connections->begin ();
c != connections->end (); ++c)
{
if (dynamic_cast (*c) != NULL)
outputConnections.push_back (*dynamic_cast (*c));
else
inputConnections.push_back (*dynamic_cast (*c));
}
}
TemporalNegotiatorGraph*
TemporalNegotiator::applicationGraph ()
{
return nodes;
}
bool
TemporalNegotiator::isLeader ()
{
return mpi_get_rank (setup_->communicator ()) == 0;
}
bool
TemporalNegotiator::hasPeers ()
{
return mpi_get_comm_size (setup_->communicator ()) > 1;
}
void
TemporalNegotiator::createNegotiationCommunicator ()
{
ApplicationMap* applicationMap = setup_->applicationMap ();
int* ranks = new int[nApplications_];
for (int i = 0; i < nApplications_; ++i)
ranks[i] = (*applicationMap)[i].leader ();
MPI_Comm_group (MPI_COMM_WORLD, &groupWorld);
MPI_Group_incl (groupWorld, nApplications_, ranks, &applicationLeaders);
delete[] ranks;
MPI_Comm_create (MPI_COMM_WORLD, applicationLeaders, &negotiationComm);
}
int
TemporalNegotiator::negotiationDataSize (int nConnections)
{
return negotiationDataSize (1, nConnections);
}
int
TemporalNegotiator::negotiationDataSize (int nBlocks, int nConnections)
{
// -1 due to definition of connection member
return (nBlocks * sizeof(TemporalNegotiationData)
+ (nConnections - 1) * sizeof(ConnectionDescriptor));
}
TemporalNegotiationData*
TemporalNegotiator::allocNegotiationData (int nBlocks, int nConnections)
{
void* memory = new char[negotiationDataSize (nBlocks, nConnections)];
return static_cast (memory);
}
void
TemporalNegotiator::freeNegotiationData (TemporalNegotiationData* data)
{
if (data != NULL)
{
delete[] static_cast (static_cast (data));
data = NULL;
}
}
int
TemporalNegotiator::computeDefaultMaxBuffered (int maxLocalWidth,
int eventSize, ClockState tickInterval, double timebase)
{
int res;
// Do different calculation depending on the kind of port
// NOTE: We should not base this choice eventSize but instead on
// proper type information
if (eventSize == 0)
// continuous data
res = DEFAULT_PACKET_SIZE / maxLocalWidth;
else if (eventSize == 1)
// message data
res = DEFAULT_MESSAGE_MAX_BUFFERED;
else
// event data
res = (DEFAULT_PACKET_SIZE
/ (EVENT_FREQUENCY_ESTIMATE * maxLocalWidth * eventSize * timebase
* tickInterval));
if (res < 1)
res = 1;
return res;
}
int
TemporalNegotiator::findNodeColor (int leader)
{
int color = -1;
ApplicationMap* applicationMap = setup_->applicationMap ();
for (int i = 0; i < nApplications_; ++i)
if (leader == (*applicationMap)[i].leader ())
color = (*applicationMap)[i].color ();
assert (color != -1);
return color;
}
void
TemporalNegotiator::collectNegotiationData (ClockState ti)
{
int nOut = outputConnections.size ();
int nIn = inputConnections.size ();
nLocalConnections = nOut + nIn;
MUSIC_LOG ("nLocalConnections = " << nLocalConnections
<< ", nOut = " << nOut
<< ", nIn = " << nIn);
negotiationData = allocNegotiationData (1, nLocalConnections);
negotiationData->timebase = setup_->timebase ();
negotiationData->tickInterval = ti;
negotiationData->color = setup_->applicationColor ();
negotiationData->leader = setup_->leader ();
negotiationData->nProcs = setup_->nProcs ();
negotiationData->nOutConnections = outputConnections.size ();
negotiationData->nInConnections = inputConnections.size ();
for (int i = 0; i < nOut; ++i)
{
Connector* connector = outputConnections[i].connector ();
int remote = connector->remoteLeader ();
negotiationData->connection[i].remoteNode = findNodeColor (remote);
negotiationData->connection[i].receiverPort =
connector->receiverPortCode ();
negotiationData->connection[i].multiComm = connector->idFlag ();
negotiationData->connection[i].maxBuffered =
outputConnections[i].maxBuffered ();
negotiationData->connection[i].defaultMaxBuffered =
computeDefaultMaxBuffered (connector->maxLocalWidth (),
outputConnections[i].elementSize (), ti, setup_->timebase ());
negotiationData->connection[i].accLatency = 0;
}
for (int i = 0; i < nIn; ++i)
{
int remote = inputConnections[i].connector ()->remoteLeader ();
negotiationData->connection[nOut + i].remoteNode = findNodeColor (
remote);
negotiationData->connection[nOut + i].receiverPort =
inputConnections[i].connector ()->receiverPortCode ();
negotiationData->connection[nOut + i].multiComm =
inputConnections[i].connector ()->idFlag ();
negotiationData->connection[nOut + i].maxBuffered =
inputConnections[i].maxBuffered ();
negotiationData->connection[nOut + i].defaultMaxBuffered = 0;
negotiationData->connection[nOut + i].accLatency =
inputConnections[i].accLatency ();
MUSIC_LOGR ("port " << inputConnections[i].connector ()->receiverPortName () << ": " << inputConnections[i].accLatency ());
negotiationData->connection[nOut + i].interpolate =
inputConnections[i].interpolate ();
}
}
void
TemporalNegotiator::fillTemporalNegotiatorGraph ()
{
nodes->setNConnections (nAllConnections / 2);
char* memory = static_cast (static_cast (negotiationBuffer));
TemporalNegotiationData* data;
for (int i = 0; i < nApplications_; ++i)
{
data =
static_cast (static_cast (memory));
int nOut = data->nOutConnections;
int nIn = data->nInConnections;
nodes->addNode (
ANode (nOut, nIn,
*data), data->color);
memory += negotiationDataSize (nOut + nIn);
}
}
void
TemporalNegotiator::communicateNegotiationData ()
{
// First talk to others about how many connections each node has
int* nConnections = new int[nApplications_];
MPI_Allgather (&nLocalConnections, 1, MPI_INT, nConnections, 1,
MPI_INT, negotiationComm);
for (int i = 0; i < nApplications_; ++i)
nAllConnections += nConnections[i];
negotiationBuffer = allocNegotiationData (nApplications_, nAllConnections);
int* receiveSizes = new int[nApplications_];
int* displacements = new int[nApplications_];
int displacement = 0;
for (int i = 0; i < nApplications_; ++i)
{
int receiveSize = negotiationDataSize (nConnections[i]);
receiveSizes[i] = receiveSize;
displacements[i] = displacement;
displacement += receiveSize;
}
delete[] nConnections;
int sendSize = negotiationDataSize (nLocalConnections);
MPI_Allgatherv (negotiationData, sendSize, MPI_BYTE,
negotiationBuffer, receiveSizes, displacements, MPI_BYTE,
negotiationComm);
delete[] displacements;
delete[] receiveSizes;
freeNegotiationData (negotiationData);
fillTemporalNegotiatorGraph ();
}
ConnectionDescriptor*
TemporalNegotiator::findInputConnection (int node, int port)
{
int nOut = nodes->at (node).data ().nOutConnections;
// Get address of first input ConnectionDescriptor
ConnectionDescriptor* inputDescriptors =
&nodes->at (node).data ().connection[nOut];
for (int i = 0; i < nodes->at (node).data ().nInConnections; ++i)
if (inputDescriptors[i].receiverPort == port)
return &inputDescriptors[i];
error ("internal error in TemporalNegotiator::findInputConnection");
return 0; // never reached
}
void
TemporalNegotiator::combineParameters ()
{
double timebase = nodes->at (0).data ().timebase;
for (int o = 0; o < nApplications_; ++o)
{
// check timebase
if (nodes->at (o).data ().timebase != timebase)
error0 ("applications don't use same timebase");
for (int c = 0; c < nodes->at (o).data ().nOutConnections; ++c)
{
ConnectionDescriptor* out = &nodes->at (o).data ().connection[c];
int i = out->remoteNode;
ConnectionDescriptor* in = findInputConnection (i,
out->receiverPort);
// maxBuffered
// check defaults
if (out->maxBuffered == MAX_BUFFERED_NO_VALUE
&& in->maxBuffered == MAX_BUFFERED_NO_VALUE)
out->maxBuffered = out->defaultMaxBuffered;
else if (in->maxBuffered != MAX_BUFFERED_NO_VALUE)
{
// convert to sender side ticks
ClockState inMaxBufferedTime = in->maxBuffered
* nodes->at (i).data ().tickInterval;
int inMaxBuffered = (inMaxBufferedTime
/ nodes->at (o).data ().tickInterval);
// take min maxBuffered
if (out->maxBuffered == MAX_BUFFERED_NO_VALUE
|| inMaxBuffered < out->maxBuffered)
out->maxBuffered = inMaxBuffered;
}
// store maxBuffered in sender units
in->maxBuffered = out->maxBuffered;
MUSIC_LOG0("Max Buffered:"<maxBuffered);
// accLatency
out->accLatency = in->accLatency;
// interpolate
out->interpolate = in->interpolate;
// remoteTickInterval
out->remoteTickInterval = nodes->at (i).data ().tickInterval;
in->remoteTickInterval = nodes->at (o).data ().tickInterval;
}
}
}
void
TemporalNegotiator::distributeParameters ()
{
for (int o = 0; o < nApplications_; ++o)
{
for (int c = 0; c < nodes->at (o).data ().nOutConnections; ++c)
{
ConnectionDescriptor* out = &nodes->at (o).data ().connection[c];
int i = out->remoteNode;
ConnectionDescriptor* in = findInputConnection (i,
out->receiverPort);
// store maxBuffered in sender units
in->maxBuffered = out->maxBuffered;
}
}
}
void
TemporalNegotiator::loopAlgorithm ()
{
std::vector > path;
TemporalNegotiatorGraph::iterator it;
for (it = nodes->begin (); it < nodes->end (); ++it)
if (!it->visited)
nodes->depthFirst (*it, path);
}
void
TemporalNegotiator::broadcastNegotiationData ()
{
MPI_Comm comm = setup_->communicator ();
if (hasPeers ())
{
MPI_Bcast (&nAllConnections, 1, MPI_INT, 0, comm);
char* memory =
static_cast (static_cast (negotiationBuffer));
MPI_Bcast (memory, negotiationDataSize (nApplications_, nAllConnections), MPI_BYTE,
0, comm);
}
}
void
TemporalNegotiator::receiveNegotiationData ()
{
MPI_Comm comm = setup_->communicator ();
MPI_Bcast (&nAllConnections, 1, MPI_INT, 0, comm);
negotiationBuffer = allocNegotiationData (nApplications_, nAllConnections);
char* memory = static_cast (static_cast (negotiationBuffer));
MPI_Bcast (memory, negotiationDataSize (nApplications_, nAllConnections),
MPI_BYTE, 0,
comm);
fillTemporalNegotiatorGraph ();
}
void
TemporalNegotiator::negotiate (Clock& localTime,
std::vector* connections)
{
separateConnections (connections);
//MUSIC_LOGR (printconns ("NOut: ", outputConnections));
//MUSIC_LOGR (printconns ("NIn: ", inputConnections));
createNegotiationCommunicator ();
if (isLeader ())
{
collectNegotiationData (localTime.tickInterval ());
communicateNegotiationData ();
combineParameters ();
loopAlgorithm ();
distributeParameters ();
broadcastNegotiationData ();
}
else
receiveNegotiationData ();
}
void
TemporalNegotiatorGraph::handleLoop (
ANode &x,
std::vector > & path)
{
// Search path to detect beginning of loop
int loop;
for (loop = 0; &path[loop].pre () != &x; ++loop)
;
// Compute how much headroom we have for buffering
ClockState totalDelay = 0;
for (unsigned int c = loop; c < path.size (); ++c)
{
MUSIC_LOGR ("latency = " << path[c].data().accLatency << ", ti = "
<< path[c].pre ().data().tickInterval);
totalDelay += path[c].data ().accLatency
- path[c].pre ().data ().tickInterval;
}
// If negative we will not be able to make it in time
// around the loop even without any extra buffering
if (totalDelay < 0)
{
std::ostringstream ostr;
ostr << "too short latency (" << -timebase_ * totalDelay
<< " s) around loop: "; // << path[loop].pre().name();
for (unsigned int c = loop + 1; c < path.size (); ++c)
ostr << ", "; // << path[c].pre().name();
error0 (ostr.str ());
}
// Distribute totalDelay as allowed buffering uniformly over loop
// (we could do better by considering constraints form other loops)
int loopLength = path.size () - loop;
ClockState bufDelay = totalDelay / loopLength;
for (unsigned int c = loop; c < path.size (); ++c)
{
int allowedTicks = bufDelay / path[c].pre ().data ().tickInterval;
path[c].data ().maxBuffered = std::min (path[c].data ().maxBuffered,
allowedTicks);
}
}
void
TemporalNegotiatorGraph::setNConnections (int nConns)
{
nConnections_ = nConns;
}
int
TemporalNegotiatorGraph::getNConnections ()
{
return nConnections_;
}
}
#endif
music-1.2.1/src/collector.cc 0000644 0005140 0005140 00000007563 14372254427 012657 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2009, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/collector.hh"
#include "music/debug.hh"
#if MUSIC_USE_MPI
// collector.hh needs to be included first since it causes inclusion
// of mpi.h (in data_map.hh). mpi.h must be included before other
// header files on BG/L
#include
#include
#include "music/event.hh"
#include "music/mpi_utils.hh"
namespace MUSIC {
Collector::Interval::Interval (IndexInterval& interval)
{
setBegin (interval.begin ());
setLength (interval.end () - interval.begin ());
}
void
Collector::configure (DataMap* dmap, int maxsize)
{
dataMap = dmap;
maxsize_ = maxsize;
}
IntervalTree*
Collector::buildTree ()
{
IntervalTree* tree
= new IntervalTree ();
IndexMap* indices = dataMap->indexMap ();
for (IndexMap::iterator i = indices->begin ();
i != indices->end ();
++i)
{
MUSIC_LOGR ("adding (" << i->begin () << ", " << i->end ()
<< ", " << i->local () << ") to tree");
tree->add (*i, i->local ());
}
tree->build ();
return tree;
}
void
Collector::addRoutingInterval (IndexInterval interval, BIFO* buffer)
{
BufferMap::iterator b = buffers.find (buffer);
if (b == buffers.end ())
{
buffers.insert (std::make_pair (buffer, Intervals ()));
b = buffers.find (buffer);
}
Intervals& intervals = b->second;
intervals.push_back (Interval (interval));
}
void
Collector::IntervalCalculator::operator() (int& offset)
{
interval_.setBegin (elementSize_
* (interval_.begin () - offset));
interval_.setLength (elementSize_ * interval_.length ());
}
void
Collector::initialize ()
{
IntervalTree* tree = buildTree ();
for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
{
BIFO* buffer = b->first;
Intervals& intervals = b->second;
sort (intervals.begin (), intervals.end ());
int elementSize = mpi_get_type_size (dataMap->type ());
int size = 0;
for (Intervals::iterator i = intervals.begin ();
i != intervals.end ();
++i)
{
IntervalCalculator calculator (*i, elementSize);
MUSIC_LOGX ("searching for " << i->begin ());
tree->search (i->begin (), &calculator);
size += i->length ();
}
buffer->configure (size, maxsize_);
}
}
void
Collector::collect (ContDataT* base)
{
ContDataT* dest = static_cast (base);
for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
{
BIFO* buffer = b->first;
Intervals& intervals = b->second;
ContDataT* src = static_cast (buffer->next ());
if (src == NULL)
// Out of data (remote has flushed)
return;
for (Intervals::iterator i = intervals.begin ();
i != intervals.end ();
++i)
{
MUSIC_LOGX ("collect to dest = " << static_cast (dest)
<< ", begin = " << i->begin ()
<< ", length = " << i->length ());
memcpy (dest + i->begin (), src, i->length ());
src += i->length ();
}
}
}
void
Collector::collect ()
{
collect (static_cast (dataMap->base ()));
}
}
#endif
music-1.2.1/src/ChangeLog 0000644 0005140 0005140 00000102716 12652207070 012117 0000000 0000000 2013-07-09 Mikael Djurfeldt
* runtime.cc (Runtime::Runtime): Only create scheduling agents if
launched by MUSIC.
2012-09-26 Mikael Djurfeldt
* Makefile.am, connector.cc, event_router.cc, multibuffer.cc,
music/connectivity.hh, music/connector.hh, music/multibuffer.hh,
music/runtime.hh, music/scheduler.hh, music/subconnector.hh,
port.cc, runtime.cc, scheduler.cc, subconnector.cc: Implementation
of multiconnectors.
2012-09-15 Mikael Djurfeldt
* connector.cc (lessOutputSubconnector): Make less condition
consistent.
2012-09-14 Mikael Djurfeldt
* connector.cc (Connector::initialize): Sort input and output
subconnectors according to different criteria in order to obtain
the communication schedule described in Mikael Djurfeldt et
al. (2005) "Massively parallel simulation of brain-scale neuronal
network models."
* music/connector.hh (Connector::isInput)
(InputConnector::isInput): New member function.
* music/subconnector.hh (Subconnector::localRank): New member
function.
2012-09-08 Mikael Djurfeldt
* music/clock.hh, clock.cc (Clock::reset): New member function.
2012-09-04 Mikael Djurfeldt
* scheduler.cc (Scheduler::nextCommunication): Make sure that all
events from the first point in time are scheduled.
* music/scheduler.hh (SConnection): Renamed from Connection in
order not to be confused with connection.hh::Connection.
* connector.cc (Connector::isProxy): New member function.
* music/scheduler.hh, scheduler.cc (Scheduler::addConnection): New
argument multiComm.
(Scheduler::Connection): New member multiComm.
* music/temporal.hh, temporal.cc (ConnectionDescriptor): New
member multiComm.
(TemporalNegotiator::collectNegotiationData): Set multiComm.
(TemporalNegotiator::fillScheduler): Pass multiComm to
Scheduler::addConnection.
2012-09-03 Mikael Djurfeldt
* scheduler.cc (Scheduler::initialize): Setup ProxyConnector
representing a distant connection.
* music/scheduler.hh (Scheduler::Node): New member functions
leader and nProcs.
* music/scheduler.hh, scheduler.cc (Scheduler::addNode,
Scheduler::Node::Node): New arguments leader and nProcs.
* music/setup.hh, setup.cc (Setup::nProcs): New member function.
* music/temporal.hh (TemporalNegotiationData): Added new members
leader and nProcs.
* temporal.cc (TemporalNegotiator::collectNegotiationData): Set
leader and nProcs.
(TemporalNegotiator::fillScheduler): Pass leader and nProcs to
Scheduler::addNode.
* music/connector.hh (ProxyConnector): New class. These objects
will represent connections which the local application doesn't
participate in but still need to be aware of in order to schedule
common collective communication events.
2012-09-02 Mikael Djurfeldt
* music/event_router.hh, event_router.cc (DirectRouter): New
class.
* music/setup.hh, setup.cc (Setup::leader): Added selector.
* music/configuration.hh, configuration.cc
(Configuration::leader): Added selector.
2012-08-27 Mikael Djurfeldt
* music/spatial.hh, spatial.cc: Simplification made possible by
previous change.
* spatial.cc (SpatialNegotiator::send)
(SpatialNegotiator::receive): First send size of receive buffer in
order to avoid successive resizing. This is kinder to the memory
allocator.
2012-08-25 Mikael Djurfeldt
* music/memory.hh, memory.cc: New files.
* Makefile.am, runtime.cc: Report memory usage for world rank #0
using mallinfo.
* music/runtime.hh, runtime.cc, music/connector.hh: Initial
support for MultiConnector:s. MultiConnector is an object
governing simultaneous communication through a set of
Connector:s.
* runtime.cc, music/connector.hh, music/subconnector.hh: Added
some debugging/analysis code.
2012-08-23 Mikael Djurfeldt
* music/scheduler.hh (Scheduler::Node::outputConnections),
scheduler.cc: Pass outputConnections as a pointer rather than as a
vector.
* event_routing_map.cc (OutputRoutingMap::fillRouter): Bugfix:
return -> continue.
* interval.cc: New file.
* music/interval.hh: Make Interval:s printable.
* music/music-config.hh-in: (and many other files) Some #include
reorganization: Let those who need it include music-config.hh as
the common first header file.
* music/ordered_ilist.hh (OrderedIList::iterator): Satisfy BG/P
compiler which complained that an OrderedIList member creates a
circular reference with respect to type.
2012-08-22 Mikael Djurfeldt
* music/port.hh, port.cc (Port::checkIndexMap): New member.
* port.cc (OutputPort::mapImpl, InputPort::mapImpl: Use
checkIndexMap.
* event_routing_map.cc (OutputRoutingMap::fillRouter): Ask
EventRouter if it needs as few points as possible rather than as
few intervals as possible, and close gaps only in the latter case.
This is important when using the new table based routing together
with simulators with round-robin allocation, such as NEST.
* music/event_router.hh: Let table based routers say that they
need few points rather than intervals.
2012-08-21 Mikael Djurfeldt
* music/interval_table.hh, music/ordered_ilist.hh: Introduced an
interval table optimization variable MUSIC_ITABLE_FLAVOR with the
options MUSIC_VANILLA, MUSIC_TRIMMED, MUSIC_COMPACT and
MUSIC_SCATTERED explained at the top of music/interval_table.hh.
* music/event_router.hh: #define MUSIC_ITABLE_FLAVOR to
MUSIC_SCATTERED.
* music/interval_table.hh (IntervalTable::search): Check index
against tableSize_ instead of container size.
* music/subconnector.hh, music/event_routing_map.hh: Don't
#include which contains heavy template
stuff. Instead forward declare EventRouter. Since both
subconnector.hh and event_routing_map.hh are included by other
header files, this speeds up compilation and decreases the
dependencies in the code tree.
* connector.cc, event_routing_map.cc, port.cc, subconnector.cc:
#include "music/event_router.hh".
* runtime.cc (Runtime::tick): Only access first element of
schedule if non-empty.
(Runtime::finalize): Only do schedule-related processing if
schedule initially non-empty.
* Makefile.am: Added music/interval_table.hh,
music/ordered_ilist.hh.
* music/interval_table.hh, music/ordered_ilist.hh: New files.
* music/event_router.hh: Use new IntervalTable template.
2012-08-19 Mikael Djurfeldt
* music/event_routing_map.hh, event_routing_map.cc
(EventRoutingMap::build): Removed. Replaced by fillRouter which is
now public.
music/port.hh (EventOutputPort::setupCleanup), port.cc
(EventOutputPort::buildTable), connector.cc
(EventInputCollectiveConnector::spatialNegotiation): Use
EventRoutingMap::fillRouter and call EventRouter::buildTable
directly. Delete the event routing map before calling buildTable
so that the data structures used by buildTable don't co-exist in
memory with the event routing map.
2012-08-18 Mikael Djurfeldt
* music/interval_tree.hh, music/collector.hh, collector.cc,
music/distributor.hh, distributor.cc, event_routing_map.cc:
Separated the template DataType parameter of IntervalTree into
IntervalType and DataType.
* Makefile.am, music/event_routing_map.hh, event_routing_map.cc,
music/connector.hh, music/port.hh: Renamed
event_routingmap.{cc,hh} -> event_routing_map.{cc,hh}.
* music/interval_tree.hh: Optimized memory usage.
2012-08-17 Mikael Djurfeldt
* music/index_map.hh, music/interval.hh: Removed clone().
* connector.cc, music/event_router.hh, event_router.cc,
event_routingmap.cc, music/event.hh: Removal of indirection and
virtual pointers for IndexProcessors.
* music/event_router, event_router.cc: Removed unused member Data ().
* interval.hh, music/event_router.hh, event_router.cc,
event_routingmap.cc: Simplifications enabled by previous changes.
* music/event_router.hh, event_router.cc: Removed indirection
(pointer) to EventRoutingData from the IntervalTree through the
use of templates.
* port.cc: Let type dispatch happen here instead of in the
interval tree.
* event_routingmap.cc: Formatting.
* music/collector.hh, collector.cc, music/distributor.hh,
distributor.cc: Reverted to old use of interval_tree.
* music/interval_tree.hh: Reverted to version in trunk, but with
an added assignment operator.
2012-08-17 Mikael Djurfeldt
* application_map.cc (ApplicationMap::read): Only create file
"leaders" if MUSIC_DEBUGGING is defined.
* configuration.cc (Configuration::getEnv): Handle the case where
the MUSIC configuration variable is not present (launched without
MUSIC) properly.
2012-08-13 Mikael Djurfeldt
* scheduler.cc (Scheduler::Node::advance): Define time variable
only if debugging. Formatting changes.
* music/data_map.hh (~DataMap::DataMap), music/event_router.hh
(~IndexProcessor::IndexProcessor), music/index_map.hh
(~IndexMap::IndexMap)
(~IndexMap::IteratorImplementation::IteratorImplementation),
music/interval.hh (~Interval::Interval), music/spatial.hh
(~NegotiationIterator::Implementation::Implementation: Destructor
made virtual.
* music/collector.hh (Collector::Interval::clone),
music/distributor.hh (Distributor::Interval::clone): Added for
consistency.
* event_router.cc, music/event_router.hh, music/collector.hh,
music/distributor.hh, music/interval.hh, music/index_map.hh,
music/interval_tree.hh: Renamed Clone --> clone throughout.
* event_router.cc, music/event_router.hh: Renamed "spicialized"
--> "specialized" throughout.
* application_map.cc (ApplicationMap::assignLeaders): Only create
ranks file if MUSIC_DEBUG is defined.
2012-08-07 Mikael Djurfeldt
* runtime.cc (runtime.cc): Disable deletion of ports.
2012-08-03 Mikael Djurfeldt
* music/version.hh.in: New file.
2012-03-20 Mikael Djurfeldt
* setup.cc, music/setup.hh (Setup::maybeProcessMusicArgv): New
method. Get argc and argv from MUSIC_ARGV, if available.
2012-03-18 Mikael Djurfeldt
* runtime.cc (Runtime::Runtime): Call maybepostponedSetup ().
* configuration.cc (MUSIC): Added comment with syntax of
_MUSIC_CONFIG_.
2012-03-15 Mikael Djurfeldt
* music/setup.hh, setup.cc (maybePostponedSetup, fullInit): New
functions.
* music/configuration.hh, configuration.cc
(Configuration::postponeSetup): New function.
* port.cc (Port::Port): Call maybepostponedSetup ().
2011-11-24 Mikael Djurfeldt
* Makefile.am (libmusic_la_LDFLAGS): Added libmpidep.la in order
to support predictRank.
* music/predict_rank.hh, predict_rank.cc: New files.
2011-01-31 Mikael Djurfeldt
* Makefile.am (libmusic_c_la_DEPENDENCIES): Added in order to
support parallel builds.
2011-01-13 Mikael Djurfeldt
* subconnector.cc (ContInputSubconnector::receive): Update receive
buffer pointer for subsequent receives when large packages have
been split.
* BIFO.cc (BIFO::insertBlock): Fixes to logic when buffer has
wrapped around.
2010-07-28 Mikael Djurfeldt
* Release 1.0.7
* synchronizer.cc (Synchronizer::nextCommunication): Revert
buggy handling of tight loops in change of 2009-10-23.
* subconnector.cc
(MessageOutputSubconnector::MessageOutputSubconnector): Bugfix:
Initialize synchronizer pointer properly.
2009-10-25 Mikael Djurfeldt
* Release 1.0.6
* ioutils.c, parse.cc: Added #include .
2009-10-24 Mikael Djurfeldt
* Release 1.0.5
2009-10-23 Mikael Djurfeldt
* synchronizer.cc (Synchronizer::nextCommunication): Handle
tight loops (maxBuffered == 0) of spike events.
* temporal.cc (TemporalNegotiator::combineParameters): Correctly
take MAX_BUFFERED_NO_VALUE arguments into consideration.
* music/subconnector.hh, connector.cc, runtime.cc,
subconnector.cc: Use COMM_WORLD ranks for the pair-wise
communication schedule in Runtime::buildSchedule.
* music/port.hh, port.cc (EventOutputPort::EventOutputPort,
EventInputPort::EventInputPort): Moved from header file to
port.cc.
* temporal.cc (TemporalNegotiator::distributeNegotiationData): Use
type ClockState for accLatency.
2009-10-20 Mikael Djurfeldt
* connector.hh, event_router.hh, interval.hh, port.hh,
connector.cc, event_router.cc, port.cc: New version of event
routing interval joining code which handles interval sequences for
different targets separately.
2009-10-19 Mikael Djurfeldt
* event_router.cc (EventRouter::buildTable): Added debugging
printout of routing table size (when #define MUSIC_DEBUG is
uncommented).
* music/interval_tree.hh (IntervalTree::size): New method (for debugging purposes).
2009-10-12 Mikael Djurfeldt
* setup.cc (Setup::Setup): Report an error if MPI::Init has been
called.
2009-10-05 Mikael Djurfeldt
* music/connector.hh, music/event_router.hh, music/port.hh,
connector.cc, event_router.cc, port.cc: Join event routing
intervals over holes in the routing map. This increases
efficiency of event routing but has the consequence that
non-mapped indices may now be erroneously routed.
2009-10-04 Mikael Djurfeldt
* music-c.h: (MUSIC_EventOutputPort_mapGlobalIndex)
(MUSIC_EventOutputPort_mapLocalIndex): Inserted missing
declarations. (Thanks to Michael Hines.)
* Makefile.am (musicinclude_HEADERS): Removed duplicate
message.hh.
2009-04-01 Mikael Djurfeldt
* Release 1.0.4
2009-03-15 Mikael Djurfeldt
* music/spatial.hh, spatial.cc (NegotiationIterator): Join
intervals. (In some cases this allows thousands of routing
intervals to be replaced by a single one.)
* runtime.cc (Runtime::finalize): Only include Barrier call for
OpenMPI versions <= 1.2.
* music/temporal.hh,
temporal.cc (TemporalNegotiator::computeDefaultMaxBuffered):
Select a proper default buffering for message ports.
* spatial.cc (SpatialInputNegotiator::negotiateWidth): Set
maxLocalWidth_ when given wildcard index.
2009-03-14 Mikael Djurfeldt
* music/connector.hh, music/subconnector.hh, connector.cc,
subconnector.cc: Moved buffer from subconnector to connector for
MessageOutputPorts.
* music/subconnector.hh (BufferingOutputSubconnector): New class.
* music/FIBO.hh, FIBO.cc (FIBO::clear, FIBO::nextBlockNoClear):
New member functions.
* port.cc (MessageInputPort::mapImpl): Give correct routing
information in the indexMap.
* music/port.hh, port.cc (MessageInputPort::map): Cover all
argument combinations.
* music/index_map.hh, index_map.cc (Index::WILDCARD_MAX): New
member.
* spatial.cc: Accept wild card indices on receiver side.
* subconnector.cc (EventInputSubconnectorGlobal::receive,
EventInputSubconnectorLocal::receive,
MessageInputSubconnector::receive): Define `data' as vector of
char, not vector of char*.
2009-03-13 Mikael Djurfeldt
* Release 1.0.3
* setup.cc: #include "config.h"
2009-03-12 Mikael Djurfeldt
* music/temporal.hh, temporal.cc
(class TemporalNegotiator,
TemporalNegotiator::createNegotiationCommunicator,
TemporalNegotiator::~TemporalNegotiator): Keep handles to MPI
groups throughout communication.
* runtime.cc (Runtime::finalize): Call Connector::freeIntercomm
(); Include a barrier call to make freeing work under OpenMPI.
* music/connector.hh, connector.cc (Connector::freeIntercomm): New
member function.
2009-03-12 Mikael Djurfeldt
* Release 1.0.2
* version.cc: Updated to version 1.0.2.
2009-03-11 Mikael Djurfeldt
* setup.cc: Conditionally delete temporalNegotiator.
* music/port.hh
(OutputRedistributionPort::OutputRedistributionPort,
InputRedistributionPort::InputRedistributionPort): New
constructors: Initialize spatialNegotiator to NULL pointer.
* port.cc (OutputRedistributionPort::setupCleanup,
InputRedistributionPort::setupCleanup): Conditionally delete
spatialNegotiator. (It has not been allocated if the port has not
been mapped.)
* music/BIFO.hh, music/clock.hh, music/connector.hh,
music/subconnector.hh, music/synchronizer.hh, music/temporal.hh,
BIFO.cc, clock.cc, connector.cc, port.cc, runtime.cc,
subconnector.cc, synchronizer.cc, temporal.cc: Major revision of
timing logic. Cont ports can now be connected in loops.
2009-03-09 Mikael Djurfeldt
* synchronizer.cc (Synchronizer::setMaxDelay (ClockState)): Moved
decrementing of localTime to Runtime::initialize.
(Synchronizer::setMaxDelay (ClockState, Clock&)): Use
Clock::setClockTicks to set startTime. (setMaxDelay may be called
multiple times.)
* runtime.cc (Runtime::initialize): Decrement localTime one tick
here.
* music/temporal.hh, temporal.cc
(TemporalNegotiator::distributeParameters): New function.
* collector.cc: Collector shouldn't make assumptions and compute a
"better" maxBlockSize-value for the buffers. Instead use
allowedBuffered as given when configured.
* connector.cc: Configure compute the actual needed buffer size
here instead.
* music/clock.hh, clock.cc (Clock::setClockTicks): New function.
* BIFO.cc (BFIO::trimBlock): More informative overflow message.
2009-03-08 Mikael Djurfeldt
* synchronizer.cc, port.cc, music/temporal.hh: Decrement
maxBuffered at the proper place. (This fixes a bug where the loop
algorithm worked on different parameters than the timing schedule
algorithm.)
* music/debug.hh (MUSIC_LOGBR): New debug macro.
* synchronizer.cc: Inserted some debugging statements.
* port.cc (OutputRedistributionPort::setupCleanup,
InputRedistributionPort::setupCleanup): Delete spatialNegotiator
at end of setup phase.
* music/connector.hh, connector.cc, runtime.cc: Resolve a memory
allocation problem so that we leak less memory.
* port.cc (ContInputPort::mapImpl): Don't call assertInput ()
here.
* music/error.hh, music/port.hh, music/runtime.hh, music/setup.hh,
error.cc, port.cc, runtime.cc, setup.cc (Setup::Setup,
Runtime::Runtime, Port::map): Added error messages when trying to
call repeatedly.
2009-03-08 Mikael Djurfeldt
* Release 1.0.1
* music/connector.hh, music/port.hh, music/spatial.hh,
music/subconnector.hh, music/temporal.hh, configuration.cc,
connector.cc, port.cc, spatial.cc, subconnector.cc, temporal.cc:
Pass MPI::Datatype to ContSubconnectors; Some code cleanups.
2009-03-06 Mikael Djurfeldt
* music/synchronizer.hh, synchronizer.cc, connector.cc: Removed
some old cruft in timing logic.
* sampler.cc: #include
* setup.cc (Setup::publishMessageInput,
Setup::publishMessageOutput): Added.
* Makefile.am: Link shared library against MPI.
* music/port.hh, port.cc: Bugfixed error reporting.
* Makefile.am: Don't accept unresolved symbols in the shared library.
* music/version.hh, version.cc: New files.
* Makefile.am: Added ditto.
* Makefile.am: Set shared library version 1.0.0. (Note that this
version number follows different rules than the MUSIC version.)
* port.cc (Port::assertOutput, Port::assertInput, Port::hasWidth,
Port::width): Supply port name in error messages.
* connectivity.cc (Connectivity::add): Pass port name to
ConnectivityInfo constructor.
* music/connectivity.hh (ConnectivityInfo): Added portName (to be
used for more comprehensible error messages).
2009-03-05 Mikael Djurfeldt
* setup.hh (class Setup): Hide internal API as private.
* music/connector.hh, music/runtime.hh, music/setup.hh,
music/spatial.hh, music/subconnector.hh, music/temporal.hh,
connector.cc, port.cc, runtime.cc, setup.cc, spatial.cc,
subconnector.cc, synchronizer.cc, temporal.cc: Begin to reorganize
connectors so that functionality for setup and not needed during
runtime is moved to the new class Connection.
* music/connection.hh, connection.cc: New files.
* Makefile.am: Updated.
* music/temporal.hh, temporal.cc (ConnectionEdge): Renamed from
"Connection".
2009-03-03 Mikael Djurfeldt
* Release 1.0
2009-02-27 Mikael Djurfeldt
* ChangeLog, Makefile.am, music/FIBO.hh, music/array_data.hh,
music/clock.hh, music/connector.hh, music/data_map.hh,
music/event.hh, music/interval.hh, music/port.hh,
music/runtime.hh, music/spatial.hh, music/subconnector.hh,
music/synchronizer.hh, music/temporal.hh, FIBO.cc, array_data.cc,
clock.cc, connector.cc, port.cc, runtime.cc, spatial.cc,
subconnector.cc, synchronizer.cc, temporal.cc: Continous data port
framework.
* music/BIFO.hh, music/collector.hh, music/distributor.hh,
music/sampler.hh, BIFO.cc, collector.cc, distributor.cc,
sampler.cc: New files.
2009-02-16 Mikael Djurfeldt
* Makefile.am (libmusic_la_SOURCES): Added distributor.cc,
music/distributor.cc, collector.cc, music/collector.hh.
* music/spatial.hh, spatial.cc: Added destructor which destroys
indices.
* setup.cc, runtime.cc: Pass connectors even if not launched using
the music utility.
2009-02-11 Mikael Djurfeldt
* music-c.h, music-c-c.c, music-c.cc (MUSIC_setupCommunicator):
Declare properly and don't use MPI_Intracomm.
2009-02-09 Mikael Djurfeldt
* music/subconnector.hh,
subconnector.cc (InputSubconnector::flushed): Bugfix: Initialize.
* error.cc, music/error.hh (error0): Report errors only from MPI
process rank 0.
* music/temporal.hh, temporal.cc: Implemented distribution of
allowed buffering using a loop detection algorithm.
2009-02-08 Mikael Djurfeldt
* FIBO.cc, connector.cc, music/FIBO.hh, music/connector.hh,
music/event.hh, music/runtime.hh, music/subconnector.hh,
music/synchronizer.hh, runtime.cc, subconnector.cc,
synchronizer.cc: Flush buffers at MUSIC::finalize.
2009-02-06 Mikael Djurfeldt
* music/connector.hh, music/spatial.hh, music/synchronizer.hh,
music/temporal.hh, port.cc, spatial.cc, synchronizer.cc,
temporal.cc: Compute default maxBuffered value based on
temporal.hh:DEFAULT_PACKET_SIZE.
2009-02-05 Mikael Djurfeldt
* music/setup.hh, music/synchronizer.hh, music/temporal.hh,
runtime.cc, setup.cc, temporal.cc: Bugfix: Convert accLatency to
ClockStateT.
* clock.cc, connectivity.cc, connector.cc, music/clock.hh,
music/connectivity.hh, music/connector.hh, music/debug.hh,
music/runtime.hh, music/setup.hh, music/synchronizer.hh,
music/temporal.hh, runtime.cc, setup.cc, spatial.cc,
synchronizer.cc, temporal.cc: Timing for applications with
different inter-tick-intervals may now work.
2009-01-27 Mikael Djurfeldt
* clock.cc, connector.cc, music/clock.hh, music/connector.hh,
music/runtime.hh, music/setup.hh, music/synchronizer.hh,
music/temporal.hh, port.cc, runtime.cc, setup.cc, subconnector.cc,
synchronizer.cc, temporal.cc: First steps of the timing algorithm.
2008-12-02 Mikael Djurfeldt
* Switch to CamelCase.
2008-11-05 Mikael Djurfeldt
* music/interval_tree.hh: Bugfix: Compute the size of the binary
tree correctly.
2008-11-04 Mikael Djurfeldt
* music/connectivity.hh, connectivity.cc: Modified
connectivity_map to use indices rather than pointers (which cause
problems when the vector of connections is resized).
* music/debug.hh: New file.
2008-11-03 Mikael Djurfeldt
* FIBO.cc (FIBO::FIBO, FIBO::grow): Bugfix: Use resize instead of
reserve on buffer vector, otherwise old elements are not
guaranteed to be copied.
* music/event.hh (event::event): New constructor.
(event::operator<): New operator.
* port.cc (port::has_width, port::width): Added some error
checking.
* music/spatial.hh,
spatial.cc (spatial_negotiator::wrap_intervals): Compute local
offset differently depending on index::type argument.
* music/index_map.hh (index_interval::set_local): New member
function.
* linear_index.cc, permutation_index.cc: Correctly compute local
index offset.
* configuration (configuration::configuration,
configuration::~configuration): Create and delete application_map
and connectivity also when not launched under music.
* event_router.cc (event_router::insert_event): Always subtract
local offset (not subtracting requires that all offsets are zero
which only happens either if both sides use global indices or if
both sides use local indices which even out).
2008-10-31 Mikael Djurfeldt
* music/spatial.hh, spatial.cc (negotiate_width): Error check
width.
* music/event_router.hh (inserter_global): Offsets are negative
due to the spatial negotiation algorithm.
* music/spatial.hh, spatial.cc (intersect_to_buffers): New
implementation which allows index_maps for different MPI processes
to overlap. The new algorithm is O (NP^2) where N is the number of
indices and P the number of processes. (The old one was O (N).)
* music/permutation_index.hh, permutation_index.cc: Implemented.
* music/index_map.hh (index_map): Use value semantics (so that we
can copy the position by copying the iterator).
* music/linear_index.hh (linear_index): Ditto.
2008-10-30 Mikael Djurfeldt
* spatial.cc: Bugfix: Changed MPI::INTEGER (Fortran) -> MPI::INT
* spatial.hh (TRANSMITTED_INTERVALS_MAX): New constant.
* spatial.cc (spatial_negotiator::send,
spatial_negotiator::receive): Allow transmission of an arbitrary
number of spatial negotiation intervals.
* subconnector.hh (SPIKE_BUFFER_MAX): New constant.
* subconnector.cc (event_output_subconnector::send,
event_input_subconnector_global, event_input_subconnector_local):
Allow transmission of an arbitrary number of spikes.
* spatial.cc (spatial_output_negotiator::negotiate): Bugfix: Use
remote_n_proc instead of n_processes when sending to remote side.
* music/application_map.hh, application_map.cc, index_map.cc,
music/interval.hh, music/interval_tree.hh, music/ioutils.hh,
ioutils.cc, music/spatial.hh, spatial.cc, music/subconnector.hh,
subconnector.cc, music/temporal.hh, temporal.cc: New files.
* Changes throughout to implement propagation of configuration
information and routing of spikes.
2008-10-16 Mikael Djurfeldt
* music/FIBO.hh (FIBO::buffer): Bugfix: Changed to vector of char
instead of char*.
2008-10-14 Mikael Djurfeldt
* music/port.hh, port.cc (port::is_connected): Make sure this
method works also in the runtime phase.
2008-10-13 Mikael Djurfeldt
* Makefile.am, music/FIBO.hh, FIBO.cc, clock.cc,
music/configuration.hh, configuration.cc, music/connector.hh,
connector.cc, music/event_router.hh, event_router.cc,
music/port.hh, port.cc, music/runtime.hh, runtime.cc,
music/setup.hh, setup.cc, synchronizer.cc: A first, cheating,
approximation of the implementation of spike communication. Will
be followed by cleanups and real implementation. The present
implementation only allows two applications with an output and
input port respectively. The ports have a constant width given in
ports.hh and the sender and receiver application must have equal
number of MPI processes.
* music/connectivity.hh, connectivity.cc: New files.
2008-10-10 Mikael Djurfeldt
* music/index_map.hh (local_index::local_index,
local_index::local_index): New constructor.
* music-c.h, music-c.cc (MUSIC_event_input_port_map_global_index,
MUSIC_event_input_port_map_local_index): Replacing
MUSIC_event_input_port_map.
* music/port.hh (event_input_port): Added facilities to support C
interface.
* music/port.hh, port.cc (event_input_port::map): Take
event_handler_global_index and event_handler_local_index instead
of event_handler in second argument.
* music/event.hh (event_handler_global_index,
event_handler_local_index): New classes which replace
event_handler.
* music/port.hh, port.cc (insert_event): Replaced old method with
two new, one with a second argument local_index, and an overloaded
version with global_index.
* music/index_map.hh (global_index, local_index): New classes.
2008-10-09 Mikael Djurfeldt
* music/event_data.hh, music/message_data.hh: Removed.
* music/event.hh (event_handler::operator ()): Made virtual and
corrected arguments to adhere to RFC.
* port.cc (event_output_port::insert_event): Send spikes to event
router.
* Makefile.am (libmusic_la_SOURCES): Added event_router.cc,
music/event_router.hh
* music/event_router, event_router.cc: New files.
2008-10-08 Mikael Djurfeldt
* runtime.cc (runtime::runtime): Initialize my_communicator and
schedule.
* music/connector.hh, connector.cc: Connectors take over the role
of subconnectors.
2008-10-06 Mikael Djurfeldt
* music/port.hh, port.cc (event_output_port::insert_event): New method.
2008-09-23 Mikael Djurfeldt
* setup.cc (setup::setup): Compile use of MPI::Init_thread
conditionally.
* music-c.cc: #include .
2007-11-26 Mikael Djurfeldt
* Makefile.am (libmusic_la_SOURCES): Added music/spike_data.hh,
spike_data.cc.
* spike_data.cc: New file.
2007-11-23 Mikael Djurfeldt
* music/spike_data.hh: New file.
* music/setup.hh (setup::publish): Removed
(setup::publish_input, setup::publish_output): New methods.
* music/array_data.hh, music/data_map.hh, music/index_map.hh,
music/linear_index.hh: Added copyright notice + #ifdef logic.
* music/array_data.hh (array_data::array_data): Data type argument
moved first; added new constructor for linear arrays.
* Makefile.am: Added music/port.hh, port.cc.
* music/port.hh, port.cc: New files.
* music/runtime.hh (runtime::input_ports, runtime::output_ports):
New members.
2007-11-08 Mikael Djurfeldt
* configuration.cc (configuration::configuration): Handle dirct
launch by mpirun.
* music/configuration.hh (setup::launched_by_music): New method.
* music/configuration.hh (setup::_launched_by_music): New private
member.
* music/setup.hh, setup.cc (setup::my_communicator): Renamed from
myCommunicator.
* parse.cc (parser::parse_string, parser::next_arg): Use int
instead of char to handle characters.
* configuration.cc (configuration::configuration,
configuration::tap): Use int instead of char to handle
characters.
2007-11-02 Mikael Djurfeldt
* music/setup.hh, music/parse.hh: Don't #include
.
* music/setup.hh: #include .
2007-11-01 Mikael Djurfeldt
* music/error.hh, error.cc: Added.
* music/parse.hh, parse.cc: Moved here from utils subdirectory.
* music/configuration.hh, condiguration.cc
(configuration::configuration, configuration::lookup,
configuration::write_env,
configuration::insert, configuration::color): New methods.
* music/application_map.hh, application_map.cc: Moved to utils
subdirectory.
* Makefile.am (libmusic_la_SOURCES): Removed
music/application_map.hh, application_map.cc; Added
music/parse.hh, parse.cc.
* music/setup.hh, setup.cc: Rewritten.
2007-10-26 Örjan Ekeberg
* runtime.cc, music/runtime.hh: Use type Intracomm for communicator.
2007-10-25 Mikael Djurfeldt
* Makefile.am: Added configuration.cc, music/configuration.hh,
application_map.cc music/application_map.hh.
* application_map.cc, music/application_map.hh: New files.
* configuration.cc, music/configuration.hh: New files.
2007-10-23 Mikael Djurfeldt
* music/setup.hh, setup.cc (setup::config_string): Renamed from
config_get_string.
(setup::config_int): Renamed from config_get_int.
(setup::config_double): Renamed from config_get_double.
2007-10-19 Örjan Ekeberg
* music/runtime.hh, runtime.cc, music/setup.hh, setup.cc:
Replace C MPI calls to their equivalent C++ versions.
2007-10-19 Mikael Djurfeldt
* music/setup.hh, setup.cc (setup::config_get_string,
setup::config_get_int, setup::config_get_double, setup::is_port,
setup::port_size): New methods.
* array_data.cc, music/array_data.hh: Renamed from arraydata.cc,
music/arraydata.hh.
* linear_index.cc, music/linear_index.hh: Renamed from
linearindex.cc, music/linearindex.hh.
* arraydata.cc, linearindex.cc, music/arraydata.hh,
music/linearindex.hh, music/setup.hh (array_data, linear_index):
Renamed from arraydata and linearindex everywhere.
* Makefile.am (libmusic_la_SOURCES): Added linear_index.cc,
music/linear_index.hh music/index_map.hh mysic/array_data.hh
array_data.cc music/array_data.hh.
(musicinclude_HEADERS): Added music/index_map.hh music/data_map.hh
music/linear_index.hh music/array_data.hh.
2007-10-19 Örjan Ekeberg
* Makefile.am, music/arraydata.hh, music/data_map.hh,
music/index_map.hh, music/linearindex.hh, arraydata.cc,
linearindex.cc: Added abstraction classes for data indexing.
* music/setup.hh, setup.cc: Added publish method.
Add communicator access method (duplication from runtime).
2007-09-13 Mikael Djurfeldt
* runtime.cc, setup.cc: Rewritten.
* Makefile.am, music/setup.hh, music/runtime.hh: New files.
* music.hh: Rewritten to include header files under the music
directory.
2007-08-17 orjan
* music.hh (MUSIC): Add binding routines
2007-08-17 Mikael Djurfeldt
* Bong!
music-1.2.1/src/scheduler.cc 0000644 0005140 0005140 00000047210 14372254427 012640 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2012, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
//#define MUSIC_DEBUG
#include "music/scheduler.hh"
#include "music/scheduler_agent.hh"
#include "music/debug.hh"
#if MUSIC_USE_MPI
#include
#include
#include
#include
#ifdef MUSIC_DEBUG
#include
#endif
namespace MUSIC
{
Scheduler::Scheduler (MPI_Comm comm, int leader) :
nodes (NULL), appl_data_ (NULL), conn_data_ (NULL)
{
comm_ = comm;
leader_ = leader;
}
Scheduler::~Scheduler ()
{
if (nodes != NULL)
delete nodes;
if (appl_data_ != NULL)
delete[] appl_data_;
if (conn_data_ != NULL)
delete[] conn_data_;
}
void
Scheduler::initialize (TemporalNegotiatorGraph *appl_graph,
std::vector& connectors)
{
nodes = new SGraph (appl_graph->local_node_color (), appl_graph->nNodes (),
appl_graph->getNConnections ());
setApplications (appl_graph);
setConnections (appl_graph, connectors);
color_ = appl_graph->local_node_color ();
iter_node = nodes->begin ();
iter_conn = 0;
pushForward ();
std::vector::iterator agent;
for (agent = agents_.begin(); agent != agents_.end(); agent++)
(*agent)->initialize(connectors);
initializeAgentState ();
}
void
Scheduler::setAgent (SchedulerAgent* agent)
{
agents_.push_back (agent);
}
void
Scheduler::initializeAgentState ()
{
cur_agent_ = agents_.begin ();
}
AEdge
Scheduler::pushForward ()
{
while (true)
{
#if 0
// std::vector::iterator node;
for (; iter_node < nodes.size (); ++iter_node )
{
Node *node = nodes.at(iter_node);
if (iter_conn < 0 && node->nextReceive () > node->localTime ().time ())
node->advance ();
std::vector* conns = node->outputConnections ();
// std::vector::iterator conn;
for (++iter_conn;
iter_conn < static_cast (conns->size ());
++iter_conn)
{
SConnection *conn = conns->at(iter_conn);
//do we have data ready to be sent?
if (conn->nextSend () <= conn->preNode ()->localTime ()
&& conn->nextReceive () == conn->postNode ()->localTime ())
{
SConnection sconn = *conn;
sconn.postponeNextSend( conn->preNode()->localTime());
conn->advance();
return sconn;
}
}
iter_conn = -1;
}
#endif
for (; iter_node < nodes->end (); iter_node++)
{
if (iter_conn == 0)
iter_conn = (*iter_node).begin_o ();
else
{
advanceConnection ( (**iter_conn).data ());
++iter_conn;
}
for (; iter_conn < (*iter_node).end_o (); iter_conn++)
{
//do we have data ready to be sent?
if ( (*iter_conn)->data ().nextSend
<= (*iter_conn)->pre ().data ().localTime
&& (*iter_conn)->data ().nextReceive
== (*iter_conn)->post ().data ().localTime)
{
last_sconn_ = * (*iter_conn);
last_sconn_.data ().postponeNextSend (
(*iter_conn)->pre ().data ().localTime);
return last_sconn_;
}
}
iter_conn = 0;
}
for (iter_node = nodes->begin (); iter_node < nodes->end ();
iter_node++)
{
Clock next_recv = nextApplicationReceive (*iter_node);
if ((*iter_node).data ().localTime < next_recv)
(*iter_node).data ().localTime.tick ();
}
iter_node = nodes->begin ();
}
}
#if 0
void
Scheduler::createMultiConnectors (Clock localTime,
std::vector& connectors,
MultiBuffer* multiBuffer,
std::vector& multiConnectors)
{
//if (mpi_get_rank (MPI_COMM_WORLD) == 2)
// std::cout << "prep localTime = " << localTime.time () << std::endl;
// We need to create the MultiConnectors ahead of time since their
// creation requires communication between all members of
// COMM_WORLD. Temporary solution: Create all MultiConnectors
// that will be needed during the first 100 steps.
std::vector > schedule;
std::vector multiProxies;
multiProxies.resize (Connector::proxyIdRange ());
for (int self_node = 0; self_node < (int) nodes.size (); ++self_node)
{
localTime.reset ();
createMultiConnNext (self_node,
localTime,
connectors,
multiBuffer,
schedule);
localTime.ticks (-1);
std::vector cCache;
for (int i = 0; i < 100; ++i)
{
localTime.tick ();
createMultiConnStep (self_node,
localTime,
connectors,
multiBuffer,
multiConnectors,
multiProxies,
cCache,
schedule,
false);
}
createMultiConnStep (self_node,
localTime,
connectors,
multiBuffer,
multiConnectors,
multiProxies,
cCache,
schedule,
true);
schedule.clear ();
// Now reset node and connection clocks to starting values
for (std::vector::iterator node = nodes.begin ();
node != nodes.end ();
++node)
(*node).localTime.reset ();
for (std::vector::iterator conn = connections.begin ();
conn != connections.end ();
++conn)
{
(*conn)->resetClocks ();
(*conn)->advance ();
}
}
}
void
Scheduler::createMultiConnNext (int self_node,
Clock& localTime,
std::vector& connectors,
MultiBuffer* multiBuffer_,
std::vector > &schedule)
{
while (schedule.empty ()
// always plan forward past the first time point to make
// sure that all events at that time are scheduled
|| schedule.front ().first == schedule.back ().first)
{
std::vector::iterator node;
for ( node=nodes.begin (); node < nodes.end (); ++node )
{
if ((*node)->nextReceive () > (*node)->localTime ().time ())
(*node)->advance ();
std::vector* conns = (*node)->outputConnections ();
std::vector::iterator conn;
for (conn = conns->begin (); conn < conns->end (); ++conn)
//do we have data ready to be sent?
if ((*conn)->nextSend () <= (*conn)->preNode ()->localTime ()
&& (*conn)->nextReceive () == (*conn)->postNode ()->localTime ())
{
if (self_node == (*conn)->postNode ()->getId () //input
|| self_node == (*conn)->preNode ()->getId ())//output
{
double nextComm
= (self_node == (*conn)->postNode ()->getId ()
? (*conn)->postNode ()->localTime ().time ()
: (*conn)->preNode ()->localTime ().time ());
schedule.push_back
(std::pair(nextComm,
(*conn)->getConnector ()));
}
MUSIC_LOG0 ("Scheduled communication:"<< (*conn)->preNode ()->getId () <<"->"<< (*conn)->postNode ()->getId () << "at(" << (*conn)->preNode ()->localTime ().time () << ", "<< (*conn)->postNode ()->localTime ().time () <<")");
(*conn)->advance ();
}
}
}
}
void
Scheduler::createMultiConnStep (int self_node,
Clock& localTime,
std::vector& connectors,
MultiBuffer* multiBuffer_,
std::vector& multiConnectors,
std::vector& multiProxies,
std::vector& cCache,
std::vector > &schedule,
bool finalize)
{
std::set* connsToFinalize;
int finalCount = 0;
if (finalize)
{
connsToFinalize = new std::set;
for (std::vector::iterator c = connectors.begin ();
c != connectors.end ();
++c)
connsToFinalize->insert ((*c)->receiverPortCode ());
}
while (schedule[0].first <= localTime.time()
|| (finalize && //!connsToFinalize->empty ()
++finalCount <= 4000))
{
std::vector< std::pair >::iterator comm;
for (comm = schedule.begin ();
comm != schedule.end() && comm->first <= localTime.time ();
++comm)
{
Connector* connector = comm->second;
if (connector == NULL)
continue;
if (finalize)
connsToFinalize->erase (connector->receiverPortCode ());
if (!connector->idFlag ())
continue;
unsigned int multiId = 0;
unsigned int multiProxyId = 0;
if (!connector->isProxy ())
{
multiId = connector->idFlag ();
cCache.push_back (connector);
}
else
{
dynamic_cast (connector)->setNode (self_node);
multiProxyId = connector->idFlag ();
}
bool isProxy = connector->isProxy ();
int remoteLeader = connector->remoteLeader ();
bool direction = connector->isInput ();
// yes, horrible quadratic algorithm for now
for (std::vector< std::pair >::iterator c
= comm + 1;
c != schedule.end () && c->first <= localTime.time();
++c)
{
if (c->second == NULL || c->second->idFlag () == 0)
continue;
if (c->second->isProxy ())
dynamic_cast (c->second)->setNode (self_node);
// lumping criterion
if (!(c->second->isProxy () ^ isProxy)
&& c->second->remoteLeader () == remoteLeader
&& c->second->isInput () == direction)
{
if (finalize)
connsToFinalize->erase (c->second->receiverPortCode ());
if (!c->second->isProxy ())
{
cCache.push_back (c->second);
multiId |= c->second->idFlag ();
}
else
{
multiProxyId |= c->second->idFlag ();
}
c->second = NULL; // taken
}
}
//if mpi_get_rank ((MPI_COMM_WORLD) == 2)
// std::cout << "Prep multiId = " << multiId << std::endl;
if (cCache.size () == 0)
{
if (!multiProxies[multiProxyId])
{
std::cout << "Rank " << mpi_get_rank (MPI_COMM_WORLD)
<< ": *" << std::endl << std::flush;
MPI_Comm comm;
MPI_Comm_create (MPI_COMM_WORLD, MPI_GROUP_EMPTY, &comm);
MPI_Barrier (MPI_COMM_WORLD);
//*fixme* Impossible to delete the following object
multiProxies[multiProxyId] = true;
}
}
else if (multiConnectors[multiId] == NULL)
{
multiConnectors[multiId]
= new MultiConnector (multiBuffer_, cCache);
}
cCache.clear ();
}
schedule.erase (schedule.begin (), comm);
createMultiConnNext (self_node,
localTime,
connectors,
multiBuffer_,
schedule);
}
if (finalize)
delete connsToFinalize;
}
#endif
void
Scheduler::reset (int color)
{
if (color < 0)
color = nodes->local_node_color ();
color_ = color;
reset ();
nodes->setTempColor (color);
std::vector path;
nodes->depthFirst (nodes->at (color), path);
cur_agent_ = agents_.begin ();
iter_node = nodes->begin ();
iter_conn = 0;
pushForward ();
}
void
Scheduler::reset ()
{
nodes->reset ();
for (SGraph::iterator n = nodes->begin (); n < nodes->end (); n++)
{
(*n).data ().localTime.reset ();
for (SNode::edge_iterator e = (*n).begin_o (); e < (*n).end_o (); e++)
{
(*e)->data ().reset ();
advanceConnection ( (**e).data ());
}
}
}
void
Scheduler::tick (Clock& localTime)
{
// tick is done when at least one of the agent will schedule the future communication
// next tick will start from the last successful agent
// this algorithm is based on temporally ordered SConnections
bool done = false;
for (; !done; cur_agent_++)
{
if (cur_agent_ == agents_.end ())
cur_agent_ = agents_.begin ();
if ( (*cur_agent_)->tick (localTime))
done = true;
}
}
void
Scheduler::finalize (Clock& localTime, std::vector& connectors)
{
/* remedius
* set of receiver port codes that still has to be finalized
*/
std::set cnn_ports;
for (std::vector::iterator c = connectors.begin ();
c != connectors.end (); ++c)
#if 0
if (! (*c)->needsMultiCommunication ())
#endif
{
cnn_ports.insert ( (*c)->receiverPortCode ());
}
#if 0
for (std::vector::iterator a = agents_.begin ();
a != agents_.end (); ++a)
(*a)->preFinalize (cnn_ports);
#endif
for (; !cnn_ports.empty (); cur_agent_++)
{
if (cur_agent_ == agents_.end ())
cur_agent_ = agents_.begin ();
(*cur_agent_)->finalize (cnn_ports);
}
}
Clock
Scheduler::nextApplicationReceive (SNode &node)
{
SNode::edge_iterator in_conn;
Clock nextTime;
nextTime.set(ClockState(LLONG_MAX));
for (in_conn = node.begin_i (); in_conn < node.end_i (); ++in_conn)
{
SConnData &data = (*in_conn)->data ();
if (data.nextReceive < nextTime)
nextTime = data.nextReceive;
}
return nextTime;
}
void
Scheduler::advanceConnection (SConnData &data)
{
advanceConnectionClocks (data);
Clock r = data.nextReceive;
Clock s = data.nextSend;
advanceConnectionClocks (data);
while (data.nextReceive == r)
{
s = data.nextSend;
advanceConnectionClocks (data);
}
data.nextReceive = r;
data.nextSend = s;
MUSIC_LOG0 (pre_id << "->"<nNodes ()];
int i = 0;
TemporalNegotiatorGraph::iterator it;
for (it = appl_graph->begin (); it < appl_graph->end (); ++it, ++i)
{
appl_data_[i].color = (*it).data ().color;
appl_data_[i].leader = (*it).data ().leader;
appl_data_[i].nProcs = (*it).data ().nProcs;
appl_data_[i].localTime.configure ( (*it).data ().timebase,
(*it).data ().tickInterval);
nodes->addNode (
SNode ( (*it).data ().nOutConnections, (*it).data ().nInConnections,
appl_data_[i]), (*it).data ().color);
}
}
void
Scheduler::setConnections (TemporalNegotiatorGraph *appl_graph,
std::vector& connectors)
{
conn_data_ = new SConnData[appl_graph->getNConnections ()];
int k = 0;
SGraph::iterator inode;
for (inode = nodes->begin (); inode < nodes->end (); inode++)
{
TemporalNegotiationData &data =
appl_graph->at ( (*inode).data ().color).data ();
for (int i = 0; i < data.nOutConnections; ++i)
{
Connector *connector;
bool foundLocalConnector = false;
ConnectionDescriptor &descr = data.connection[i];
SNode &pre = *inode;
SNode &post = nodes->at (descr.remoteNode);
for (std::vector::iterator c = connectors.begin ();
c != connectors.end (); ++c)
{
if (descr.receiverPort == (*c)->receiverPortCode ())
{
foundLocalConnector = true;
connector = *c;
(*c)->setInterpolate (descr.interpolate);
(*c)->setLatency (descr.accLatency);
(*c)->initialize ();
break;
}
}
#if 1
if (!foundLocalConnector)
{
if (descr.multiComm)
connector = new ProxyConnector (pre.data ().color,
pre.data ().leader, pre.data ().nProcs,
post.data ().color, post.data ().leader,
post.data ().nProcs);
else
connector = new ProxyConnector ();
}
#endif
conn_data_[k].descr = descr;
conn_data_[k].connector = connector;
conn_data_[k].nextSend.configure (pre.data ().localTime.timebase (),
pre.data ().localTime.tickInterval ());
conn_data_[k].nextReceive.configure (
post.data ().localTime.timebase (),
post.data ().localTime.tickInterval ());
SConnection &edge = nodes->addEdge (
SConnection (pre, post, conn_data_[k++]));
advanceConnection (edge.data ());
}
}
}
void
Scheduler::SGraph::handleLoop (SNode &x, std::vector & path)
{
if (&x == &nodes_[tmp_color_])
{
// Mark connections on path as loop connected to self_node
for (std::vector::iterator c = path.begin ();
c != path.end (); ++c)
(*c).data ().isLoopConnected = true;
}
}
}
#endif
music-1.2.1/src/BIFO.cc 0000644 0005140 0005140 00000011360 12652207070 011365 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/BIFO.hh"
#include "music/debug.hh"
#if MUSIC_USE_MPI
#include
#include "music/error.hh"
namespace MUSIC {
void
BIFO::configure (int elementSize, int maxBlockSize)
{
elementSize_ = elementSize;
maxBlockSize_ = maxBlockSize;
size = maxBlockSize_;
buffer.resize (size);
beginning = 0;
end = 0;
current = 0;
top = 0;
}
// Duplicate the single element in the buffer to a total of nElements
// 0 is allowed as argument in which case the buffer is emptied
void
BIFO::fill (int nElements)
{
int neededSize = nElements * elementSize_;
if (neededSize > size)
grow (neededSize);
if (end - current != elementSize_)
error ("internal error: BIFO in erroneous state before fill");
beginning = 0;
if (nElements == 0)
{
end = 0;
current = 0;
top = 0;
return;
}
// Here we use the assumption that vector memory is contiguous
// Josuttis says this is the intention of STL even though the
// first version of the report is not clear about this.
if (current != 0)
{
memcpy (&buffer[0], &buffer[current], elementSize_);
current = 0;
}
top = elementSize_;
end = nElements * elementSize_;
while (top < end)
{
memcpy (&buffer[top], &buffer[0], elementSize_);
top += elementSize_;
}
}
bool
BIFO::isEmpty ()
{
return current == end;
}
void*
BIFO::insertBlock ()
{
beginning = end; // set insertion point to end of last block
if (current <= end) // reading below inserting?
{
// Inserting above current data
// Is it time to wrap around the insertion point? This should
// only be done if we can fit a maximal block below current
// (current > maxBlockSize_). We need to use > since a
// maximal block otherwise could cause an empty buffer.
if (current > maxBlockSize_)
beginning = 0; // Wrap around!
else if (beginning + maxBlockSize_ > size) // Need to enlarge?
// (The peculiar choice of growing just as much as we need
// is made since buffers can be VERY large in large scale
// simulations.)
grow (beginning + maxBlockSize_);
}
else
{
// Inserting below current data
if (current - beginning <= maxBlockSize_) // Too tight?
{
// delta is how much more space we need + epsilon (8 to be
// nice to memory)
int delta = maxBlockSize_ - (current - beginning) + 8;
if (size - top < delta) // Need to enlarge?
// (The peculiar choice of growing just as much as we need
// is made since buffers can be VERY large in large scale
// simulations.)
grow (size + delta);
// Now move entire upper chunk of data:
memmove (&buffer[current + delta], &buffer[current],
top - current);
current += delta;
top += delta;
}
}
return static_cast (&buffer[beginning]);
}
void
BIFO::trimBlock (int blockSize)
{
if (blockSize > 0)
{
end = beginning + blockSize;
if (end > size)
{
std::ostringstream msg;
msg << "BIFO buffer overflow; received "
<< blockSize / elementSize_
<< ", room " << (size - beginning) / elementSize_
<< ", permitted " << maxBlockSize_ / elementSize_;
error (msg);
}
if (current <= end)
top = end;
}
}
void*
BIFO::next ()
{
if (isEmpty ())
{
MUSIC_LOGR ("attempt to read from empty BIFO buffer");
return NULL;
}
if (current == top)
{
// wrap around
current = 0;
top = end;
}
// Here we use the assumption that vector memory is contiguous
// Josuttis says this is the intention of STL even though the
// first version of the report is not clear about this.
void* memory = static_cast (&buffer[current]);
/* remedius
* could it be possible that elementSize > size of received data? no
* changed from current+=elementSize_ to the following line:
*/
current += std::min(elementSize_,top-current);
return memory;
}
void
BIFO::grow (int newSize)
{
size = newSize;
buffer.resize (size);
}
}
#endif
music-1.2.1/src/permutation_index.cc 0000644 0005140 0005140 00000003072 12652207070 014405 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/permutation_index.hh"
#include
namespace MUSIC {
PermutationIndex::PermutationIndex (GlobalIndex* indices, int size)
{
// NOTE: collapse adjacent intervals where possible?
for (int i = 0; i < size; ++i)
indices_.push_back (IndexInterval (indices[i],
indices[i] + 1,
indices[i] - i));
sort (indices_.begin (), indices_.end ());
}
PermutationIndex::PermutationIndex (std::vector& indices)
: indices_ (indices)
{
}
IndexMap::iterator
PermutationIndex::begin ()
{
return IndexMap::iterator (new iterator (&indices_.front ()));
}
const IndexMap::iterator
PermutationIndex::end () const
{
return IndexMap::iterator (new iterator (&indices_.back () + 1));
}
IndexMap*
PermutationIndex::copy ()
{
return new PermutationIndex (indices_);
}
}
music-1.2.1/src/FIBO.cc 0000644 0005140 0005140 00000004527 12665046752 011410 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include "music/FIBO.hh"
namespace MUSIC {
FIBO::FIBO (int es)
{
configure (es);
}
void
FIBO::configure (int es)
{
elementSize = es;
size_ = elementSize * nInitial;
if (es > 0)
buffer.resize (size_);
current = 0;
}
bool
FIBO::isEmpty ()
{
return current == 0;
}
void*
FIBO::insert ()
{
if (current == size_)
grow (2 * size_);
// Here we use the assumption that vector memory is contiguous
// Josuttis says this is the intention of STL even though the
// first version of the report is not clear about this.
void* memory = static_cast (&buffer[current]);
current += elementSize;
return memory;
}
void
FIBO::insert (void* elements, int n_elements)
{
int blockSize = elementSize * n_elements;
if (current + blockSize > size_)
grow (3 * (current + blockSize) / 2);
// Here we use the assumption that vector memory is contiguous
// Josuttis says this is the intention of STL even though the
// first version of the report is not clear about this.
void* memory = static_cast (&buffer[current]);
memcpy (memory, elements, blockSize);
current += blockSize;
}
void
FIBO::clear ()
{
current = 0;
}
void
FIBO::nextBlockNoClear (void*& data, int& blockSize)
{
data = static_cast (&buffer[0]);
blockSize = current;
}
void
FIBO::nextBlock (void*& data, int& blockSize)
{
nextBlockNoClear (data, blockSize);
clear ();
}
void
FIBO::grow (int newSize)
{
size_ = newSize;
buffer.resize (size_);
}
}
music-1.2.1/src/connectivity.cc 0000644 0005140 0005140 00000013564 14153770767 013414 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009, 2012 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include "music/music-config.hh"
#include "music/debug.hh"
#include "music/connectivity.hh"
#include "music/ioutils.hh"
#include "music/error.hh"
namespace MUSIC {
int ConnectorInfo::maxPortCode_;
#if __cplusplus <=199711L
ConnectivityInfo* const Connectivity::NO_CONNECTIVITY = NULL;
#endif
void
ConnectorInfo::registerPortCode (int portCode)
{
ConnectorInfo::maxPortCode_ = std::max (portCode,
ConnectorInfo::maxPortCode_);
}
void
ConnectivityInfo::addConnection (std::string recApp,
std::string recName,
int recCode,
int rLeader,
int nProc,
int commType,
int procMethod
)
{
portConnections_.push_back (ConnectorInfo (recApp,
recName,
recCode,
rLeader,
nProc,
commType,
procMethod));
}
void
Connectivity::add (std::string localPort,
ConnectivityInfo::PortDirection dir,
int width,
std::string recApp,
std::string recPort,
int recPortCode,
int remoteLeader,
int remoteNProc,
int commType,
int procMethod
)
{
std::map::iterator cmapInfo
= connectivityMap.find (localPort);
ConnectivityInfo* info;
if (cmapInfo == connectivityMap.end ())
{
MUSIC_LOG ("creating new entry for " << localPort);
int index = connections_.size ();
connections_.push_back (ConnectivityInfo (localPort, dir, width));
info = &connections_.back ();
MUSIC_LOG ("ci = " << info);
connectivityMap.insert (std::make_pair (localPort, index));
}
else
{
MUSIC_LOG ("found old entry for " << localPort);
info = &connections_[cmapInfo->second];
if (info->direction () != dir)
error ("port " + localPort + " used both as output and input");
}
info->addConnection (recApp,
recPort,
recPortCode,
remoteLeader,
remoteNProc,
commType,
procMethod
);
}
ConnectivityInfo*
Connectivity::info (std::string portName)
{
std::map::iterator info
= connectivityMap.find (portName);
if (info == connectivityMap.end ())
return NO_CONNECTIVITY;
else
return &connections_[info->second];
}
bool
Connectivity::isConnected (std::string portName)
{
return connectivityMap.find (portName) != connectivityMap.end ();
}
ConnectivityInfo::PortDirection
Connectivity::direction (std::string portName)
{
return connections_[connectivityMap[portName]].direction ();
}
int
Connectivity::width (std::string portName)
{
return connections_[connectivityMap[portName]].width ();
}
PortConnectorInfo
Connectivity::connections (std::string portName)
{
return connections_[connectivityMap[portName]].connections ();
}
void
Connectivity::write (std::ostringstream& out)
{
out << connectivityMap.size ();
std::map::iterator i;
for (i = connectivityMap.begin ();
i != connectivityMap.end ();
++i)
{
out << ':' << i->first << ':';
ConnectivityInfo* ci = &connections_[i->second];
out << ci->direction () << ':' << ci->width () << ':';
PortConnectorInfo conns = ci->connections ();
out << conns.size ();
PortConnectorInfo::iterator c;
for (c = conns.begin (); c != conns.end (); ++c)
{
out << ':' << c->receiverAppName ();
out << ':' << c->receiverPortName ();
out << ':' << c->receiverPortCode ();
out << ':' << c->remoteLeader ();
out << ':' << c->nProcesses ();
out << ':' << c->communicationType();
out << ':' << c->processingMethod();
}
}
}
void
Connectivity::read (std::istringstream& in, std::map leaders)
{
int nPorts;
in >> nPorts;
for (int i = 0; i < nPorts; ++i)
{
in.ignore ();
std::string portName = IOUtils::read (in);
in.ignore ();
int dir;
in >> dir;
ConnectivityInfo::PortDirection pdir
= static_cast (dir);
in.ignore ();
int width;
in >> width;
in.ignore ();
int nConnections;
in >> nConnections;
for (int i = 0; i < nConnections; ++i)
{
in.ignore ();
std::string recApp = IOUtils::read (in);
in.ignore ();
std::string recPort = IOUtils::read (in);
in.ignore ();
int recPortCode;
in >> recPortCode;
ConnectorInfo::registerPortCode (recPortCode);
in.ignore ();
// leader information is not available through configuration string
// application color is used instead
int color;
in >> color;
in.ignore ();
int nProc;
in >> nProc;
in.ignore ();
int commType;
in >> commType;
in.ignore ();
int procMethod;
in >> procMethod;
add (portName,
pdir,
width,
recApp,
recPort,
recPortCode,
leaders[color],
nProc,
commType,
procMethod
);
MUSIC_LOG ("add (portName = " << portName
<< ", pdir = " << pdir
<< ", width = " << width
<< ", recApp = " << recApp
<< ", recPort = " << recPort
<< ", rLeader = " << leaders[color]
<< ", nProc = " << nProc
<< ", commType = " << commType
<< ", procMethod = " << procMethod
<< ")");
}
}
}
}
music-1.2.1/src/linear_index.cc 0000644 0005140 0005140 00000003326 12652207070 013312 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2007, 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/linear_index.hh"
namespace MUSIC {
LinearIndex::iterator::iterator (LinearIndex* li)
: indices_ (li)
{
}
const IndexInterval
LinearIndex::iterator::operator* ()
{
return indices_->interval_;
}
const IndexInterval*
LinearIndex::iterator::dereference ()
{
return &indices_->interval_;
}
void
LinearIndex::iterator::operator++ ()
{
indices_ = 0;
}
bool
LinearIndex::iterator::isEqual (IteratorImplementation* i) const
{
return indices_ == static_cast (i)->indices_;
}
LinearIndex::LinearIndex (GlobalIndex baseindex, int size)
: interval_ (baseindex, baseindex + size, static_cast (baseindex))
{
}
IndexMap::iterator
LinearIndex::begin ()
{
return IndexMap::iterator (new iterator (this));
}
const IndexMap::iterator
LinearIndex::end () const
{
return IndexMap::iterator (new iterator (0));
}
IndexMap*
LinearIndex::copy ()
{
return new LinearIndex (*this);
}
}
music-1.2.1/src/multibuffer.cc 0000644 0005140 0005140 00000063363 14372254427 013215 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2012, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/multibuffer.hh"
#include "music/debug.hh"
#include
#include
extern "C" {
#include
}
#if MUSIC_USE_MPI
namespace MUSIC {
/********************************************************************
*
* MultiBuffer
*
********************************************************************/
MultiBuffer::MultiBuffer (MPI_Comm comm,
int localLeader,
std::vector& connectors)
: localLeader_ (localLeader)
{
//bool hang = true;
//while (hang) ;
MPI_Group worldGroup;
MPI_Comm_group (MPI_COMM_WORLD, &worldGroup);
MPI_Group localGroup;
MPI_Comm_group (comm, &localGroup);
int localSize = mpi_get_group_size (localGroup);
// maps leaders to vectors mapping local ranks to COMM_WORLD ranks
RankMap* rankMap = new RankMap ();
setupRankMap (mpi_get_rank (comm), rankMap);
#if 0
std::ostringstream ostr;
ostr << "Rank " << mpi_get_rank (MPI_COMM_WORLD) << ": rankMap ";
for (RankMap::iterator i = rankMap->begin ();
i != rankMap->end ();
++i)
{
ostr << i->first << ": ";
std::vector& ranks = i->second;
for (std::vector::iterator j = ranks.begin ();
j != ranks.end ();
++j)
ostr << *j << " ";
ostr << " ";
}
std::cout << ostr.str () << std::endl;
#endif
for (std::vector::iterator c = connectors.begin ();
c != connectors.end ();
++c)
{
// supports multicommunication?
if (!(*c)->idFlag ())
continue;
CollectiveConnector* connector
= dynamic_cast (*c);
// We create InputSubconnectorInfo:s also for output connectors.
// In this case s will be NULL.
InputSubconnector* s
= dynamic_cast (connector->subconnector ());
std::pair res
= inputConnectorMap_.insert
(InputConnectorMap::value_type (connector,
InputSubconnectorInfo (s)));
InputSubconnectorInfo& isi = res.first->second;
// decide group leader and size
int outputLeader;
int outputSize;
int inputLeader;
int inputSize;
if (connector->isInput ())
{
outputLeader = connector->remoteLeader ();
outputSize = connector->remoteNProcs ();
inputLeader = localLeader;
inputSize = localSize;
}
else
{
outputLeader = localLeader;
outputSize = localSize;
inputLeader = connector->remoteLeader ();
inputSize = connector->remoteNProcs ();
}
// setup BufferInfo array
isi.setSize (outputSize);
if (!connector->isInput ())
{
// create OutputSubconnectorInfo
OutputSubconnector* s
= dynamic_cast (connector->subconnector ());
BufferInfo* bi = &*(isi.begin () + mpi_get_rank (comm));
outputConnectorMap_.insert
(OutputConnectorMap::value_type (connector,
OutputSubconnectorInfo (s, bi)));
}
// register output group
std::vector& worldRanks = (*rankMap) [outputLeader];
registerGroup (outputLeader, worldRanks);
// setup Block array
Blocks::iterator pos = getBlock (outputLeader);
if (pos == block_.end () || pos->rank () != outputLeader)
{
// outputLeader not found in block_
// fill it in, creating one new Block for each rank
// with one BufferInfo per Block
int i = 0;
for (BufferInfos::iterator bi = isi.begin ();
bi != isi.end ();
++bi, ++i)
{
int worldRank = worldRanks[i];
pos = getBlock (worldRank);
int offset = pos - block_.begin ();
block_.insert (pos, Block ());
pos = block_.begin () + offset;
pos->setRank (worldRank);
pos->push_back (&*bi);
}
}
else
{
// outputLeader's group of ranks already had Blocks in block_
// Insert one BufferInfo per Block
int i = 0;
for (BufferInfos::iterator bi = isi.begin ();
bi != isi.end ();
++bi, ++i)
{
getBlock (worldRanks[i])->push_back (&*bi);
}
}
// register input group
worldRanks = (*rankMap) [inputLeader];
registerGroup (inputLeader, worldRanks);
pos = getBlock (inputLeader);
if (pos == block_.end () || pos->rank () != inputLeader)
{
// inputLeader's group of ranks were not represented in block_
// Create empty Block:s for them
for (int i = 0; i < inputSize; ++i)
{
int worldRank = worldRanks[i];
pos = getBlock (worldRank);
int offset = pos - block_.begin ();
block_.insert (pos, Block ());
pos = block_.begin () + offset;
pos->setRank (worldRank);
}
}
}
#if 0
{
std::ostringstream ostr;
ostr << "Rank " << mpi_get_rank (MPI_COMM_WORLD) << ": block_ ranks ";
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
ostr << b->rank () << ' ';
std::cout << ostr.str () << std::endl;
}
#endif
delete rankMap;
// setup Block and BufferInfo fields
unsigned int start = 0;
// reserve space for error block staging area
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
start = std::max (start, b->headerSize ());
MPI_Allreduce (MPI_IN_PLACE, &start, 1, MPI_UNSIGNED, MPI_MAX, MPI_COMM_WORLD);
errorBlockSize_ = start;
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
{
b->setStart (start);
start += sizeof (HeaderType); // error flag
unsigned int size = b->headerSize ();
if (size < errorBlockSize_)
{
start += errorBlockSize_ - size; // add some slack
size = errorBlockSize_;
}
b->setSize (size);
for (BufferInfoPtrs::iterator bi = b->begin (); bi != b->end (); ++bi)
{
start += sizeof (HeaderType); // data size field
(*bi)->setStart (start);
(*bi)->setSize (0);
}
}
// allocate buffer
size_ = start;
buffer_ = BufferType (malloc (size_));
// clear flags in staging area
clearFlags ();
// write header fields into buffer
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
{
b->clearBufferFlags (buffer_);
for (BufferInfoPtrs::iterator bi = b->begin (); bi != b->end (); ++bi)
(*bi)->writeDataSize (buffer_, 0);
}
}
void
MultiBuffer::setupRankMap (int localRank, RankMap* rankMap)
{
int worldSize = mpi_get_comm_size (MPI_COMM_WORLD);
int worldRank = mpi_get_rank (MPI_COMM_WORLD);
std::vector rankInfos (worldSize);
rankInfos[worldRank] = RankInfo (localLeader_, localRank);
MPI_Allgather (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
&rankInfos.front (),
sizeof (RankInfo) / sizeof (int),
MPI_INT,
MPI_COMM_WORLD);
for (int wr = 0; wr < worldSize; ++wr)
{
RankInfo& ri = rankInfos[wr];
std::vector& worldRanks = (*rankMap)[ri.leader];
if (worldRanks.size () <= static_cast (ri.localRank))
worldRanks.resize (ri.localRank + 1);
worldRanks[ri.localRank] = wr;
}
}
void
MultiBuffer::registerGroup (unsigned int leader,
std::vector& worldRanks)
{
if (groupMap_.find (leader) == groupMap_.end ())
{
Intervals& ivals = groupMap_[leader];
assert (!worldRanks.empty ());
std::vector::iterator wr = worldRanks.begin ();
int first = *wr;
int last = first;
for (++wr; wr != worldRanks.end (); ++wr)
if (*wr == last + 1)
last = *wr;
else
{
ivals.push_back (Interval (first, last));
first = last = *wr;
}
ivals.push_back (Interval (first, last));
}
}
unsigned int
MultiBuffer::computeSize (bool twostage)
{
// compute required total size
unsigned int summedSize = 0;
unsigned int thisRankSize = 0;
int thisRank = mpi_get_rank (MPI_COMM_WORLD);
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
{
unsigned int size;
if (!twostage && !b->errorFlag (buffer_))
size = b->size ();
else
{
// this block requires more space
unsigned int blockSize = sizeof (HeaderType); // error flag
int i = 0;
for (BufferInfoPtrs::iterator bi = b->begin ();
bi != b->end ();
++bi, ++i)
{
blockSize += sizeof (HeaderType); // size field
unsigned int requested = b->requestedDataSize (buffer_, i);
if (requested > (*bi)->size ())
{
blockSize += requested;
}
else
blockSize += (*bi)->size ();
}
size = std::max (errorBlockSize_, blockSize);
}
summedSize += size;
if (b->rank () == thisRank)
thisRankSize = size;
}
return thisRankSize + summedSize;
}
void
MultiBuffer::restructure (bool twostage)
{
unsigned int size = computeSize (twostage);
// resize multi-buffer
if (size > size_)
{
buffer_ = BufferType (realloc (buffer_, size));
size_ = size;
}
// relocate buffers
unsigned int newStart = size;
for (Blocks::reverse_iterator b = block_.rbegin ();
b != block_.rend ();
++b)
{
if (!twostage && !b->errorFlag (buffer_))
{
// move entire block with one memmove
newStart -= b->size ();
unsigned int oldStart = b->start ();
unsigned int offset = newStart - oldStart;
if (offset == 0)
break; // we know that there are no further error flags set
memmove (buffer_ + newStart, buffer_ + oldStart, b->size ());
b->setStart (newStart);
for (BufferInfoPtrs::iterator bi = b->begin ();
bi != b->end ();
++bi)
(*bi)->setStart ((*bi)->start () + offset);
}
else
{
unsigned int lastStart = newStart;
// at least one of the buffers requires more storage
int i = b->nBuffers () - 1;
for (BufferInfoPtrs::reverse_iterator bi
= b->rbegin ();
bi != b->rend ();
++bi, --i)
{
unsigned int oldPos = (*bi)->start () - sizeof (HeaderType);
unsigned int oldSize = (*bi)->size ();
unsigned int requested = b->requestedDataSize (buffer_, i);
if (requested > oldSize)
(*bi)->setSize (requested);
newStart -= (*bi)->size ();
(*bi)->setStart (newStart);
newStart -= sizeof (HeaderType);
// only touch buffer contents if the block belongs to
// current rank => error staging area is used for
// requested buffer sizes and buffer contains output
// data
if (b->rank () == mpi_get_rank (MPI_COMM_WORLD)
&& newStart > oldPos)
memmove (buffer_ + newStart,
buffer_ + oldPos,
oldSize + sizeof (HeaderType));
}
newStart -= sizeof (HeaderType); // error flag
*headerPtr (buffer_ + newStart)
= *headerPtr (buffer_ + b->start ());
unsigned int blockSize = lastStart - newStart;
if (blockSize < errorBlockSize_)
{
newStart -= errorBlockSize_ - blockSize;
blockSize = errorBlockSize_;
}
b->setStart (newStart);
b->setSize (blockSize);
b->clearBufferErrorFlag (buffer_);
}
}
clearErrorFlag ();
// update all existing multiConnectors
for (std::vector::iterator c = multiConnectors.begin ();
c != multiConnectors.end ();
++c)
(*c)->update ();
}
MultiBuffer::Blocks::iterator
MultiBuffer::getBlock (int rank)
{
// binary search (modified from Wikipedia)
int imin = 0;
int imax = block_.size () - 1;
while (imax >= imin)
{
/* calculate the midpoint for roughly equal partition */
int imid = (imin + imax) / 2;
// determine which subarray to search
if (block_[imid].rank () < rank)
// change min index to search upper subarray
imin = imid + 1;
else if (block_[imid].rank () > rank)
// change max index to search lower subarray
imax = imid - 1;
else
// block found at index imid
return block_.begin () + imid;
}
// rank not found---return position where rank should be inserted
return block_.begin () + imin;
}
MultiBuffer::InputSubconnectorInfo*
MultiBuffer::getInputSubconnectorInfo (Connector* connector)
{
InputConnectorMap::iterator pos = inputConnectorMap_.find (connector);
assert (pos != inputConnectorMap_.end ());
return &pos->second;
}
MultiBuffer::OutputSubconnectorInfo*
MultiBuffer::getOutputSubconnectorInfo (Connector* connector)
{
OutputConnectorMap::iterator pos = outputConnectorMap_.find (connector);
assert (pos != outputConnectorMap_.end ());
return &pos->second;
}
void
MultiBuffer::dumpBlocks ()
{
for (Blocks::iterator b = block_.begin (); b != block_.end (); ++b)
std::cout << b->rank () << std::endl;
}
/********************************************************************
*
* MultiConnector
*
********************************************************************/
MultiConnector::MultiConnector (MultiBuffer* multiBuffer)
: multiBuffer_ (multiBuffer),
recvcountInvalid_ (false)
{
connectorCode_ = ConnectorInfo::allocPortCode ();
buffer_ = multiBuffer_->buffer ();
groupMap_ = new GroupMap;
multiBuffer_->addMultiConnector (this);
}
//*fixme* code repetition
MultiConnector::MultiConnector (MultiBuffer* multiBuffer,
std::vector& connectors)
: multiBuffer_ (multiBuffer),
recvcountInvalid_ (false)
{
buffer_ = multiBuffer_->buffer ();
groupMap_ = new GroupMap;
multiBuffer_->addMultiConnector (this);
for (std::vector::iterator c = connectors.begin ();
c != connectors.end ();
++c)
add (*c);
initialize ();
}
void
MultiConnector::mergeGroup (int leader, bool isInput)
{
if (groupMap_->find (leader) == groupMap_->end ())
{
MCGroupInfo& g = (*groupMap_)[leader];
g.worldRankIntervals = &multiBuffer_->getWorldRankIntervals (leader);
g.blank = isInput;
}
else
// Only groups which provide output communicate. Groups which
// only have inputs are blanked. "Blanked" means that the
// corresponding recvcount in Allgather is 0.
(*groupMap_)[leader].blank &= isInput;
}
void
MultiConnector::add (Connector* connector)
{
if (connector->isInput ())
{
// The following has to be done here so that multiConnector
// groups are created the same way in all applications.
//
// BUT: Do we need to sort the connectors? We do if the
// scheduler can deliver connectors in different order in
// different applications.
connectorIds_.push_back (std::make_pair (connector->remoteLeader (),
multiBuffer_->localLeader ()));
mergeGroup (multiBuffer_->localLeader (), true);
mergeGroup ((connector)->remoteLeader (), false);
inputSubconnectorInfo_.push_back (multiBuffer_
->getInputSubconnectorInfo (connector));
}
else
{
connectorIds_.push_back (std::make_pair (multiBuffer_->localLeader (),
connector->remoteLeader ()));
mergeGroup ((connector)->remoteLeader (), true);
mergeGroup (multiBuffer_->localLeader (), false);
outputSubconnectorInfo_.push_back (multiBuffer_
->getOutputSubconnectorInfo (connector));
}
}
void
MultiConnector::initialize ()
{
bool isContiguous = true;
{
#ifdef MUSIC_DEBUG
std::ostringstream ostr;
ostr << "Rank " << mpi_get_rank (MPI_COMM_WORLD) << ": Create ";
#endif
int nRanges = 0;
for (GroupMap::iterator g = groupMap_->begin ();
g != groupMap_->end ();
++g)
nRanges += g->second.worldRankIntervals->size ();
int (*range)[3] = new int[nRanges][3];
int i = 0;
for (GroupMap::iterator g = groupMap_->begin ();
g != groupMap_->end ();
++g)
{
int leader = g->first;
Intervals& ivals = *g->second.worldRankIntervals;
#ifdef MUSIC_DEBUG
ostr << leader << ", ";
#endif
int size = 0;
int next = ivals[0].first;
for (Intervals::iterator ival = ivals.begin ();
ival != ivals.end ();
++ival)
{
range[i][0] = ival->first;
range[i][1] = ival->last;
range[i][2] = 1;
++i;
if (ival->first != next)
isContiguous = false;
next = ival->last + 1;
size += ival->last - ival->first + 1;
}
g->second.size = size;
}
#ifdef MUSIC_DEBUG
ostr << std::endl;
std::cout << ostr.str () << std::flush;
#endif
MPI_Group worldGroup;
MPI_Comm_group (MPI_COMM_WORLD, &worldGroup);
MPI_Group_range_incl (worldGroup, nRanges, range, &group_);
delete[] range;
}
sort (connectorIds_.begin (), connectorIds_.end ());
std::ostringstream idstr_;
std::vector >::iterator cid = connectorIds_.begin ();
idstr_ << cid->first << cid->second;
++cid;
for (; cid != connectorIds_.end (); ++cid)
idstr_ << ':' << cid->first << cid->second;
id_ = "mc" + idstr_.str ();
if (!isContiguous
|| mpi_get_group_size (group_) < mpi_get_comm_size (MPI_COMM_WORLD))
MPI_Comm_create (MPI_COMM_WORLD, group_, &comm_);
else
comm_ = MPI_COMM_WORLD;
MPI_Barrier (MPI_COMM_WORLD);
std::vector ranks (size ());
std::vector indices (size ());
for (int rank = 0; rank < size (); ++rank)
ranks[rank] = rank;
MPI_Group_translate_ranks (group_, size (), &ranks[0],
mpi_get_group (MPI_COMM_WORLD), &indices[0]);
#ifdef MUSIC_TWOSTAGE_ALLGATHER
twostage_ = true;
#endif
for (int rank = 0; rank < size (); ++rank)
{
Blocks::iterator b = multiBuffer_->getBlock (indices[rank]);
#ifdef MUSIC_DEBUG
if (b == multiBuffer_->blockEnd () && mpi_get_rank (MPI_COMM_WORLD) == 0)
{
std::cout << "asked for rank " << indices[rank] << " among:" << std::endl;
multiBuffer_->dumpBlocks ();
}
#endif
assert (b != multiBuffer_->blockEnd ());
block_.push_back (&*b);
#ifdef MUSIC_TWOSTAGE_ALLGATHER
// *fixme* need better criterion in the case of MC:s with
// proxy connectors
if (b->nBuffers () > 1)
twostage_ = false;
else if (twostage_ && b->nBuffers () > 0)
{
BufferInfo* bi = *b->begin ();
// Should store this information in separate data structure
bi->setRank (rank);
}
#endif
}
recvcounts_ = new int[size ()];
displs_ = new int[size ()];
blank_ = new bool[size ()];
int i = 0;
for (GroupMap::iterator g = groupMap_->begin ();
g != groupMap_->end ();
++g)
{
int leader = g->first;
int size = (*groupMap_)[leader].size;
int limit = i + size;
for (; i < limit; ++i)
blank_[i] = g->second.blank;
}
assert (i == size ());
delete groupMap_;
restructuring_ = true;
update ();
restructuring_ = false;
}
void
MultiConnector::update ()
{
buffer_ = multiBuffer_->buffer ();
for (OutputSubconnectorInfos::iterator osi
= outputSubconnectorInfo_.begin ();
osi != outputSubconnectorInfo_.end ();
++osi)
{
unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
BufferInfo* bi = (*osi)->bufferInfo ();
bi->writeDataSize (buffer_, dataSize);
(*osi)->subconnector ()->setOutputBuffer (buffer_
+ bi->start (),
bi->size ());
}
for (int r = 0; r < size (); ++r)
{
Block* block = block_[r];
#ifdef MUSIC_TWOSTAGE_ALLGATHER
if (twostage_)
{
if (block->begin () != block->end ())
displs_[r] = (*block->begin ())->start ();
else
displs_[r] = 0;
}
else
#endif
{
int newRecvcount = blank_[r] ? 0 : block->size ();
if (!restructuring_ && r == rank () && newRecvcount > recvcounts_[r])
// Another MultiConnector has caused MultiBuffer
// restructuring. We need to postpone modifying recvcount
// until our partner knows the new size.
recvcountInvalid_ = true;
else
recvcounts_[r] = newRecvcount;
displs_[r] = block->start ();
}
}
}
bool
MultiConnector::writeSizes ()
{
bool dataFits = true;
for (OutputSubconnectorInfos::iterator osi
= outputSubconnectorInfo_.begin ();
osi != outputSubconnectorInfo_.end ();
++osi)
{
(*osi)->subconnector ()->nextBlock ();
unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
if (!recvcountInvalid_)
(*osi)->bufferInfo ()->writeDataSize (buffer_, dataSize);
if (dataSize > (*osi)->bufferInfo ()->size ())
dataFits = false;
}
if (recvcountInvalid_ // another MultiConnector caused restructuring
|| !dataFits)
{
displs_[rank ()] = 0; // error block staging area
multiBuffer_->setErrorFlag ();
int i = 0;
for (OutputSubconnectorInfos::iterator osi
= outputSubconnectorInfo_.begin ();
osi != outputSubconnectorInfo_.end ();
++osi, ++i)
{
unsigned int size = (*osi)->bufferInfo ()->size ();
unsigned int dataSize = (*osi)->subconnector ()->dataSize ();
multiBuffer_->writeRequestedDataSize (i, std::max (size, dataSize));
}
return false;
}
return true;
}
void
MultiConnector::fillBuffers ()
{
for (OutputSubconnectorInfos::iterator osi
= outputSubconnectorInfo_.begin ();
osi != outputSubconnectorInfo_.end ();
++osi)
(*osi)->subconnector ()->fillOutputBuffer ();
}
void
MultiConnector::processInput ()
{
for (InputSubconnectorInfoPtrs::iterator isi
= inputSubconnectorInfo_.begin ();
isi != inputSubconnectorInfo_.end ();
++isi)
{
InputSubconnector* subconnector = (*isi)->subconnector ();
for (BufferInfos::iterator bi = (*isi)->begin ();
bi != (*isi)->end ();
++bi)
subconnector->processData (buffer_ + bi->start (),
bi->readDataSize (buffer_));
}
}
#ifdef MUSIC_TWOSTAGE_ALLGATHER
void
MultiConnector::processReceived ()
{
for (InputSubconnectorInfoPtrs::iterator isi
= inputSubconnectorInfo_.begin ();
isi != inputSubconnectorInfo_.end ();
++isi)
{
InputSubconnector* subconnector = (*isi)->subconnector ();
for (BufferInfos::iterator bi = (*isi)->begin ();
bi != (*isi)->end ();
++bi)
subconnector->processData (buffer_ + bi->start (),
recvcounts_[bi->rank ()]);
}
}
void
MultiConnector::checkRestructure ()
{
bool dataFits = true;
doAllgather_ = false;
int r = 0;
for (BlockPtrs::iterator b = block_.begin ();
b != block_.end ();
++r, ++b)
{
int size = recvcounts_[r];
if (size)
doAllgather_ = true;
if (size & TWOSTAGE_FINALIZE_FLAG)
{
block_[r]->setFinalizeFlag (buffer_);
recvcounts_[r] &= ~TWOSTAGE_FINALIZE_FLAG;
}
BufferInfoPtrs::iterator bipi = (*b)->begin ();
if (bipi != (*b)->end ())
{
BufferInfo* bi = *bipi;
if (size > bi->size ())
dataFits = false;
}
}
if (!dataFits)
{
int r = 0;
for (BlockPtrs::iterator b = block_.begin ();
b != block_.end ();
++r, ++b)
{
BufferInfoPtrs::iterator bipi = (*b)->begin ();
if (bipi != (*b)->end ())
{
int size = recvcounts_[r];
BufferInfo* bi = *bipi;
if (size < bi->size ())
size = bi->size ();
bi->writeDataSize (buffer_, size);
}
}
BufferInfoPtrs::iterator bipi = block_[rank()]->begin ();
int bsize = 0;
if (bipi != block_[rank ()]->end ())
bsize = (*bipi)->size ();
multiBuffer_->writeRequestedDataSize (0,
std::max (recvcounts_[rank ()],
bsize));
multiBuffer_->restructure (true);
}
}
#endif
static void
dumprecvc (std::string id, int* recvc, int* displs, int n)
{
std::ostringstream ostr;
#if 1
ostr << "Rank " << mpi_get_rank (MPI_COMM_WORLD) << ": "
<< id << ": Allgather " << *recvc;
for (int i = 1; i < n; ++i)
ostr << ", " << recvc[i];
#else
ostr << "Rank " << mpi_get_rank (MPI_COMM_WORLD) << ": "
<< id << ": Allgather "
<< *displs << ':' << *recvc;
for (int i = 1; i < n; ++i)
ostr << ", " << displs[i] << ':' << recvc[i];
#endif
ostr << std::endl;
std::cout << ostr.str () << std::flush;
}
void
MultiConnector::tick ()
{
#ifdef MUSIC_TWOSTAGE_ALLGATHER
if (twostage_)
{
// *fixme* nextBlock ()
OutputSubconnectorInfos::iterator osi = outputSubconnectorInfo_.begin ();
int recvc;
if (osi != outputSubconnectorInfo_.end ())
recvc = (*osi)->subconnector ()->dataSize ();
else
recvc = 0;
if (block_[rank ()]->finalizeFlag (buffer_))
recvc |= TWOSTAGE_FINALIZE_FLAG;
recvcounts_[rank ()] = recvc;
MPI_Allgather (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
recvcounts_, 1, MPI_INT,
comm_);
checkRestructure (); // sets doAllgather_
if (doAllgather_)
{
fillBuffers ();
#ifdef MUSIC_DEBUG
dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
#endif
MPI_Allgatherv (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
buffer_, recvcounts_, displs_, MPI_BYTE,
comm_);
processReceived ();
}
}
else
#endif
{
if (writeSizes ())
// Data will fit
fillBuffers ();
#ifdef MUSIC_DEBUG
dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
#endif
MPI_Allgatherv (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
buffer_, recvcounts_, displs_, MPI_BYTE,
comm_);
for (BlockPtrs::iterator b = block_.begin ();
b != block_.end ();
++b)
if ((*b)->errorFlag (buffer_))
{
restructuring_ = true;
multiBuffer_->restructure (false);
restructuring_ = false;
recvcountInvalid_ = false;
fillBuffers ();
#ifdef MUSIC_DEBUG
dumprecvc (id_, recvcounts_, displs_, comm_.Get_size ());
#endif
MPI_Allgatherv (MPI_IN_PLACE, 0, MPI_DATATYPE_NULL,
buffer_, recvcounts_, displs_, MPI_BYTE,
comm_);
break;
}
processInput ();
}
}
bool
MultiConnector::isFinalized ()
{
bool finalized = true;
for (int i = 0; i < size (); ++i)
if (!blank_[i] && !block_[i]->finalizeFlag (buffer_))
finalized = false;
return finalized;
}
void
MultiConnector::finalize ()
{
if (!blank_[rank ()])
block_[rank ()]->setFinalizeFlag (buffer_);
}
}
#endif // MUSIC_USE_MPI
music-1.2.1/src/version.cc 0000644 0005140 0005140 00000001471 12652207070 012335 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/version.hh"
namespace MUSIC {
const char*
version ()
{
return MUSIC_VERSION;
}
}
music-1.2.1/src/distributor.cc 0000644 0005140 0005140 00000007207 14372254427 013236 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2009, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/distributor.hh"
#include "music/debug.hh"
#if MUSIC_USE_MPI
// distributor.hh needs to be included first since it causes inclusion
// of mpi.h (in data_map.hh). mpi.h must be included before other
// header files on BG/L
#include
#include
#include "music/event.hh"
#include "music/mpi_utils.hh"
namespace MUSIC {
Distributor::Interval::Interval (IndexInterval& interval)
{
setBegin (interval.begin ());
setLength (interval.end () - interval.begin ());
}
void
Distributor::configure (DataMap* dmap)
{
dataMap = dmap;
}
IntervalTree*
Distributor::buildTree ()
{
IntervalTree* tree
= new IntervalTree ();
IndexMap* indices = dataMap->indexMap ();
for (IndexMap::iterator i = indices->begin ();
i != indices->end ();
++i)
{
MUSIC_LOGR ("adding (" << i->begin () << ", " << i->end ()
<< ", " << i->local () << ") to tree");
tree->add (*i, i->local ());
}
tree->build ();
return tree;
}
void
Distributor::addRoutingInterval (IndexInterval interval, FIBO* buffer)
{
BufferMap::iterator b = buffers.find (buffer);
if (b == buffers.end ())
{
buffers.insert (std::make_pair (buffer, Intervals ()));
b = buffers.find (buffer);
}
Intervals& intervals = b->second;
intervals.push_back (Interval (interval));
}
void
Distributor::IntervalCalculator::operator() (int& offset)
{
interval_.setBegin (elementSize_
* (interval_.begin () - offset));
interval_.setLength (elementSize_ * interval_.length ());
}
void
Distributor::initialize ()
{
IntervalTree* tree = buildTree ();
for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
{
FIBO* buffer = b->first;
Intervals& intervals = b->second;
sort (intervals.begin (), intervals.end ());
int elementSize = mpi_get_type_size (dataMap->type ());
int size = 0;
for (Intervals::iterator i = intervals.begin ();
i != intervals.end ();
++i)
{
IntervalCalculator calculator (*i, elementSize);
tree->search (i->begin (), &calculator);
size += i->length ();
}
buffer->configure (size);
}
delete tree;
}
void
Distributor::distribute ()
{
for (BufferMap::iterator b = buffers.begin (); b != buffers.end (); ++b)
{
FIBO* buffer = b->first;
Intervals& intervals = b->second;
ContDataT* src = static_cast (dataMap->base ());
ContDataT* dest = static_cast (buffer->insert ());
for (Intervals::iterator i = intervals.begin ();
i != intervals.end ();
++i)
{
MUSIC_LOGR ("src = " << static_cast (src)
<< ", begin = " << i->begin ()
<< ", length = " << i->length ());
memcpy (dest, src + i->begin (), i->length ());
dest += i->length ();
}
}
}
}
#endif
music-1.2.1/src/music.hh 0000644 0005140 0005140 00000001612 12652207070 011777 0000000 0000000 #ifndef MUSIC_HH
/*
* This file is part of MUSIC.
* Copyright (C) 2007, 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/runtime.hh"
#include "music/setup.hh"
#include "music/permutation_index.hh"
#include "music/array_data.hh"
#define MUSIC_HH
#endif /* MUSIC_HH */
music-1.2.1/src/array_data.cc 0000644 0005140 0005140 00000002666 14372254427 012777 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2007, 2008, 2009, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
// This header file needs to be included first since array_data.hh
// includes which musy be included first on BG/L
#include "music/array_data.hh"
#if MUSIC_USE_MPI
#include "music/linear_index.hh"
namespace MUSIC {
ArrayData::ArrayData (void* buffer, MPI_Datatype type, IndexMap* map)
: DataMap (buffer), type_ (type), indexMap_ (map->copy ())
{
}
ArrayData::~ArrayData ()
{
delete indexMap_;
}
ArrayData::ArrayData (void* buffer,
MPI_Datatype type,
int baseIndex,
int size)
: DataMap (buffer)
{
type_ = type;
indexMap_ = new LinearIndex (baseIndex, size);
}
DataMap*
ArrayData::copy ()
{
return new ArrayData (base (), type_, indexMap_);
}
}
#endif
music-1.2.1/src/configuration.cc 0000644 0005140 0005140 00000017344 14153770752 013537 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2007, 2008, 2009, 2012, 2021 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/configuration.hh" // Must be included first on BG/L
#include "music/debug.hh"
extern "C" {
#include
}
#include "music/ioutils.hh"
#include "music/error.hh"
#include
#include
namespace MUSIC {
const char* const Configuration::configEnvVarName = "_MUSIC_CONFIG_";
// const char* const Configuration::mapFileName = "music.map";
/*
* This is the syntax of the _MUSIC_CONFIG_ variable:
*
* POSTPONE:COLOR means that configuration is postponed until the
* first port is created. At that time, the variable is expected to
* contain the full configuration information:
*
*
* APPLICATIONNAME:COLOR:APPLICATIONMAP:CONNECTIVITYMAP:CONFIGDICT
*
* APPLICATIONNAME = name of this application (string)
*
* COLOR = index of section in music configuration file
*
* APPLICATIONMAP = SIZE:...:NAMEk:NPROCk:...
*
* SIZE = number of applications (integer)
*
* NAMEk = name of application k
*
* NPROCk = number of processes in application k
*
* CONNECTIVITYMAP = SIZE:...:PORTNAMEk:DIRECTIONk:WIDTHk:CONNECTIONSk:...
*
* SIZE = number of ports of this application
*
* PORTNAMEk = port name
*
* DIRECTIONk = port direction, 0 = OUTPUT, 1 = INPUT
*
* WIDTHk = port width
*
* CONNECTIONSk = SIZE:...:
* RECAPPNAME:RECPORTNAME:RECPORTCODE:REMOTELEADER:NREMOTEPROCS
* :COMMTYPE:PROCMETHOD:...
*
* RECAPPNAME = name of receiving application
*
* RECPORTNAME = name of receiver port
*
* RECPORTCODE = code unique for every receiver port
*
* REMOTELEADER = lowest rank of the remote application
*
* NREMOTEPROCS = number of processes in the remote application
*
* COMMTYPE = communication algorithm, 0 = collective, 1 = point-to-point
*
* PROCMETHOD = processing method, 0 = tree, 1 = table
*
* CONFIGDICT = ...:VARNAMEk=VALUEk:...
*/
Configuration::Configuration ()
{
init ();
}
#if MUSIC_USE_MPI
Configuration::Configuration (std::string configStr)
{
init ();
parse (configStr);
}
#endif
Configuration::~Configuration ()
{
delete connectivityMap_;
delete applications_;
if (defaultConfig_ != NULL)
delete defaultConfig_;
}
void
Configuration::init ()
{
applications_ = new ApplicationMap ();
connectivityMap_ = new Connectivity ();
defaultConfig_ = NULL;
}
#if MUSIC_USE_MPI
void
Configuration::parse(std::string configStr)
{
std::istringstream env (configStr);
setName (IOUtils::read (env));
env.ignore (); // delim
// do not need color information,
// but we can use for error check
IOUtils::read (env);
env.ignore (); // delim
applications_->read (env);
env.ignore ();
std::map leaders = applications_->assignLeaders( Name ());
connectivityMap_->read (env, leaders);
// parse config string
while (!env.eof ())
{
env.ignore ();
std::string name = IOUtils::read (env, '=');
env.ignore ();
std::string v = IOUtils::read (env);
// std::cerr << name << " " << v << std::endl;
insert (name, v );
}
}
#endif
void
Configuration::write (std::ostringstream& env, Configuration* mask)
{
std::map::iterator pos;
for (pos = dict_.begin (); pos != dict_.end (); ++pos)
{
std::string name = pos->first;
if (!(mask && mask->lookup (name)))
{
env << ':' << name << '=';
IOUtils::write (env, pos->second);
}
}
}
void
Configuration::writeEnv ()
{
std::ostringstream env;
env << Name () << ':' << Color () << ':';
applications_->write (env);
env << ':';
connectivityMap_->write (env);
write (env, 0);
if (defaultConfig_ != NULL)
defaultConfig_->write (env, this);
setenv (configEnvVarName, env.str ().c_str (), 1);
}
bool
Configuration::lookup(std::string name)
{
return dict_.find(name) != dict_.end();
}
bool
Configuration::lookup(std::string name, std::string* result)
{
std::map::iterator pos = dict_.find(name);
if (pos == dict_.end())
return defaultConfig_ && defaultConfig_->lookup(name, result);
*result = pos->second;
return true;
}
bool
Configuration::lookup(std::string name, int* result)
{
std::map::iterator pos = dict_.find(name);
if (pos == dict_.end())
return defaultConfig_ && defaultConfig_->lookup(name, result);
std::istringstream iss(pos->second);
if (! (iss >> *result).fail())
return true;
std::ostringstream oss;
oss << "var " << name << " given wrong type (" << pos->second
<< "; expected int) in config file";
error(oss.str());
return true; // Doesn't happen! Just for compiler!
}
bool
Configuration::lookup(std::string name, double* result)
{
std::map::iterator pos = dict_.find(name);
if (pos == dict_.end())
return defaultConfig_ && defaultConfig_->lookup (name, result);
std::istringstream iss(pos->second);
if (! (iss >> *result).fail())
return true;
std::ostringstream oss;
oss << "var " << name << " given wrong type (" << pos->second
<< "; expected double) in config file";
error(oss.str());
return true; // Doesn't happen! Just for compiler!
}
bool
Configuration::lookup (std::string name, bool* result)
{
std::map::iterator pos = dict_.find (name);
if (pos == dict_.end ())
return defaultConfig_ && defaultConfig_->lookup (name, result);
std::istringstream iss(pos->second);
if (! (iss >> std::boolalpha >> *result).fail ())
return true;
std::ostringstream oss;
oss << "var " << name << " given wrong type (" << pos->second
<< "; expected bool) in config file";
error(oss.str ());
return true; // Doesn't happen! Just for compiler!
}
std::string
Configuration::Name ()
{
return app_name_;
}
void
Configuration::setName (std::string app_name)
{
app_name_ = app_name;
}
int
Configuration::Color()
{
return applications_->lookup (app_name_)->color ();
}
int
Configuration::Leader()
{
ApplicationInfo* info = applications_->lookup (app_name_);
return info == 0 ? -1 : info->leader ();
}
void
Configuration::insert (std::string name, std::string value)
{
dict_.insert (std::make_pair (name, value));
}
ApplicationMap*
Configuration::applications ()
{
return applications_;
}
Configuration*
Configuration::defaultConfig ()
{
if (defaultConfig_ == NULL)
defaultConfig_ = new Configuration();
return defaultConfig_;
}
Connectivity*
Configuration::connectivityMap ()
{
return connectivityMap_;
}
const Configuration::ConfigDict &
Configuration::getDict()
{
return dict_;
}
void
Configuration::setDict(const Configuration::ConfigDict &dict)
{
dict_ = dict;
}
void
Configuration::resetDict()
{
dict_ = Configuration::ConfigDict ();
}
}
music-1.2.1/src/parse.cc 0000644 0005140 0005140 00000004623 12652207070 011764 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2007, 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/parse.hh"
#include
#include
#include
namespace MUSIC {
Parser::Parser (std::string s)
: in (new std::istringstream (s))
{
}
Parser::~Parser ()
{
delete in;
}
void
Parser::ignoreWhitespace ()
{
while (isspace (in->peek ()))
in->ignore ();
}
void
Parser::parseString (std::ostringstream& arg, char delim)
{
while (true)
{
int c;
switch (c = in->get ())
{
case '\'':
case '"':
if (c == delim)
break;
default:
arg << (char) c;
continue;
case '\\':
arg << (char) in->get ();
continue;
case EOF:
// NOTE: generate error message
break;
}
break;
}
}
std::string
Parser::nextArg ()
{
std::ostringstream arg;
while (true)
{
int c;
switch (c = in->get ())
{
default:
arg << (char) c;
continue;
case '\\':
arg << (char) in->get ();
continue;
case '\'':
case '"':
parseString (arg, c);
continue;
case ' ':
case '\t':
case EOF:
break;
}
break;
}
return arg.str ();
}
char **
parseArgs (std::string cmd,
std::string argstring,
int* argc)
{
Parser in (argstring);
std::vector args;
args.push_back (cmd);
in.ignoreWhitespace ();
while (! in.eof ())
args.push_back (in.nextArg ());
int nArgs = args.size ();
char** result = new char*[nArgs + 1];
for (int i = 0; i < nArgs; ++i)
{
int len = args[i].length ();
result[i] = new char[len + 1];
args[i].copy (result[i], len);
result[i][len] = '\0';
}
result[nArgs] = 0;
*argc = nArgs;
return result;
}
}
music-1.2.1/src/music-c.h 0000644 0005140 0005140 00000015167 12652207070 012061 0000000 0000000 #ifndef MUSIC_C_H
/*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/music-config.hh"
#if MUSIC_USE_MPI
#include
#if MUSIC_HAVE_SIZE_T
#include
#else
typedef int size_t;
#endif
/* Setup */
typedef struct MUSIC_Setup MUSIC_Setup;
MUSIC_Setup *MUSIC_createSetup (int *argc, char ***argv);
MUSIC_Setup *MUSIC_createSetupThread (int *argc,
char ***argv,
int required,
int* provided);
/* Communicators */
#ifndef BUILDING_MUSIC_LIBRARY
MPI_Comm MUSIC_setupCommunicator (MUSIC_Setup *setup);
#endif
/* Ports */
typedef struct MUSIC_ContOutputPort MUSIC_ContOutputPort;
typedef struct MUSIC_ContInputPort MUSIC_ContInputPort;
typedef struct MUSIC_EventOutputPort MUSIC_EventOutputPort;
typedef struct MUSIC_EventInputPort MUSIC_EventInputPort;
typedef struct MUSIC_MessageOutputPort MUSIC_MessageOutputPort;
typedef struct MUSIC_MessageInputPort MUSIC_MessageInputPort;
MUSIC_ContOutputPort *MUSIC_publishContOutput (MUSIC_Setup *setup, char *id);
MUSIC_ContInputPort *MUSIC_publishContInput (MUSIC_Setup *setup, char *id);
MUSIC_EventOutputPort *MUSIC_publishEventOutput (MUSIC_Setup *setup, char *id);
MUSIC_EventInputPort *MUSIC_publishEventInput (MUSIC_Setup *setup, char *id);
MUSIC_MessageOutputPort *MUSIC_publishMessageOutput (MUSIC_Setup *setup, char *id);
MUSIC_MessageInputPort *MUSIC_publishMessageInput (MUSIC_Setup *setup, char *id);
/* remedius
* Free of the ports is done by the Runtime instance
*/
/*void MUSIC_destroyContOutput (MUSIC_ContOutputPort* port);
void MUSIC_destroyContInput (MUSIC_ContInputPort* port);
void MUSIC_destroyEventOutput (MUSIC_EventOutputPort* port);
void MUSIC_destroyEventInput (MUSIC_EventInputPort* port);
void MUSIC_destroyMessageOutput (MUSIC_MessageOutputPort* port);
void MUSIC_destroyMessageInput (MUSIC_MessageInputPort* port);
*/
/* General port methods */
int MUSIC_ContOutputPort_isConnected (MUSIC_ContOutputPort *port);
int MUSIC_ContInputPort_isConnected (MUSIC_ContInputPort *port);
int MUSIC_EventOutputPort_isConnected (MUSIC_EventOutputPort *port);
int MUSIC_EventInputPort_isConnected (MUSIC_EventInputPort *port);
int MUSIC_MessageOutputPort_isConnected (MUSIC_MessageOutputPort *port);
int MUSIC_MessageInputPort_isConnected (MUSIC_MessageInputPort *port);
int MUSIC_ContOutputPort_hasWidth (MUSIC_ContOutputPort *port);
int MUSIC_ContInputPort_hasWidth (MUSIC_ContInputPort *port);
int MUSIC_EventOutputPort_hasWidth (MUSIC_EventOutputPort *port);
int MUSIC_EventInputPort_hasWidth (MUSIC_EventInputPort *port);
int MUSIC_ContOutputPort_width (MUSIC_ContOutputPort *port);
int MUSIC_ContInputPort_width (MUSIC_ContInputPort *port);
int MUSIC_EventOutputPort_width (MUSIC_EventOutputPort *port);
int MUSIC_EventInputPort_width (MUSIC_EventInputPort *port);
/* Mapping */
/* Data maps */
typedef struct MUSIC_DataMap MUSIC_DataMap;
typedef struct MUSIC_ContData MUSIC_ContData;
typedef struct MUSIC_ArrayData MUSIC_ArrayData;
/* Index maps */
typedef struct MUSIC_IndexMap MUSIC_IndexMap;
typedef struct MUSIC_PermutationIndex MUSIC_PermutationIndex;
typedef struct MUSIC_LinearIndex MUSIC_LinearIndex;
/* No arguments are optional. */
void MUSIC_ContOutputPort_map (MUSIC_ContOutputPort *port,
MUSIC_ContData *dmap,
int maxBuffered);
void MUSIC_ContInputPort_map (MUSIC_ContInputPort *port,
MUSIC_ContData *dmap,
double delay,
int maxBuffered,
int interpolate);
void MUSIC_EventOutputPort_mapGlobalIndex (MUSIC_EventOutputPort *Port,
MUSIC_IndexMap *indices,
int maxBuffered);
void MUSIC_EventOutputPort_mapLocalIndex (MUSIC_EventOutputPort *Port,
MUSIC_IndexMap *indices,
int maxBuffered);
typedef void MUSIC_EventHandler (double t, int id);
void MUSIC_EventInputPort_mapGlobalIndex (MUSIC_EventInputPort *port,
MUSIC_IndexMap *indices,
MUSIC_EventHandler *handleEvent,
double accLatency,
int maxBuffered);
void MUSIC_EventInputPort_mapLocalIndex (MUSIC_EventInputPort *port,
MUSIC_IndexMap *indices,
MUSIC_EventHandler *handleEvent,
double accLatency,
int maxBuffered);
void MUSIC_MessageOutputPort_map_no_handler (MUSIC_MessageOutputPort *port);
void MUSIC_MessageOutputPort_map (MUSIC_MessageOutputPort *port,
int maxBuffered);
typedef void MUSIC_MessageHandler (double t, void *msg, size_t size);
void MUSIC_MessageInputPort_map (MUSIC_MessageInputPort *port,
MUSIC_MessageHandler *handleMessage,
double accLatency,
int maxBuffered);
/* Index maps */
MUSIC_PermutationIndex *MUSIC_createPermutationIndex (int *indices,
int size);
void MUSIC_destroyPermutationIndex (MUSIC_PermutationIndex *Index);
MUSIC_LinearIndex *MUSIC_createLinearIndex (int baseIndex,
int size);
void MUSIC_destroyLinearIndex (MUSIC_LinearIndex *Index);
/* Exception: The map argument can take any type of index map. */
MUSIC_ArrayData *MUSIC_createArrayData (void *buffer,
MPI_Datatype type,
void *map);
/* Exception: MUSIC_createLinearArrayData corresponds to
c++ MUSIC::ArrayData::ArrayData (..., ..., ..., ...) */
MUSIC_ArrayData *MUSIC_createLinearArrayData (void *buffer,
MPI_Datatype type,
int baseIndex,
int size);
void MUSIC_destroyArrayData (MUSIC_ArrayData *arrayData);
/* Configuration variables */
/* Exceptions: Result is char *
Extra maxlen argument prevents buffer overflow.
Result is terminated by \0 unless longer than maxlen - 1 */
int MUSIC_configString (MUSIC_Setup *setup,
char *name,
char *result,
size_t maxlen);
int MUSIC_configInt (MUSIC_Setup *setup, char *name, int *result);
int MUSIC_configDouble (MUSIC_Setup *setup, char *name, double *result);
/* Runtime */
typedef struct MUSIC_Runtime MUSIC_Runtime;
MUSIC_Runtime *MUSIC_createRuntime (MUSIC_Setup *setup, double h);
void MUSIC_tick (MUSIC_Runtime *runtime);
double MUSIC_time (MUSIC_Runtime *runtime);
/* Finalization */
void MUSIC_destroyRuntime (MUSIC_Runtime *runtime);
#endif
#define MUSIC_C_H
#endif /* MUSIC_C_H */
music-1.2.1/src/music-c.cc 0000644 0005140 0005140 00000027004 12652207070 012210 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2008, 2009 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music.hh"
#if MUSIC_USE_MPI
#include
#include
extern "C" {
#include "music-c.h"
/* Setup */
MUSIC_Setup *
MUSIC_createSetup (int *argc, char ***argv)
{
return (MUSIC_Setup *) new MUSIC::Setup (*argc, *argv);
}
MUSIC_Setup *
MUSIC_createSetupThread (int *argc, char ***argv, int required, int *provided)
{
return (MUSIC_Setup *) new MUSIC::Setup (*argc, *argv, required, provided);
}
/* Communicators */
MPI_Comm
MUSIC_setupCommunicatorGlue (MUSIC_Setup *setup)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MPI_Comm) cxxSetup->communicator ();
}
/* Port creation */
MUSIC_ContOutputPort *
MUSIC_publishContOutput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_ContOutputPort *) cxxSetup->publishContOutput (id);
}
MUSIC_ContInputPort *
MUSIC_publishContInput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_ContInputPort *) cxxSetup->publishContInput(id);
}
MUSIC_EventOutputPort *
MUSIC_publishEventOutput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_EventOutputPort *) cxxSetup->publishEventOutput(id);
}
MUSIC_EventInputPort *
MUSIC_publishEventInput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_EventInputPort *) cxxSetup->publishEventInput(id);
}
MUSIC_MessageOutputPort *
MUSIC_publishMessageOutput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_MessageOutputPort *) cxxSetup->publishMessageOutput(id);
}
MUSIC_MessageInputPort *
MUSIC_publishMessageInput (MUSIC_Setup *setup, char *id)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_MessageInputPort *) cxxSetup->publishMessageInput(id);
}
/*
void
MUSIC_destroyContOutput (MUSIC_ContOutputPort* Port)
{
delete (MUSIC::ContOutputPort *) Port;
}
void
MUSIC_destroyContInput (MUSIC_ContInputPort* Port)
{
delete (MUSIC::ContInputPort *) Port;
}
void
MUSIC_destroyEventOutput (MUSIC_EventOutputPort* Port)
{
delete (MUSIC::EventOutputPort *) Port;
}
void
MUSIC_destroyEventInput (MUSIC_EventInputPort* Port)
{
delete (MUSIC::EventInputPort *) Port;
}
void
MUSIC_destroyMessageOutput (MUSIC_MessageOutputPort* Port)
{
delete (MUSIC::MessageOutputPort *) Port;
}
void
MUSIC_destroyMessageInput (MUSIC_MessageInputPort* Port)
{
delete (MUSIC::MessageInputPort *) Port;
}
*/
/* General port methods */
int
MUSIC_ContOutputPort_isConnected (MUSIC_ContOutputPort *Port)
{
MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_ContInputPort_isConnected (MUSIC_ContInputPort *Port)
{
MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_EventOutputPort_isConnected (MUSIC_EventOutputPort *Port)
{
MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_EventInputPort_isConnected (MUSIC_EventInputPort *Port)
{
MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_MessageOutputPort_isConnected (MUSIC_MessageOutputPort *Port)
{
MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_MessageInputPort_isConnected (MUSIC_MessageInputPort *Port)
{
MUSIC::MessageInputPort* cxxPort = (MUSIC::MessageInputPort *) Port;
return cxxPort->isConnected ();
}
int
MUSIC_ContOutputPort_hasWidth (MUSIC_ContOutputPort *Port)
{
MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
return cxxPort->hasWidth ();
}
int
MUSIC_ContInputPort_hasWidth (MUSIC_ContInputPort *Port)
{
MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
return cxxPort->hasWidth ();
}
int
MUSIC_EventOutputPort_hasWidth (MUSIC_EventOutputPort *Port)
{
MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
return cxxPort->hasWidth ();
}
int
MUSIC_EventInputPort_hasWidth (MUSIC_EventInputPort *Port)
{
MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
return cxxPort->hasWidth ();
}
int
MUSIC_ContOutputPort_width (MUSIC_ContOutputPort *Port)
{
MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
return cxxPort->width ();
}
int
MUSIC_ContInputPort_width (MUSIC_ContInputPort *Port)
{
MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
return cxxPort->width ();
}
int
MUSIC_EventOutputPort_width (MUSIC_EventOutputPort *Port)
{
MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
return cxxPort->width ();
}
int
MUSIC_EventInputPort_width (MUSIC_EventInputPort *Port)
{
MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
return cxxPort->width ();
}
/* Mapping */
/* No arguments are optional. */
void
MUSIC_ContOutputPort_map (MUSIC_ContOutputPort *Port,
MUSIC_ContData *dmap,
int maxBuffered)
{
MUSIC::ContOutputPort* cxxPort = (MUSIC::ContOutputPort *) Port;
MUSIC::ContData* cxxDmap = (MUSIC::ContData *) dmap;
cxxPort->map (cxxDmap, maxBuffered);
}
void
MUSIC_ContInputPort_map (MUSIC_ContInputPort *Port,
MUSIC_ContData *dmap,
double delay,
int maxBuffered,
int interpolate)
{
MUSIC::ContInputPort* cxxPort = (MUSIC::ContInputPort *) Port;
MUSIC::ContData* cxxDmap = (MUSIC::ContData *) dmap;
cxxPort->map (cxxDmap, delay, maxBuffered, interpolate);
}
void
MUSIC_EventOutputPort_mapGlobalIndex (MUSIC_EventOutputPort *Port,
MUSIC_IndexMap *indices,
int maxBuffered)
{
MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
cxxPort->map (cxxIndices, MUSIC::Index::GLOBAL, maxBuffered);
}
void
MUSIC_EventOutputPort_mapLocalIndex (MUSIC_EventOutputPort *Port,
MUSIC_IndexMap *indices,
int maxBuffered)
{
MUSIC::EventOutputPort* cxxPort = (MUSIC::EventOutputPort *) Port;
MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
cxxPort->map (cxxIndices, MUSIC::Index::LOCAL, maxBuffered);
}
typedef void MUSIC_EventHandler (double t, int id);
void
MUSIC_EventInputPort_mapGlobalIndex (MUSIC_EventInputPort *Port,
MUSIC_IndexMap *indices,
MUSIC_EventHandler *handleEvent,
double accLatency,
int maxBuffered)
{
MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
MUSIC::EventHandlerGlobalIndexProxy* cxxHandleEvent =
cxxPort->allocEventHandlerGlobalIndexProxy (handleEvent);
cxxPort->map (cxxIndices, cxxHandleEvent, accLatency, maxBuffered);
}
void
MUSIC_EventInputPort_mapLocalIndex (MUSIC_EventInputPort *Port,
MUSIC_IndexMap *indices,
MUSIC_EventHandler *handleEvent,
double accLatency,
int maxBuffered)
{
MUSIC::EventInputPort* cxxPort = (MUSIC::EventInputPort *) Port;
MUSIC::IndexMap* cxxIndices = (MUSIC::IndexMap *) indices;
MUSIC::EventHandlerLocalIndexProxy* cxxHandleEvent =
cxxPort->allocEventHandlerLocalIndexProxy (handleEvent);
cxxPort->map (cxxIndices, cxxHandleEvent, accLatency, maxBuffered);
}
void
MUSIC_MessageOutputPort_map_no_handler (MUSIC_MessageOutputPort *Port)
{
MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
cxxPort->map ();
}
void
MUSIC_MessageOutputPort_map (MUSIC_MessageOutputPort *Port,
int maxBuffered)
{
MUSIC::MessageOutputPort* cxxPort = (MUSIC::MessageOutputPort *) Port;
cxxPort->map (maxBuffered);
}
typedef void MUSIC_MessageHandler (double t, void *msg, size_t size);
void
MUSIC_MessageInputPort_map (MUSIC_MessageInputPort *Port,
MUSIC_MessageHandler *handleMessage,
double accLatency,
int maxBuffered)
{
MUSIC::MessageInputPort* cxxPort = (MUSIC::MessageInputPort *) Port;
MUSIC::MessageHandlerProxy* cxxHandleMessage =
cxxPort->allocMessageHandlerProxy (handleMessage);
cxxPort->map (cxxHandleMessage, accLatency, maxBuffered);
}
/* Index maps */
MUSIC_PermutationIndex *
MUSIC_createPermutationIndex (int *indices,
int size)
{
void* data = static_cast (indices);
return (MUSIC_PermutationIndex *)
new MUSIC::PermutationIndex (static_cast (data),
size);
}
void
MUSIC_destroyPermutationIndex (MUSIC_PermutationIndex *Index)
{
delete (MUSIC::PermutationIndex *) Index;
}
MUSIC_LinearIndex *
MUSIC_createLinearIndex (int baseIndex,
int size)
{
return (MUSIC_LinearIndex *) new MUSIC::LinearIndex (baseIndex, size);
}
void
MUSIC_destroyLinearIndex (MUSIC_LinearIndex *Index)
{
delete (MUSIC::LinearIndex *) Index;
}
/* Data maps */
/* Exception: The map argument can take any type of index map. */
MUSIC_ArrayData *
MUSIC_createArrayData (void *buffer,
MPI_Datatype type,
void *map)
{
MUSIC::IndexMap* cxxMap = (MUSIC::IndexMap *) map;
return (MUSIC_ArrayData *) new MUSIC::ArrayData (buffer, type, cxxMap);
}
/* Exception: MUSIC_createLinearArrayData corresponds to
c++ MUSIC::ArrayData::ArrayData (..., ..., ..., ...) */
MUSIC_ArrayData *
MUSIC_createLinearArrayData (void *buffer,
MPI_Datatype type,
int baseIndex,
int size)
{
return (MUSIC_ArrayData *) new MUSIC::ArrayData (buffer,
type,
baseIndex,
size);
}
void
MUSIC_destroyArrayData (MUSIC_ArrayData *ArrayData)
{
delete (MUSIC::ArrayData *) ArrayData;
}
/* Configuration variables */
/* Exceptions: Result is char *
Extra maxlen argument prevents buffer overflow.
Result is terminated by \0 unless longer than maxlen - 1 */
int
MUSIC_configString (MUSIC_Setup *setup,
char *name,
char *result,
size_t maxlen)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
std::string cxxResult;
int res = cxxSetup->config (string (name), &cxxResult);
strncpy(result, cxxResult.c_str (), maxlen);
return res;
}
int
MUSIC_configInt (MUSIC_Setup *setup, char *name, int *result)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return cxxSetup->config (string(name), result);
}
int
MUSIC_configDouble (MUSIC_Setup *setup, char *name, double *result)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return cxxSetup->config (string(name), result);
}
/* Runtime */
MUSIC_Runtime *
MUSIC_createRuntime (MUSIC_Setup *setup, double h)
{
MUSIC::Setup* cxxSetup = (MUSIC::Setup *) setup;
return (MUSIC_Runtime *) new MUSIC::Runtime (cxxSetup, h);
}
void
MUSIC_tick (MUSIC_Runtime *runtime)
{
MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
cxxRuntime->tick ();
}
double
MUSIC_time (MUSIC_Runtime *runtime)
{
MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
return cxxRuntime->time ();
}
/* Finalization */
void
MUSIC_destroyRuntime (MUSIC_Runtime *runtime)
{
MUSIC::Runtime* cxxRuntime = (MUSIC::Runtime *) runtime;
delete cxxRuntime;
}
}
#endif
music-1.2.1/src/predict_rank-c.cc 0000644 0005140 0005140 00000001603 12652207070 013532 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2011 CSC, KTH
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include "music/predict_rank.hh"
extern "C" {
#include "music/predict_rank-c.h"
int MUSIC_predictRank (int argc, char **argv) {
return MUSIC::predictRank (argc, argv);
}
}
music-1.2.1/src/runtime.cc 0000644 0005140 0005140 00000037405 14372254427 012352 0000000 0000000 /*
* This file is part of MUSIC.
* Copyright (C) 2007-2012, 2022 INCF
*
* MUSIC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MUSIC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
//#define MUSIC_DEBUG
//#define MUSIC_AFTER_RUNTIME_CONSTRUCTOR_REPORT
#include "music/runtime.hh"
#if MUSIC_USE_MPI
#include
#include "music/temporal.hh"
#include "music/error.hh"
#include "music/connection.hh"
#include "music/memory.hh"
#include
#include
#include
#include
namespace MUSIC
{
bool Runtime::isInstantiated_ = false;
Runtime::Runtime (Setup* s, double h)
: mAgent (0)
{
checkInstantiatedOnce (isInstantiated_, "Runtime");
s->maybePostponedSetup ();
app_name = s->applicationName ();
leader_ = s->leader ();
/* remedius
* new type of subconnectors for collective communication was created.
*/
//CollectiveSubconnectors collectiveSubconnectors;
// Setup the MUSIC clock
localTime = Clock (s->timebase (), h);
comm = s->communicator ();
/* remedius
* copy ports in order to delete them afterwards (it was probably a memory leak in previous revision)
*/
for (std::vector::iterator it = s->ports ()->begin ();
it < s->ports ()->end (); it++)
ports.push_back ( (*it));
Connections* connections = s->connections ();
scheduler = new Scheduler (comm, leader_);
if (s->launchedByMusic ())
{
takeTickingPorts (s);
// create a total order for connectors and
// establish connection to peers
connectToPeers (connections);
// specialize connectors and fill up connectors vector
specializeConnectors (connections);
// from here we can start using the vector `connectors'
// negotiate where to route data and fill up subconnector vectors
spatialNegotiation ();
// build data routing tables
buildTables (s);
takePreCommunicators ();
takePostCommunicators ();
// negotiate timing constraints for synchronizers
temporalNegotiation (s, connections);
#if 0
if (needsMultiCommunication ())
{
#endif
sAgents.push_back (mAgent = new MulticommAgent (scheduler));
scheduler->setAgent (mAgent);
#if 0
}
#endif
sAgents.push_back (new UnicommAgent (scheduler));
scheduler->setAgent (sAgents[sAgents.size () - 1]);
// final initialization before simulation starts
initialize (s);
}
else
{
sAgents.push_back (new DummyAgent (scheduler));
scheduler->setAgent (sAgents[0]);
scheduler->initializeAgentState ();
}
delete s;
#ifdef MUSIC_AFTER_RUNTIME_CONSTRUCTOR_REPORT
if (mpi_get_rank (MPI_COMM_WORLD) == 0)
reportMem ();
#if 0
// Code used for debugging and analysis
for (std::vector::iterator connector = connectors.begin ();
connector != connectors.end ();
++connector)
(*connector)->report ();
#endif
#endif
}
Runtime::~Runtime ()
{
// delete connectors
for (std::vector::iterator connector = connectors.begin ();
connector != connectors.end (); ++connector)
delete *connector;
#if 0
/* MDJ 2012-08-07
Some applications assume that they need to delete the ports.
Until we have made a decision what is the proper usage pattern,
this code is disabled. */
// delete ports
for (std::vector::iterator it=ports.begin(); it < ports.end(); it++ )
delete (*it);
#endif
for (std::vector::iterator it = sAgents.begin ();
it != sAgents.end (); it++)
delete (*it);
delete scheduler;
isInstantiated_ = false;
}
bool
Runtime::needsMultiCommunication ()
{
std::vector::iterator c;
for (c = connectors.begin (); c != connectors.end (); ++c)
if ((*c)->needsMultiCommunication ())
return true;
return false;
}
void
Runtime::takeTickingPorts (Setup* s)
{
std::vector::iterator p;
for (p = ports.begin (); p != ports.end (); ++p)
{
TickingPort* tp = dynamic_cast (*p);
if (tp != NULL)
tickingPorts.push_back (tp);
}
}
void
Runtime::takePreCommunicators ()
{
std::vector::iterator c;
for (c = connectors.begin (); c != connectors.end (); ++c)
{
PreCommunicationConnector* preCommunicationConnector =
dynamic_cast