A Discrete-Event Network Simulator
API
null-message-simulator-impl.cc
Go to the documentation of this file.
1/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright 2013. Lawrence Livermore National Security, LLC.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Steven Smith <smith84@llnl.gov>
19 */
20
29
33#include "mpi-interface.h"
34
35#include <ns3/simulator.h>
36#include <ns3/scheduler.h>
37#include <ns3/event-impl.h>
38#include <ns3/channel.h>
39#include <ns3/node-container.h>
40#include <ns3/double.h>
41#include <ns3/ptr.h>
42#include <ns3/pointer.h>
43#include <ns3/assert.h>
44#include <ns3/log.h>
45
46#include <cmath>
47#include <iostream>
48#include <fstream>
49#include <iomanip>
50
51namespace ns3 {
52
53NS_LOG_COMPONENT_DEFINE ("NullMessageSimulatorImpl");
54
55NS_OBJECT_ENSURE_REGISTERED (NullMessageSimulatorImpl);
56
57NullMessageSimulatorImpl* NullMessageSimulatorImpl::g_instance = 0;
58
59TypeId
61{
62 static TypeId tid = TypeId ("ns3::NullMessageSimulatorImpl")
64 .SetGroupName ("Mpi")
65 .AddConstructor<NullMessageSimulatorImpl> ()
66 .AddAttribute ("SchedulerTune", "Null Message scheduler tuning parameter",
67 DoubleValue (1.0),
69 MakeDoubleChecker<double> (0.01,1.0))
70 ;
71 return tid;
72}
73
75{
76 NS_LOG_FUNCTION (this);
77
80
81 m_stop = false;
84 m_currentTs = 0;
87 m_eventCount = 0;
88 m_events = 0;
89
90 m_safeTime = Seconds (0);
91
92 NS_ASSERT (g_instance == 0);
93 g_instance = this;
94}
95
97{
98 NS_LOG_FUNCTION (this);
99}
100
101void
103{
104 NS_LOG_FUNCTION (this);
105
106 while (!m_events->IsEmpty ())
107 {
108 Scheduler::Event next = m_events->RemoveNext ();
109 next.impl->Unref ();
110 }
111 m_events = 0;
113}
114
115void
117{
118 NS_LOG_FUNCTION (this);
119
120 while (!m_destroyEvents.empty ())
121 {
122 Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
123 m_destroyEvents.pop_front ();
124 NS_LOG_LOGIC ("handle destroy " << ev);
125 if (!ev->IsCancelled ())
126 {
127 ev->Invoke ();
128 }
129 }
130
133}
134
135void
137{
138 NS_LOG_FUNCTION (this);
139
140 int num_local_nodes = 0;
141
142 if (MpiInterface::GetSize () > 1)
143 {
145 for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
146 {
147 if ((*iter)->GetSystemId () != MpiInterface::GetSystemId ())
148 {
149 continue;
150 }
151
152 num_local_nodes++;
153
154 for (uint32_t i = 0; i < (*iter)->GetNDevices (); ++i)
155 {
156 Ptr<NetDevice> localNetDevice = (*iter)->GetDevice (i);
157 // only works for p2p links currently
158 if (!localNetDevice->IsPointToPoint ())
159 {
160 continue;
161 }
162 Ptr<Channel> channel = localNetDevice->GetChannel ();
163 if (channel == 0)
164 {
165 continue;
166 }
167
168 // grab the adjacent node
169 Ptr<Node> remoteNode;
170 if (channel->GetDevice (0) == localNetDevice)
171 {
172 remoteNode = (channel->GetDevice (1))->GetNode ();
173 }
174 else
175 {
176 remoteNode = (channel->GetDevice (0))->GetNode ();
177 }
178
179 // if it's not remote, don't consider it
180 if (remoteNode->GetSystemId () == MpiInterface::GetSystemId ())
181 {
182 continue;
183 }
184
188 Ptr<RemoteChannelBundle> remoteChannelBundle = RemoteChannelBundleManager::Find (remoteNode->GetSystemId ());
189 if (!remoteChannelBundle)
190 {
191 remoteChannelBundle = RemoteChannelBundleManager::Add (remoteNode->GetSystemId ());
192 }
193
194 TimeValue delay;
195 channel->GetAttribute ("Delay", delay);
196 remoteChannelBundle->AddChannel (channel, delay.Get () );
197 }
198 }
199 }
200
201 // Completed setup of remote channel bundles. Setup send and receive buffers.
203
204 // Initialized to 0 as we don't have a simulation start time.
205 m_safeTime = Time (0);
206}
207
208void
210{
211 NS_LOG_FUNCTION (this << schedulerFactory);
212
213 Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
214
215 if (m_events != 0)
216 {
217 while (!m_events->IsEmpty ())
218 {
219 Scheduler::Event next = m_events->RemoveNext ();
220 scheduler->Insert (next);
221 }
222 }
223 m_events = scheduler;
224}
225
226void
228{
229 NS_LOG_FUNCTION (this);
230
231 Scheduler::Event next = m_events->RemoveNext ();
232
233 PreEventHook (EventId (next.impl, next.key.m_ts,
234 next.key.m_context, next.key.m_uid));
235
236 NS_ASSERT (next.key.m_ts >= m_currentTs);
238 m_eventCount++;
239
240 NS_LOG_LOGIC ("handle " << next.key.m_ts);
241 m_currentTs = next.key.m_ts;
243 m_currentUid = next.key.m_uid;
244 next.impl->Invoke ();
245 next.impl->Unref ();
246}
247
248bool
250{
251 return m_events->IsEmpty () || m_stop;
252}
253
254Time
256{
257 NS_LOG_FUNCTION (this);
258
259 NS_ASSERT (!m_events->IsEmpty ());
260
261 Scheduler::Event ev = m_events->PeekNext ();
262 return TimeStep (ev.key.m_ts);
263}
264
265void
267{
268 NS_LOG_FUNCTION (this << bundle);
269
270 Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
271
273 this, PeekPointer(bundle)));
274}
275
276void
278{
279 NS_LOG_FUNCTION (this << bundle);
280
281 Simulator::Cancel (bundle->GetEventId ());
282
283 Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
284
286 this, PeekPointer(bundle)));
287}
288
289void
291{
292 NS_LOG_FUNCTION (this << nodeSysId);
293
295 NS_ASSERT (bundle);
296
298}
299
300void
302{
303 NS_LOG_FUNCTION (this);
304
306
308
309 // Stop will be set if stop is called by simulation.
310 m_stop = false;
311 while (!IsFinished ())
312 {
313 Time nextTime = Next ();
314
315 if ( nextTime <= GetSafeTime () )
316 {
319 }
320 else
321 {
322 // Block until packet or Null Message has been received.
324 }
325 }
326}
327
328void
330{
331 NS_LOG_FUNCTION (this);
332
334
336
337 // Check for send completes
339}
340
341void
343{
344 NS_LOG_FUNCTION (this);
345
347
349
350 // Check for send completes
352}
353
354void
356{
357 NS_LOG_FUNCTION (this);
358
361}
362
363Time
365{
366 return m_safeTime;
367}
368
369
372{
373 return m_myId;
374}
375
376void
378{
379 NS_LOG_FUNCTION (this);
380
381 m_stop = true;
382}
383
384void
386{
387 NS_LOG_FUNCTION (this << delay.GetTimeStep ());
388
390}
391
392//
393// Schedule an event for a _relative_ time in the future.
394//
397{
398 NS_LOG_FUNCTION (this << delay.GetTimeStep () << event);
399
400 Time tAbsolute = delay + TimeStep (m_currentTs);
401
402 NS_ASSERT (tAbsolute.IsPositive ());
403 NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
405 ev.impl = event;
406 ev.key.m_ts = static_cast<uint64_t> (tAbsolute.GetTimeStep ());
407 ev.key.m_context = GetContext ();
408 ev.key.m_uid = m_uid;
409 m_uid++;
411 m_events->Insert (ev);
412 return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
413}
414
415void
417{
418 NS_LOG_FUNCTION (this << context << delay.GetTimeStep () << m_currentTs << event);
419
420 Time tAbsolute(m_currentTs + delay.GetTimeStep ());
421
422 NS_ASSERT (tAbsolute.IsPositive ());
423 NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
424
426 ev.impl = event;
427 ev.key.m_ts = tAbsolute.GetTimeStep ();
428 ev.key.m_context = context;
429 ev.key.m_uid = m_uid;
430 m_uid++;
432 m_events->Insert (ev);
433}
434
437{
438 NS_LOG_FUNCTION (this << event);
439 return Schedule (Time (0), event);
440}
441
444{
445 NS_LOG_FUNCTION (this << event);
446
447 EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
448 m_destroyEvents.push_back (id);
449 m_uid++;
450 return id;
451}
452
453Time
455{
456 return TimeStep (m_currentTs);
457}
458
459Time
461{
462 if (IsExpired (id))
463 {
464 return TimeStep (0);
465 }
466 else
467 {
468 return TimeStep (id.GetTs () - m_currentTs);
469 }
470}
471
472void
474{
475 if (id.GetUid () == EventId::UID::DESTROY)
476 {
477 // destroy events.
478 for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
479 {
480 if (*i == id)
481 {
482 m_destroyEvents.erase (i);
483 break;
484 }
485 }
486 return;
487 }
488 if (IsExpired (id))
489 {
490 return;
491 }
492 Scheduler::Event event;
493 event.impl = id.PeekEventImpl ();
494 event.key.m_ts = id.GetTs ();
495 event.key.m_context = id.GetContext ();
496 event.key.m_uid = id.GetUid ();
497 m_events->Remove (event);
498 event.impl->Cancel ();
499 // whenever we remove an event from the event list, we have to unref it.
500 event.impl->Unref ();
501
503}
504
505void
507{
508 if (!IsExpired (id))
509 {
510 id.PeekEventImpl ()->Cancel ();
511 }
512}
513
514bool
516{
517 if (id.GetUid () == EventId::UID::DESTROY)
518 {
519 if (id.PeekEventImpl () == 0
520 || id.PeekEventImpl ()->IsCancelled ())
521 {
522 return true;
523 }
524 // destroy events.
525 for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
526 {
527 if (*i == id)
528 {
529 return false;
530 }
531 }
532 return true;
533 }
534 if (id.PeekEventImpl () == 0
535 || id.GetTs () < m_currentTs
536 || (id.GetTs () == m_currentTs
537 && id.GetUid () <= m_currentUid)
538 || id.PeekEventImpl ()->IsCancelled ())
539 {
540 return true;
541 }
542 else
543 {
544 return false;
545 }
546}
547
548Time
550{
551 // XXX: I am fairly certain other compilers use other non-standard
552 // post-fixes to indicate 64 bit constants.
553 return TimeStep (0x7fffffffffffffffLL);
554}
555
558{
559 return m_currentContext;
560}
561
562uint64_t
564{
565 return m_eventCount;
566}
567
569{
571 NS_ASSERT (bundle);
572
573 return Min (NullMessageSimulatorImpl::GetInstance ()->Next (), GetSafeTime ()) + bundle->GetDelay ();
574}
575
577{
578 NS_LOG_FUNCTION (this << bundle);
579
580 Time time = Min (Next (), GetSafeTime ()) + bundle->GetDelay ();
582
584}
585
586
589{
590 NS_ASSERT (g_instance != 0);
591 return g_instance;
592}
593} // namespace ns3
594
This class can be used to hold variables of floating point type such as 'double' or 'float'.
Definition: double.h:41
An identifier for simulation events.
Definition: event-id.h:54
A simulation event.
Definition: event-impl.h:45
void Invoke(void)
Called by the simulation engine to notify the event that it is time to execute.
Definition: event-impl.cc:46
static void Destroy()
Deletes storage used by the parallel environment.
static uint32_t GetSystemId()
Get the id number of this rank.
static uint32_t GetSize()
Get the number of ranks used by ns-3.
virtual bool IsPointToPoint(void) const =0
Return true if the net device is on a point-to-point link.
virtual Ptr< Channel > GetChannel(void) const =0
keep track of a set of node pointers.
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
uint32_t GetSystemId(void) const
Definition: node.cc:123
static void ReceiveMessagesBlocking()
Blocking message receive.
static void ReceiveMessagesNonBlocking()
Non-blocking check for received messages complete.
static void SendNullMessage(const Time &guaranteeUpdate, Ptr< RemoteChannelBundle > bundle)
Send a Null Message to across the specified bundle.
static void TestSendComplete()
Check for completed sends.
static void InitializeSendReceiveBuffers(void)
Initialize send and receive buffers.
Simulator implementation using MPI and a Null Message algorithm.
double m_schedulerTune
Null Message performance tuning parameter.
Ptr< Scheduler > m_events
The event priority queue.
virtual void Remove(const EventId &id)
Remove an event from the event list.
virtual bool IsExpired(const EventId &id) const
Check if an event has already run or been cancelled.
uint32_t m_currentUid
Unique id of the current event.
uint32_t m_systemCount
MPI communicator size.
void ProcessOneEvent(void)
Process the next event on the queue.
virtual void SetScheduler(ObjectFactory schedulerFactory)
Set the Scheduler to be used to manage the event list.
uint32_t m_currentContext
Execution context of the current event.
Time m_safeTime
The time for which it is safe for this task to execute events without danger of out-of-order events.
void CalculateSafeTime(void)
Calculate the SafeTime.
virtual void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Time CalculateGuaranteeTime(uint32_t systemId)
static NullMessageSimulatorImpl * g_instance
Singleton instance.
virtual EventId Schedule(Time const &delay, EventImpl *event)
Schedule a future event execution (in the same context).
virtual Time Now(void) const
Return the current simulation virtual time.
uint32_t m_uid
Next event unique id.
virtual Time GetMaximumSimulationTime(void) const
Get the maximum representable simulation time.
virtual Time GetDelayLeft(const EventId &id) const
Get the remaining time until this event will execute.
uint64_t m_currentTs
Timestamp of the current event.
void HandleArrivingMessagesNonBlocking(void)
Non blocking receive of pending messages.
virtual void ScheduleWithContext(uint32_t context, Time const &delay, EventImpl *event)
Schedule a future event execution (in a different context).
void NullMessageEventHandler(RemoteChannelBundle *bundle)
virtual EventId ScheduleNow(EventImpl *event)
Schedule an event to run at the current virtual time.
DestroyEvents m_destroyEvents
The container of events to run at Destroy()
virtual uint64_t GetEventCount(void) const
Get the number of events executed.
virtual void Destroy()
Execute the events scheduled with ScheduleDestroy().
virtual void DoDispose(void)
Destructor implementation.
static NullMessageSimulatorImpl * GetInstance(void)
virtual void Run(void)
Run the simulation.
Time GetSafeTime(void)
Get the current SafeTime; the maximum time that events can be processed based on information received...
int m_unscheduledEvents
Number of events that have been inserted but not yet scheduled, not counting the "destroy" events; th...
virtual void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
void HandleArrivingMessagesBlocking(void)
Blocking receive of arriving messages.
virtual EventId ScheduleDestroy(EventImpl *event)
Schedule an event to run at the end of the simulation, after the Stop() time or condition has been re...
static TypeId GetTypeId(void)
Register this type.
void RescheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
bool m_stop
Flag calling for the end of the simulation.
virtual uint32_t GetContext(void) const
Get the current simulation context.
virtual uint32_t GetSystemId(void) const
Get the system id of this simulator.
void CalculateLookAhead(void)
Calculate the lookahead allowable for this MPI task.
void ScheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
virtual bool IsFinished(void) const
Check if the simulation should finish.
Instantiate subclasses of ns3::Object.
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:74
Collection of ns-3 channels between local and remote nodes.
Time GetDelay(void) const
Get the minimum delay along any channel in this bundle.
static Ptr< RemoteChannelBundle > Find(uint32_t systemId)
Get the bundle corresponding to a remote rank.
static void InitializeNullMessageEvents(void)
Setup initial Null Message events for every RemoteChannelBundle.
static Ptr< RemoteChannelBundle > Add(uint32_t systemId)
Add RemoteChannelBundle from this task to MPI task on other side of the link.
static Time GetSafeTime(void)
Get the safe time across all channels in this bundle.
static void Destroy(void)
Destroy the singleton.
Maintain the event list.
Definition: scheduler.h:156
void Unref(void) const
Decrement the reference count.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event's associated function will not be invoked when it expires...
Definition: simulator.cc:268
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
@ NO_CONTEXT
Flag for events not associated with any particular context.
Definition: simulator.h:199
The SimulatorImpl base class.
virtual void PreEventHook(const EventId &id)
Hook called before processing each event.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
int64_t GetTimeStep(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:415
bool IsPositive(void) const
Exactly equivalent to t >= 0.
Definition: nstime.h:316
AttributeValue implementation for Time.
Definition: nstime.h:1308
Time Get(void) const
Definition: time.cc:533
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
@ INVALID
INVALID.
Definition: aodv-rtable.h:51
@ VALID
VALID.
Definition: aodv-rtable.h:50
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Definition: double.h:42
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Declaration of class ns3::MpiInterface.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:793
Every class exported by the ns3 library is enclosed in the ns3 namespace.
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
channel
Definition: third.py:92
Declaration of classes ns3::NullMessageSentBuffer and ns3::NullMessageMpiInterface.
Declaration of class ns3::NullMessageSimulatorImpl.
Declaration of class ns3::RemoteChannelBundleManager.
Declaration of class ns3::RemoteChannelBundle.
Scheduler event.
Definition: scheduler.h:182
EventKey key
Key for sorting and ordering Events.
Definition: scheduler.h:184
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:183
uint32_t m_context
Event context.
Definition: scheduler.h:172
uint64_t m_ts
Event time stamp.
Definition: scheduler.h:170
uint32_t m_uid
Event unique id.
Definition: scheduler.h:171