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 
32 #include "remote-channel-bundle.h"
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 
51 namespace ns3 {
52 
53 NS_LOG_COMPONENT_DEFINE ("NullMessageSimulatorImpl");
54 
55 NS_OBJECT_ENSURE_REGISTERED (NullMessageSimulatorImpl);
56 
57 NullMessageSimulatorImpl* NullMessageSimulatorImpl::g_instance = 0;
58 
59 TypeId
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;
82  // uids are allocated from 4.
83  // uid 0 is "invalid" events
84  // uid 1 is "now" events
85  // uid 2 is "destroy" events
86  m_uid = 4;
87  // before ::Run is entered, the m_currentUid will be zero
88  m_currentUid = 0;
89  m_currentTs = 0;
92  m_eventCount = 0;
93  m_events = 0;
94 
95  m_safeTime = Seconds (0);
96 
97  NS_ASSERT (g_instance == 0);
98  g_instance = this;
99 }
100 
102 {
103  NS_LOG_FUNCTION (this);
104 }
105 
106 void
108 {
109  NS_LOG_FUNCTION (this);
110 
111  while (!m_events->IsEmpty ())
112  {
113  Scheduler::Event next = m_events->RemoveNext ();
114  next.impl->Unref ();
115  }
116  m_events = 0;
118 }
119 
120 void
122 {
123  NS_LOG_FUNCTION (this);
124 
125  while (!m_destroyEvents.empty ())
126  {
127  Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
128  m_destroyEvents.pop_front ();
129  NS_LOG_LOGIC ("handle destroy " << ev);
130  if (!ev->IsCancelled ())
131  {
132  ev->Invoke ();
133  }
134  }
135 
138 }
139 
140 void
142 {
143  NS_LOG_FUNCTION (this);
144 
145  int num_local_nodes = 0;
146 
147  if (MpiInterface::GetSize () > 1)
148  {
150  for (NodeContainer::Iterator iter = c.Begin (); iter != c.End (); ++iter)
151  {
152  if ((*iter)->GetSystemId () != MpiInterface::GetSystemId ())
153  {
154  continue;
155  }
156 
157  num_local_nodes++;
158 
159  for (uint32_t i = 0; i < (*iter)->GetNDevices (); ++i)
160  {
161  Ptr<NetDevice> localNetDevice = (*iter)->GetDevice (i);
162  // only works for p2p links currently
163  if (!localNetDevice->IsPointToPoint ())
164  {
165  continue;
166  }
167  Ptr<Channel> channel = localNetDevice->GetChannel ();
168  if (channel == 0)
169  {
170  continue;
171  }
172 
173  // grab the adjacent node
174  Ptr<Node> remoteNode;
175  if (channel->GetDevice (0) == localNetDevice)
176  {
177  remoteNode = (channel->GetDevice (1))->GetNode ();
178  }
179  else
180  {
181  remoteNode = (channel->GetDevice (0))->GetNode ();
182  }
183 
184  // if it's not remote, don't consider it
185  if (remoteNode->GetSystemId () == MpiInterface::GetSystemId ())
186  {
187  continue;
188  }
189 
193  Ptr<RemoteChannelBundle> remoteChannelBundle = RemoteChannelBundleManager::Find (remoteNode->GetSystemId ());
194  if (!remoteChannelBundle)
195  {
196  remoteChannelBundle = RemoteChannelBundleManager::Add (remoteNode->GetSystemId ());
197  }
198 
199  TimeValue delay;
200  channel->GetAttribute ("Delay", delay);
201  remoteChannelBundle->AddChannel (channel, delay.Get () );
202  }
203  }
204  }
205 
206  // Completed setup of remote channel bundles. Setup send and receive buffers.
208 
209  // Initialized to 0 as we don't have a simulation start time.
210  m_safeTime = Time (0);
211 }
212 
213 void
215 {
216  NS_LOG_FUNCTION (this << schedulerFactory);
217 
218  Ptr<Scheduler> scheduler = schedulerFactory.Create<Scheduler> ();
219 
220  if (m_events != 0)
221  {
222  while (!m_events->IsEmpty ())
223  {
224  Scheduler::Event next = m_events->RemoveNext ();
225  scheduler->Insert (next);
226  }
227  }
228  m_events = scheduler;
229 }
230 
231 void
233 {
234  NS_LOG_FUNCTION (this);
235 
236  Scheduler::Event next = m_events->RemoveNext ();
237 
238  NS_ASSERT (next.key.m_ts >= m_currentTs);
240  m_eventCount++;
241 
242  NS_LOG_LOGIC ("handle " << next.key.m_ts);
243  m_currentTs = next.key.m_ts;
245  m_currentUid = next.key.m_uid;
246  next.impl->Invoke ();
247  next.impl->Unref ();
248 }
249 
250 bool
252 {
253  return m_events->IsEmpty () || m_stop;
254 }
255 
256 Time
258 {
259  NS_LOG_FUNCTION (this);
260 
261  NS_ASSERT (!m_events->IsEmpty ());
262 
263  Scheduler::Event ev = m_events->PeekNext ();
264  return TimeStep (ev.key.m_ts);
265 }
266 
267 void
269 {
270  NS_LOG_FUNCTION (this << bundle);
271 
272  Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
273 
275  this, PeekPointer(bundle)));
276 }
277 
278 void
280 {
281  NS_LOG_FUNCTION (this << bundle);
282 
283  Simulator::Cancel (bundle->GetEventId ());
284 
285  Time delay (m_schedulerTune * bundle->GetDelay ().GetTimeStep ());
286 
288  this, PeekPointer(bundle)));
289 }
290 
291 void
293 {
294  NS_LOG_FUNCTION (this << nodeSysId);
295 
297  NS_ASSERT (bundle);
298 
300 }
301 
302 void
304 {
305  NS_LOG_FUNCTION (this);
306 
308 
310 
311  // Stop will be set if stop is called by simulation.
312  m_stop = false;
313  while (!IsFinished ())
314  {
315  Time nextTime = Next ();
316 
317  if ( nextTime <= GetSafeTime () )
318  {
319  ProcessOneEvent ();
321  }
322  else
323  {
324  // Block until packet or Null Message has been received.
326  }
327  }
328 }
329 
330 void
332 {
333  NS_LOG_FUNCTION (this);
334 
336 
338 
339  // Check for send completes
341 }
342 
343 void
345 {
346  NS_LOG_FUNCTION (this);
347 
349 
351 
352  // Check for send completes
354 }
355 
356 void
358 {
359  NS_LOG_FUNCTION (this);
360 
363 }
364 
365 Time
367 {
368  return m_safeTime;
369 }
370 
371 
372 uint32_t
374 {
375  return m_myId;
376 }
377 
378 void
380 {
381  NS_LOG_FUNCTION (this);
382 
383  m_stop = true;
384 }
385 
386 void
388 {
389  NS_LOG_FUNCTION (this << delay.GetTimeStep ());
390 
392 }
393 
394 //
395 // Schedule an event for a _relative_ time in the future.
396 //
397 EventId
399 {
400  NS_LOG_FUNCTION (this << delay.GetTimeStep () << event);
401 
402  Time tAbsolute = delay + TimeStep (m_currentTs);
403 
404  NS_ASSERT (tAbsolute.IsPositive ());
405  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
406  Scheduler::Event ev;
407  ev.impl = event;
408  ev.key.m_ts = static_cast<uint64_t> (tAbsolute.GetTimeStep ());
409  ev.key.m_context = GetContext ();
410  ev.key.m_uid = m_uid;
411  m_uid++;
413  m_events->Insert (ev);
414  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
415 }
416 
417 void
418 NullMessageSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *event)
419 {
420  NS_LOG_FUNCTION (this << context << delay.GetTimeStep () << m_currentTs << event);
421 
422  Time tAbsolute(m_currentTs + delay.GetTimeStep ());
423 
424  NS_ASSERT (tAbsolute.IsPositive ());
425  NS_ASSERT (tAbsolute >= TimeStep (m_currentTs));
426 
427  Scheduler::Event ev;
428  ev.impl = event;
429  ev.key.m_ts = tAbsolute.GetTimeStep ();
430  ev.key.m_context = context;
431  ev.key.m_uid = m_uid;
432  m_uid++;
434  m_events->Insert (ev);
435 }
436 
437 EventId
439 {
440  NS_LOG_FUNCTION (this << event);
441 
442  Scheduler::Event ev;
443  ev.impl = event;
444  ev.key.m_ts = m_currentTs;
445  ev.key.m_context = GetContext ();
446  ev.key.m_uid = m_uid;
447  m_uid++;
449  m_events->Insert (ev);
450  return EventId (event, ev.key.m_ts, ev.key.m_context, ev.key.m_uid);
451 }
452 
453 EventId
455 {
456  NS_LOG_FUNCTION (this << event);
457 
458  EventId id (Ptr<EventImpl> (event, false), m_currentTs, 0xffffffff, 2);
459  m_destroyEvents.push_back (id);
460  m_uid++;
461  return id;
462 }
463 
464 Time
466 {
467  return TimeStep (m_currentTs);
468 }
469 
470 Time
472 {
473  if (IsExpired (id))
474  {
475  return TimeStep (0);
476  }
477  else
478  {
479  return TimeStep (id.GetTs () - m_currentTs);
480  }
481 }
482 
483 void
485 {
486  if (id.GetUid () == 2)
487  {
488  // destroy events.
489  for (DestroyEvents::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
490  {
491  if (*i == id)
492  {
493  m_destroyEvents.erase (i);
494  break;
495  }
496  }
497  return;
498  }
499  if (IsExpired (id))
500  {
501  return;
502  }
503  Scheduler::Event event;
504  event.impl = id.PeekEventImpl ();
505  event.key.m_ts = id.GetTs ();
506  event.key.m_context = id.GetContext ();
507  event.key.m_uid = id.GetUid ();
508  m_events->Remove (event);
509  event.impl->Cancel ();
510  // whenever we remove an event from the event list, we have to unref it.
511  event.impl->Unref ();
512 
514 }
515 
516 void
518 {
519  if (!IsExpired (id))
520  {
521  id.PeekEventImpl ()->Cancel ();
522  }
523 }
524 
525 bool
527 {
528  if (id.GetUid () == 2)
529  {
530  if (id.PeekEventImpl () == 0
531  || id.PeekEventImpl ()->IsCancelled ())
532  {
533  return true;
534  }
535  // destroy events.
536  for (DestroyEvents::const_iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end (); i++)
537  {
538  if (*i == id)
539  {
540  return false;
541  }
542  }
543  return true;
544  }
545  if (id.PeekEventImpl () == 0
546  || id.GetTs () < m_currentTs
547  || (id.GetTs () == m_currentTs
548  && id.GetUid () <= m_currentUid)
549  || id.PeekEventImpl ()->IsCancelled ())
550  {
551  return true;
552  }
553  else
554  {
555  return false;
556  }
557 }
558 
559 Time
561 {
562  // XXX: I am fairly certain other compilers use other non-standard
563  // post-fixes to indicate 64 bit constants.
564  return TimeStep (0x7fffffffffffffffLL);
565 }
566 
567 uint32_t
569 {
570  return m_currentContext;
571 }
572 
573 uint64_t
575 {
576  return m_eventCount;
577 }
578 
580 {
582  NS_ASSERT (bundle);
583 
584  return Min (NullMessageSimulatorImpl::GetInstance ()->Next (), GetSafeTime ()) + bundle->GetDelay ();
585 }
586 
588 {
589  NS_LOG_FUNCTION (this << bundle);
590 
591  Time time = Min (Next (), GetSafeTime ()) + bundle->GetDelay ();
593 
594  ScheduleNullMessageEvent (bundle);
595 }
596 
597 
600 {
601  NS_ASSERT (g_instance != 0);
602  return g_instance;
603 }
604 } // namespace ns3
605 
Time CalculateGuaranteeTime(uint32_t systemId)
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
virtual void Remove(const EventId &id)
Remove an event from the event list.
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:73
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void Unref(void) const
Decrement the reference count.
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
std::vector< Ptr< Node > >::const_iterator Iterator
Node container iterator.
virtual void Destroy()
Execute the events scheduled with ScheduleDestroy().
uint64_t m_ts
Event time stamp.
Definition: scheduler.h:170
uint64_t m_currentTs
Timestamp of the current event.
void HandleArrivingMessagesNonBlocking(void)
Non blocking receive of pending messages.
Declaration of class ns3::NullMessageSimulatorImpl.
virtual EventId ScheduleNow(EventImpl *event)
Schedule an event to run at the current virtual time.
Ptr< Scheduler > m_events
The event priority queue.
EventImpl * impl
Pointer to the event implementation.
Definition: scheduler.h:183
#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
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:411
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
virtual bool IsFinished(void) const
Check if the simulation should finish.
static void ReceiveMessagesNonBlocking()
Non-blocking check for received messages complete.
static void Cancel(const EventId &id)
Set the cancel bit on this event: the event&#39;s associated function will not be invoked when it expires...
Definition: simulator.cc:268
void ProcessOneEvent(void)
Process the next event on the queue.
void(* Time)(Time oldValue, Time newValue)
TracedValue callback signature for Time.
Definition: nstime.h:813
void RescheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
uint32_t m_currentUid
Unique id of the current event.
Collection of ns-3 channels between local and remote nodes.
Iterator End(void) const
Get an iterator which indicates past-the-last Node in the container.
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...
virtual uint32_t GetContext(void) const
Get the current simulation context.
channel
Definition: third.py:92
void CalculateSafeTime(void)
Calculate the SafeTime.
void Invoke(void)
Called by the simulation engine to notify the event that it is time to execute.
Definition: event-impl.cc:46
static NullMessageSimulatorImpl * GetInstance(void)
uint32_t m_uid
Next event unique id.
static void TestSendComplete()
Check for completed sends.
int64x64_t Min(const int64x64_t &a, const int64x64_t &b)
Minimum.
Definition: int64x64.h:218
Declaration of class ns3::MpiInterface.
static Time GetSafeTime(void)
Get the safe time across all channels in this bundle.
EventKey key
Key for sorting and ordering Events.
Definition: scheduler.h:184
static void Destroy()
Deletes storage used by the parallel environment.
AttributeValue implementation for Time.
Definition: nstime.h:1353
Ptr< Object > Create(void) const
Create an Object instance of the configured TypeId.
uint32_t m_uid
Event unique id.
Definition: scheduler.h:171
static void SendNullMessage(const Time &guaranteeUpdate, Ptr< RemoteChannelBundle > bundle)
Send a Null Message to across the specified bundle.
static void InitializeNullMessageEvents(void)
Setup initial Null Message events for every RemoteChannelBundle.
DestroyEvents m_destroyEvents
The container of events to run at Destroy()
Time GetSafeTime(void)
Get the current SafeTime; the maximum time that events can be processed based on information received...
Maintain the event list.
Definition: scheduler.h:155
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
virtual uint64_t GetEventCount(void) const
Get the number of events executed.
static void Destroy(void)
Destroy the singleton.
virtual void Run(void)
Run the simulation.
static NullMessageSimulatorImpl * g_instance
Singleton instance.
virtual bool IsExpired(const EventId &id) const
Check if an event has already run or been cancelled.
Scheduler event.
Definition: scheduler.h:181
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void CalculateLookAhead(void)
Calculate the lookahead allowable for this MPI task.
keep track of a set of node pointers.
static void ReceiveMessagesBlocking()
Blocking message receive.
virtual void ScheduleWithContext(uint32_t context, Time const &delay, EventImpl *event)
Schedule a future event execution (in a different context).
uint32_t GetSystemId(void) const
Definition: node.cc:123
static Ptr< RemoteChannelBundle > Find(uint32_t systemId)
Get the bundle corresponding to a remote rank.
void HandleArrivingMessagesBlocking(void)
Blocking receive of arriving messages.
virtual Time Now(void) const
Return the current simulation virtual time.
bool m_stop
Flag calling for the end of the simulation.
Time m_safeTime
The time for which it is safe for this task to execute events without danger of out-of-order events...
Declaration of class ns3::RemoteChannelBundleManager.
NullMessageSimulatorImpl()
Default constructor.
int m_unscheduledEvents
Number of events that have been inserted but not yet scheduled, not counting the "destroy" events; th...
static Ptr< RemoteChannelBundle > Add(uint32_t systemId)
Add RemoteChannelBundle from this task to MPI task on other side of the link.
Simulator implementation using MPI and a Null Message algorithm.
Ptr< const AttributeAccessor > MakeDoubleAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method...
Definition: double.h:42
static NodeContainer GetGlobal(void)
Create a NodeContainer that contains a list of all nodes created through NodeContainer::Create() and ...
Instantiate subclasses of ns3::Object.
Declaration of class ns3::RemoteChannelBundle.
A simulation event.
Definition: event-impl.h:44
Declaration of classes ns3::NullMessageSentBuffer and ns3::NullMessageMpiInterface.
virtual uint32_t GetSystemId(void) const
Get the system id of this simulator.
An identifier for simulation events.
Definition: event-id.h:53
static uint32_t GetSystemId()
Get the id number of this rank.
virtual Time GetMaximumSimulationTime(void) const
Get the maximum representable simulation time.
static void Stop(void)
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:180
Time Get(void) const
Definition: time.cc:530
virtual void Stop(void)
Tell the Simulator the calling event should be the last one executed.
uint32_t m_currentContext
Execution context of the current event.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
virtual void Cancel(const EventId &id)
Set the cancel bit on this event: the event&#39;s associated function will not be invoked when it expires...
void ScheduleNullMessageEvent(Ptr< RemoteChannelBundle > bundle)
Flag for events not associated with any particular context.
Definition: simulator.h:199
void NullMessageEventHandler(RemoteChannelBundle *bundle)
virtual EventId Schedule(Time const &delay, EventImpl *event)
Schedule a future event execution (in the same context).
virtual void DoDispose(void)
Destructor implementation.
static void InitializeSendReceiveBuffers(void)
Initialize send and receive buffers.
Time GetDelay(void) const
Get the minimum delay along any channel in this bundle.
This class can be used to hold variables of floating point type such as &#39;double&#39; or &#39;float&#39;...
Definition: double.h:41
double m_schedulerTune
Null Message performance tuning parameter.
a unique identifier for an interface.
Definition: type-id.h:58
virtual void SetScheduler(ObjectFactory schedulerFactory)
Set the Scheduler to be used to manage the event list.
virtual Time GetDelayLeft(const EventId &id) const
Get the remaining time until this event will execute.
static TypeId GetTypeId(void)
Register this type.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
static uint32_t GetSize()
Get the number of ranks used by ns-3.
uint32_t m_context
Event context.
Definition: scheduler.h:172
Iterator Begin(void) const
Get an iterator which refers to the first Node in the container.
The SimulatorImpl base class.
uint32_t m_systemCount
MPI communicator size.
int64_t GetTimeStep(void) const
Get the raw time value, in the current resolution unit.
Definition: nstime.h:416