Bug 1753 Halting Issue with DistributedSimulatorImpl

This commit is contained in:
Steven Smith
2013-08-15 14:45:42 -04:00
parent 9bc367b99f
commit 0e5a67fd20
4 changed files with 340 additions and 2811 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,8 @@ def register_types(module):
module.add_class('CallbackBase', import_from_module='ns.core')
## event-id.h (module 'core'): ns3::EventId [class]
module.add_class('EventId', import_from_module='ns.core')
## hash.h (module 'core'): ns3::Hasher [class]
module.add_class('Hasher', import_from_module='ns.core')
## distributed-simulator-impl.h (module 'mpi'): ns3::LbtsMessage [class]
module.add_class('LbtsMessage')
## mpi-interface.h (module 'mpi'): ns3::MpiInterface [class]
@@ -114,6 +116,8 @@ def register_types(module):
module.add_class('SimpleRefCount', automatic_type_narrowing=True, import_from_module='ns.core', template_parameters=['ns3::CallbackImplBase', 'ns3::empty', 'ns3::DefaultDeleter<ns3::CallbackImplBase>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::EventImpl, ns3::empty, ns3::DefaultDeleter<ns3::EventImpl> > [class]
module.add_class('SimpleRefCount', automatic_type_narrowing=True, import_from_module='ns.core', template_parameters=['ns3::EventImpl', 'ns3::empty', 'ns3::DefaultDeleter<ns3::EventImpl>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> > [class]
module.add_class('SimpleRefCount', automatic_type_narrowing=True, import_from_module='ns.core', template_parameters=['ns3::Hash::Implementation', 'ns3::empty', 'ns3::DefaultDeleter<ns3::Hash::Implementation>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::NixVector, ns3::empty, ns3::DefaultDeleter<ns3::NixVector> > [class]
module.add_class('SimpleRefCount', automatic_type_narrowing=True, import_from_module='ns.core', template_parameters=['ns3::NixVector', 'ns3::empty', 'ns3::DefaultDeleter<ns3::NixVector>'], parent=root_module['ns3::empty'], memory_policy=cppclass.ReferenceCountingMethodsPolicy(incref_method='Ref', decref_method='Unref', peekref_method='GetReferenceCount'))
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Packet, ns3::empty, ns3::DefaultDeleter<ns3::Packet> > [class]
@@ -172,11 +176,47 @@ def register_types(module):
nested_module = module.add_cpp_namespace('FatalImpl')
register_types_ns3_FatalImpl(nested_module)
## Register a nested module for the namespace Hash
nested_module = module.add_cpp_namespace('Hash')
register_types_ns3_Hash(nested_module)
def register_types_ns3_FatalImpl(module):
root_module = module.get_root()
def register_types_ns3_Hash(module):
root_module = module.get_root()
## hash-function.h (module 'core'): ns3::Hash::Implementation [class]
module.add_class('Implementation', import_from_module='ns.core', parent=root_module['ns3::SimpleRefCount< ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> >'])
typehandlers.add_type_alias('uint32_t ( * ) ( char const *, size_t ) *', 'ns3::Hash::Hash32Function_ptr')
typehandlers.add_type_alias('uint32_t ( * ) ( char const *, size_t ) **', 'ns3::Hash::Hash32Function_ptr*')
typehandlers.add_type_alias('uint32_t ( * ) ( char const *, size_t ) *&', 'ns3::Hash::Hash32Function_ptr&')
typehandlers.add_type_alias('uint64_t ( * ) ( char const *, size_t ) *', 'ns3::Hash::Hash64Function_ptr')
typehandlers.add_type_alias('uint64_t ( * ) ( char const *, size_t ) **', 'ns3::Hash::Hash64Function_ptr*')
typehandlers.add_type_alias('uint64_t ( * ) ( char const *, size_t ) *&', 'ns3::Hash::Hash64Function_ptr&')
## Register a nested module for the namespace Function
nested_module = module.add_cpp_namespace('Function')
register_types_ns3_Hash_Function(nested_module)
def register_types_ns3_Hash_Function(module):
root_module = module.get_root()
## hash-fnv.h (module 'core'): ns3::Hash::Function::Fnv1a [class]
module.add_class('Fnv1a', import_from_module='ns.core', parent=root_module['ns3::Hash::Implementation'])
## hash-function.h (module 'core'): ns3::Hash::Function::Hash32 [class]
module.add_class('Hash32', import_from_module='ns.core', parent=root_module['ns3::Hash::Implementation'])
## hash-function.h (module 'core'): ns3::Hash::Function::Hash64 [class]
module.add_class('Hash64', import_from_module='ns.core', parent=root_module['ns3::Hash::Implementation'])
## hash-murmur3.h (module 'core'): ns3::Hash::Function::Murmur3 [class]
module.add_class('Murmur3', import_from_module='ns.core', parent=root_module['ns3::Hash::Implementation'])
def register_methods(root_module):
register_Ns3AttributeConstructionList_methods(root_module, root_module['ns3::AttributeConstructionList'])
register_Ns3AttributeConstructionListItem_methods(root_module, root_module['ns3::AttributeConstructionList::Item'])
@@ -189,6 +229,7 @@ def register_methods(root_module):
register_Ns3ByteTagListIteratorItem_methods(root_module, root_module['ns3::ByteTagList::Iterator::Item'])
register_Ns3CallbackBase_methods(root_module, root_module['ns3::CallbackBase'])
register_Ns3EventId_methods(root_module, root_module['ns3::EventId'])
register_Ns3Hasher_methods(root_module, root_module['ns3::Hasher'])
register_Ns3LbtsMessage_methods(root_module, root_module['ns3::LbtsMessage'])
register_Ns3MpiInterface_methods(root_module, root_module['ns3::MpiInterface'])
register_Ns3ObjectBase_methods(root_module, root_module['ns3::ObjectBase'])
@@ -222,6 +263,7 @@ def register_methods(root_module):
register_Ns3SimpleRefCount__Ns3AttributeValue_Ns3Empty_Ns3DefaultDeleter__lt__ns3AttributeValue__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::AttributeValue, ns3::empty, ns3::DefaultDeleter<ns3::AttributeValue> >'])
register_Ns3SimpleRefCount__Ns3CallbackImplBase_Ns3Empty_Ns3DefaultDeleter__lt__ns3CallbackImplBase__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::CallbackImplBase, ns3::empty, ns3::DefaultDeleter<ns3::CallbackImplBase> >'])
register_Ns3SimpleRefCount__Ns3EventImpl_Ns3Empty_Ns3DefaultDeleter__lt__ns3EventImpl__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::EventImpl, ns3::empty, ns3::DefaultDeleter<ns3::EventImpl> >'])
register_Ns3SimpleRefCount__Ns3HashImplementation_Ns3Empty_Ns3DefaultDeleter__lt__ns3HashImplementation__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> >'])
register_Ns3SimpleRefCount__Ns3NixVector_Ns3Empty_Ns3DefaultDeleter__lt__ns3NixVector__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::NixVector, ns3::empty, ns3::DefaultDeleter<ns3::NixVector> >'])
register_Ns3SimpleRefCount__Ns3Packet_Ns3Empty_Ns3DefaultDeleter__lt__ns3Packet__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::Packet, ns3::empty, ns3::DefaultDeleter<ns3::Packet> >'])
register_Ns3SimpleRefCount__Ns3TraceSourceAccessor_Ns3Empty_Ns3DefaultDeleter__lt__ns3TraceSourceAccessor__gt___methods(root_module, root_module['ns3::SimpleRefCount< ns3::TraceSourceAccessor, ns3::empty, ns3::DefaultDeleter<ns3::TraceSourceAccessor> >'])
@@ -246,6 +288,11 @@ def register_methods(root_module):
register_Ns3TimeValue_methods(root_module, root_module['ns3::TimeValue'])
register_Ns3TypeIdChecker_methods(root_module, root_module['ns3::TypeIdChecker'])
register_Ns3TypeIdValue_methods(root_module, root_module['ns3::TypeIdValue'])
register_Ns3HashImplementation_methods(root_module, root_module['ns3::Hash::Implementation'])
register_Ns3HashFunctionFnv1a_methods(root_module, root_module['ns3::Hash::Function::Fnv1a'])
register_Ns3HashFunctionHash32_methods(root_module, root_module['ns3::Hash::Function::Hash32'])
register_Ns3HashFunctionHash64_methods(root_module, root_module['ns3::Hash::Function::Hash64'])
register_Ns3HashFunctionMurmur3_methods(root_module, root_module['ns3::Hash::Function::Murmur3'])
return
def register_Ns3AttributeConstructionList_methods(root_module, cls):
@@ -701,13 +748,42 @@ def register_Ns3EventId_methods(root_module, cls):
is_const=True)
return
def register_Ns3Hasher_methods(root_module, cls):
## hash.h (module 'core'): ns3::Hasher::Hasher(ns3::Hasher const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hasher const &', 'arg0')])
## hash.h (module 'core'): ns3::Hasher::Hasher() [constructor]
cls.add_constructor([])
## hash.h (module 'core'): ns3::Hasher::Hasher(ns3::Ptr<ns3::Hash::Implementation> hp) [constructor]
cls.add_constructor([param('ns3::Ptr< ns3::Hash::Implementation >', 'hp')])
## hash.h (module 'core'): uint32_t ns3::Hasher::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')])
## hash.h (module 'core'): uint32_t ns3::Hasher::GetHash32(std::string const s) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('std::string const', 's')])
## hash.h (module 'core'): uint64_t ns3::Hasher::GetHash64(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('char const *', 'buffer'), param('size_t const', 'size')])
## hash.h (module 'core'): uint64_t ns3::Hasher::GetHash64(std::string const s) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('std::string const', 's')])
## hash.h (module 'core'): ns3::Hasher & ns3::Hasher::clear() [member function]
cls.add_method('clear',
'ns3::Hasher &',
[])
return
def register_Ns3LbtsMessage_methods(root_module, cls):
## distributed-simulator-impl.h (module 'mpi'): ns3::LbtsMessage::LbtsMessage(ns3::LbtsMessage const & arg0) [copy constructor]
cls.add_constructor([param('ns3::LbtsMessage const &', 'arg0')])
## distributed-simulator-impl.h (module 'mpi'): ns3::LbtsMessage::LbtsMessage() [constructor]
cls.add_constructor([])
## distributed-simulator-impl.h (module 'mpi'): ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, ns3::Time const & t) [constructor]
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('ns3::Time const &', 't')])
## distributed-simulator-impl.h (module 'mpi'): ns3::LbtsMessage::LbtsMessage(uint32_t rxc, uint32_t txc, uint32_t id, bool isFinished, ns3::Time const & t) [constructor]
cls.add_constructor([param('uint32_t', 'rxc'), param('uint32_t', 'txc'), param('uint32_t', 'id'), param('bool', 'isFinished'), param('ns3::Time const &', 't')])
## distributed-simulator-impl.h (module 'mpi'): uint32_t ns3::LbtsMessage::GetMyId() [member function]
cls.add_method('GetMyId',
'uint32_t',
@@ -724,6 +800,10 @@ def register_Ns3LbtsMessage_methods(root_module, cls):
cls.add_method('GetTxCount',
'uint32_t',
[])
## distributed-simulator-impl.h (module 'mpi'): bool ns3::LbtsMessage::IsFinished() [member function]
cls.add_method('IsFinished',
'bool',
[])
return
def register_Ns3MpiInterface_methods(root_module, cls):
@@ -1262,6 +1342,11 @@ def register_Ns3TypeId_methods(root_module, cls):
'std::string',
[],
is_const=True)
## type-id.h (module 'core'): uint32_t ns3::TypeId::GetHash() const [member function]
cls.add_method('GetHash',
'uint32_t',
[],
is_const=True)
## type-id.h (module 'core'): std::string ns3::TypeId::GetName() const [member function]
cls.add_method('GetName',
'std::string',
@@ -1321,6 +1406,16 @@ def register_Ns3TypeId_methods(root_module, cls):
'bool',
[param('std::string', 'name'), param('ns3::TypeId::AttributeInformation *', 'info', transfer_ownership=False)],
is_const=True)
## type-id.h (module 'core'): static ns3::TypeId ns3::TypeId::LookupByHash(uint32_t hash) [member function]
cls.add_method('LookupByHash',
'ns3::TypeId',
[param('uint32_t', 'hash')],
is_static=True)
## type-id.h (module 'core'): static bool ns3::TypeId::LookupByHashFailSafe(uint32_t hash, ns3::TypeId * tid) [member function]
cls.add_method('LookupByHashFailSafe',
'bool',
[param('uint32_t', 'hash'), param('ns3::TypeId *', 'tid')],
is_static=True)
## type-id.h (module 'core'): static ns3::TypeId ns3::TypeId::LookupByName(std::string name) [member function]
cls.add_method('LookupByName',
'ns3::TypeId',
@@ -1748,6 +1843,18 @@ def register_Ns3SimpleRefCount__Ns3EventImpl_Ns3Empty_Ns3DefaultDeleter__lt__ns3
is_static=True)
return
def register_Ns3SimpleRefCount__Ns3HashImplementation_Ns3Empty_Ns3DefaultDeleter__lt__ns3HashImplementation__gt___methods(root_module, cls):
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> >::SimpleRefCount() [constructor]
cls.add_constructor([])
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> >::SimpleRefCount(ns3::SimpleRefCount<ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> > const & o) [copy constructor]
cls.add_constructor([param('ns3::SimpleRefCount< ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter< ns3::Hash::Implementation > > const &', 'o')])
## simple-ref-count.h (module 'core'): static void ns3::SimpleRefCount<ns3::Hash::Implementation, ns3::empty, ns3::DefaultDeleter<ns3::Hash::Implementation> >::Cleanup() [member function]
cls.add_method('Cleanup',
'void',
[],
is_static=True)
return
def register_Ns3SimpleRefCount__Ns3NixVector_Ns3Empty_Ns3DefaultDeleter__lt__ns3NixVector__gt___methods(root_module, cls):
## simple-ref-count.h (module 'core'): ns3::SimpleRefCount<ns3::NixVector, ns3::empty, ns3::DefaultDeleter<ns3::NixVector> >::SimpleRefCount() [constructor]
cls.add_constructor([])
@@ -2020,13 +2127,13 @@ def register_Ns3Time_methods(root_module, cls):
'bool',
[],
is_const=True)
## nstime.h (module 'core'): static ns3::Time ns3::Time::MAX() [member function]
cls.add_method('MAX',
## nstime.h (module 'core'): static ns3::Time ns3::Time::Max() [member function]
cls.add_method('Max',
'ns3::Time',
[],
is_static=True)
## nstime.h (module 'core'): static ns3::Time ns3::Time::MIN() [member function]
cls.add_method('MIN',
## nstime.h (module 'core'): static ns3::Time ns3::Time::Min() [member function]
cls.add_method('Min',
'ns3::Time',
[],
is_static=True)
@@ -2765,14 +2872,127 @@ def register_Ns3TypeIdValue_methods(root_module, cls):
[param('ns3::TypeId const &', 'value')])
return
def register_Ns3HashImplementation_methods(root_module, cls):
## hash-function.h (module 'core'): ns3::Hash::Implementation::Implementation(ns3::Hash::Implementation const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hash::Implementation const &', 'arg0')])
## hash-function.h (module 'core'): ns3::Hash::Implementation::Implementation() [constructor]
cls.add_constructor([])
## hash-function.h (module 'core'): uint32_t ns3::Hash::Implementation::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_pure_virtual=True, is_virtual=True)
## hash-function.h (module 'core'): uint64_t ns3::Hash::Implementation::GetHash64(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-function.h (module 'core'): void ns3::Hash::Implementation::clear() [member function]
cls.add_method('clear',
'void',
[],
is_pure_virtual=True, is_virtual=True)
return
def register_Ns3HashFunctionFnv1a_methods(root_module, cls):
## hash-fnv.h (module 'core'): ns3::Hash::Function::Fnv1a::Fnv1a(ns3::Hash::Function::Fnv1a const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hash::Function::Fnv1a const &', 'arg0')])
## hash-fnv.h (module 'core'): ns3::Hash::Function::Fnv1a::Fnv1a() [constructor]
cls.add_constructor([])
## hash-fnv.h (module 'core'): uint32_t ns3::Hash::Function::Fnv1a::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-fnv.h (module 'core'): uint64_t ns3::Hash::Function::Fnv1a::GetHash64(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-fnv.h (module 'core'): void ns3::Hash::Function::Fnv1a::clear() [member function]
cls.add_method('clear',
'void',
[],
is_virtual=True)
return
def register_Ns3HashFunctionHash32_methods(root_module, cls):
## hash-function.h (module 'core'): ns3::Hash::Function::Hash32::Hash32(ns3::Hash::Function::Hash32 const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hash::Function::Hash32 const &', 'arg0')])
## hash-function.h (module 'core'): ns3::Hash::Function::Hash32::Hash32(ns3::Hash::Hash32Function_ptr hp) [constructor]
cls.add_constructor([param('ns3::Hash::Hash32Function_ptr', 'hp')])
## hash-function.h (module 'core'): uint32_t ns3::Hash::Function::Hash32::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-function.h (module 'core'): void ns3::Hash::Function::Hash32::clear() [member function]
cls.add_method('clear',
'void',
[],
is_virtual=True)
return
def register_Ns3HashFunctionHash64_methods(root_module, cls):
## hash-function.h (module 'core'): ns3::Hash::Function::Hash64::Hash64(ns3::Hash::Function::Hash64 const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hash::Function::Hash64 const &', 'arg0')])
## hash-function.h (module 'core'): ns3::Hash::Function::Hash64::Hash64(ns3::Hash::Hash64Function_ptr hp) [constructor]
cls.add_constructor([param('ns3::Hash::Hash64Function_ptr', 'hp')])
## hash-function.h (module 'core'): uint32_t ns3::Hash::Function::Hash64::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-function.h (module 'core'): uint64_t ns3::Hash::Function::Hash64::GetHash64(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-function.h (module 'core'): void ns3::Hash::Function::Hash64::clear() [member function]
cls.add_method('clear',
'void',
[],
is_virtual=True)
return
def register_Ns3HashFunctionMurmur3_methods(root_module, cls):
## hash-murmur3.h (module 'core'): ns3::Hash::Function::Murmur3::Murmur3(ns3::Hash::Function::Murmur3 const & arg0) [copy constructor]
cls.add_constructor([param('ns3::Hash::Function::Murmur3 const &', 'arg0')])
## hash-murmur3.h (module 'core'): ns3::Hash::Function::Murmur3::Murmur3() [constructor]
cls.add_constructor([])
## hash-murmur3.h (module 'core'): uint32_t ns3::Hash::Function::Murmur3::GetHash32(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash32',
'uint32_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-murmur3.h (module 'core'): uint64_t ns3::Hash::Function::Murmur3::GetHash64(char const * buffer, size_t const size) [member function]
cls.add_method('GetHash64',
'uint64_t',
[param('char const *', 'buffer'), param('size_t const', 'size')],
is_virtual=True)
## hash-murmur3.h (module 'core'): void ns3::Hash::Function::Murmur3::clear() [member function]
cls.add_method('clear',
'void',
[],
is_virtual=True)
return
def register_functions(root_module):
module = root_module
register_functions_ns3_FatalImpl(module.get_submodule('FatalImpl'), root_module)
register_functions_ns3_Hash(module.get_submodule('Hash'), root_module)
return
def register_functions_ns3_FatalImpl(module, root_module):
return
def register_functions_ns3_Hash(module, root_module):
register_functions_ns3_Hash_Function(module.get_submodule('Function'), root_module)
return
def register_functions_ns3_Hash_Function(module, root_module):
return
def main():
out = FileCodeSink(sys.stdout)
root_module = module_init()

View File

@@ -14,6 +14,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*
* Some updates to this code were developed under a research contract
* sponsored by the Army Research Laboratory. (April 30, 2013)
*/
#include "distributed-simulator-impl.h"
@@ -68,6 +71,12 @@ LbtsMessage::GetMyId ()
return m_myId;
}
bool
LbtsMessage::IsFinished ()
{
return m_isFinished;
}
Time DistributedSimulatorImpl::m_lookAhead = Seconds (0);
TypeId
@@ -153,6 +162,9 @@ DistributedSimulatorImpl::CalculateLookAhead (void)
}
else
{
DistributedSimulatorImpl::m_lookAhead = GetMaximumSimulationTime ();
m_grantedTime = GetMaximumSimulationTime ();
NodeContainer c = NodeContainer::GetGlobal ();
for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
{
@@ -197,11 +209,7 @@ DistributedSimulatorImpl::CalculateLookAhead (void)
// it the new lookAhead.
TimeValue delay;
channel->GetAttribute ("Delay", delay);
if (DistributedSimulatorImpl::m_lookAhead.IsZero ())
{
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
m_grantedTime = delay.Get ();
}
if (delay.Get ().GetSeconds () < DistributedSimulatorImpl::m_lookAhead.GetSeconds ())
{
DistributedSimulatorImpl::m_lookAhead = delay.Get ();
@@ -210,6 +218,49 @@ DistributedSimulatorImpl::CalculateLookAhead (void)
}
}
}
/*
* Compute the maximum inter-task latency and use that value
* for tasks with no inter-task links.
*
* Special processing for edge cases. For tasks that have no
* nodes need to determine a reasonable lookAhead value. Infinity
* would work correctly but introduces a performance issue; tasks
* with an infinite lookAhead would execute all their events
* before doing an AllGather resulting in very bad load balance
* during the first time window. Since all tasks participate in
* the AllGather it is desirable to have all the tasks advance in
* simulation time at a similar rate assuming roughly equal events
* per unit of simulation time in order to equalize the amount of
* work per time window.
*/
long sendbuf;
long recvbuf;
/* Tasks with no inter-task links do not contribute to max */
if (m_lookAhead == GetMaximumSimulationTime ())
{
sendbuf = 0;
}
else
{
sendbuf = m_lookAhead.GetInteger ();
}
MPI_Allreduce (&sendbuf, &recvbuf, 1, MPI_LONG, MPI_MAX, MPI_COMM_WORLD);
/* For nodes that did not compute a lookahead use max from ranks
* that did compute a value. An edge case occurs if all nodes have
* no inter-task links (max will be 0 in this case). Use infinity so all tasks
* will proceed without synchronization until a single AllGather
* occurs when all tasks have finished.
*/
if (m_lookAhead == GetMaximumSimulationTime () && recvbuf != 0)
{
m_lookAhead = Time (recvbuf);
m_grantedTime = m_lookAhead;
}
#else
NS_FATAL_ERROR ("Can't use distributed simulator without MPI compiled in");
#endif
@@ -249,6 +300,12 @@ DistributedSimulatorImpl::ProcessOneEvent (void)
bool
DistributedSimulatorImpl::IsFinished (void) const
{
return m_globalFinished;
}
bool
DistributedSimulatorImpl::IsLocalFinished (void) const
{
return m_events->IsEmpty () || m_stop;
}
@@ -256,9 +313,14 @@ DistributedSimulatorImpl::IsFinished (void) const
uint64_t
DistributedSimulatorImpl::NextTs (void) const
{
NS_ASSERT (!m_events->IsEmpty ());
Scheduler::Event ev = m_events->PeekNext ();
return ev.key.m_ts;
// If local MPI task is has no more events or stop was called
// next event time is infinity.
if (IsLocalFinished ()) {
return GetMaximumSimulationTime ().GetTimeStep ();
} else {
Scheduler::Event ev = m_events->PeekNext ();
return ev.key.m_ts;
}
}
Time
@@ -273,11 +335,19 @@ DistributedSimulatorImpl::Run (void)
#ifdef NS3_MPI
CalculateLookAhead ();
m_stop = false;
while (!m_events->IsEmpty () && !m_stop)
while (!m_globalFinished)
{
Time nextTime = Next ();
if (nextTime > m_grantedTime)
{ // Can't process, calculate a new LBTS
// If local event is beyond grantedTime then need to synchronize
// with other tasks to determine new time window. If local task
// is finished then continue to participate in allgather
// synchronizations with other tasks until all tasks have
// completed.
if (nextTime > m_grantedTime || IsLocalFinished () )
{
// Can't process next event, calculate a new LBTS
// First receive any pending messages
MpiInterface::ReceiveMessages ();
// reset next time
@@ -285,7 +355,7 @@ DistributedSimulatorImpl::Run (void)
// And check for send completes
MpiInterface::TestSendComplete ();
// Finally calculate the lbts
LbtsMessage lMsg (MpiInterface::GetRxCount (), MpiInterface::GetTxCount (), m_myId, nextTime);
LbtsMessage lMsg (MpiInterface::GetRxCount (), MpiInterface::GetTxCount (), m_myId, IsLocalFinished (), nextTime);
m_pLBTS[m_myId] = lMsg;
MPI_Allgather (&lMsg, sizeof (LbtsMessage), MPI_BYTE, m_pLBTS,
sizeof (LbtsMessage), MPI_BYTE, MPI_COMM_WORLD);
@@ -295,6 +365,7 @@ DistributedSimulatorImpl::Run (void)
// so we don't update the granted time.
uint32_t totRx = m_pLBTS[0].GetRxCount ();
uint32_t totTx = m_pLBTS[0].GetTxCount ();
m_globalFinished = m_pLBTS[0].IsFinished ();
for (uint32_t i = 1; i < m_systemCount; ++i)
{
@@ -304,15 +375,29 @@ DistributedSimulatorImpl::Run (void)
}
totRx += m_pLBTS[i].GetRxCount ();
totTx += m_pLBTS[i].GetTxCount ();
m_globalFinished &= m_pLBTS[i].IsFinished ();
}
if (totRx == totTx)
{
m_grantedTime = smallestTime + DistributedSimulatorImpl::m_lookAhead;
// If lookahead is infinite then granted time should be as well.
// Covers the edge case if all the tasks have no inter tasks
// links, prevents overflow of granted time.
if (m_lookAhead == GetMaximumSimulationTime ())
{
m_grantedTime = GetMaximumSimulationTime ();
}
else
{
// Overflow is possible here if near end of representable time.
m_grantedTime = smallestTime + m_lookAhead;
}
}
}
if (nextTime <= m_grantedTime)
{ // Save to process
// Execute next event if it is within the current time window.
// Local task may be completed.
if ( (nextTime <= m_grantedTime) && (!IsLocalFinished ()) )
{ // Safe to process
ProcessOneEvent ();
}
}

View File

@@ -14,6 +14,9 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: George Riley <riley@ece.gatech.edu>
*
* Some updates to this code were developed under a research contract
* sponsored by the Army Research Laboratory. (April 30, 2013)
*/
#ifndef DISTRIBUTED_SIMULATOR_IMPL_H
@@ -39,7 +42,8 @@ public:
LbtsMessage ()
: m_txCount (0),
m_rxCount (0),
m_myId (0)
m_myId (0),
m_isFinished (false)
{
}
@@ -49,11 +53,12 @@ public:
* \param id mpi rank
* \param t smallest time
*/
LbtsMessage (uint32_t rxc, uint32_t txc, uint32_t id, const Time& t)
LbtsMessage (uint32_t rxc, uint32_t txc, uint32_t id, bool isFinished, const Time& t)
: m_txCount (txc),
m_rxCount (rxc),
m_myId (id),
m_smallestTime (t)
m_smallestTime (t),
m_isFinished (isFinished)
{
}
@@ -76,11 +81,14 @@ public:
*/
uint32_t GetMyId ();
bool IsFinished ();
private:
uint32_t m_txCount;
uint32_t m_rxCount;
uint32_t m_myId;
Time m_smallestTime;
bool m_isFinished;
};
/**
@@ -120,6 +128,7 @@ public:
private:
virtual void DoDispose (void);
void CalculateLookAhead (void);
bool IsLocalFinished (void) const;
void ProcessOneEvent (void);
uint64_t NextTs (void) const;
@@ -128,6 +137,7 @@ private:
DestroyEvents m_destroyEvents;
bool m_stop;
bool m_globalFinished; // Are all parallel instances completed.
Ptr<Scheduler> m_events;
uint32_t m_uid;
uint32_t m_currentUid;