Apply clang-format to modified code for ease of merging

This commit is contained in:
F5
2023-11-11 21:17:27 +08:00
parent ec09348f8b
commit e605065a43
45 changed files with 13100 additions and 12757 deletions

View File

@@ -48,254 +48,254 @@
#include "mpi-test-fixtures.h"
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/mpi-interface.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/point-to-point-helper.h"
#include "ns3/internet-stack-helper.h"
#include "ns3/nix-vector-helper.h"
#include "ns3/ipv4-address-helper.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/mpi-interface.h"
#include "ns3/mtp-interface.h"
#include "ns3/network-module.h"
#include "ns3/nix-vector-helper.h"
#include "ns3/on-off-helper.h"
#include "ns3/packet-sink-helper.h"
#include "ns3/mtp-interface.h"
#include <mpi.h>
#include "ns3/point-to-point-helper.h"
#include <iomanip>
#include <mpi.h>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("SimpleDistributed");
NS_LOG_COMPONENT_DEFINE("SimpleDistributed");
int
main (int argc, char *argv[])
main(int argc, char* argv[])
{
LogComponentEnable ("LogicalProcess", LOG_LEVEL_INFO);
LogComponentEnable("LogicalProcess", LOG_LEVEL_INFO);
bool nix = true;
bool nullmsg = false;
bool tracing = false;
bool testing = false;
bool verbose = false;
bool nix = true;
bool nullmsg = false;
bool tracing = false;
bool testing = false;
bool verbose = false;
// Parse command line
CommandLine cmd (__FILE__);
cmd.AddValue ("nix", "Enable the use of nix-vector or global routing", nix);
cmd.AddValue ("nullmsg", "Enable the use of null-message synchronization", nullmsg);
cmd.AddValue ("tracing", "Enable pcap tracing", tracing);
cmd.AddValue ("verbose", "verbose output", verbose);
cmd.AddValue ("test", "Enable regression test output", testing);
cmd.Parse (argc, argv);
// Parse command line
CommandLine cmd(__FILE__);
cmd.AddValue("nix", "Enable the use of nix-vector or global routing", nix);
cmd.AddValue("nullmsg", "Enable the use of null-message synchronization", nullmsg);
cmd.AddValue("tracing", "Enable pcap tracing", tracing);
cmd.AddValue("verbose", "verbose output", verbose);
cmd.AddValue("test", "Enable regression test output", testing);
cmd.Parse(argc, argv);
// Distributed simulation setup; by default use granted time window algorithm.
if(nullmsg)
// Distributed simulation setup; by default use granted time window algorithm.
if (nullmsg)
{
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::NullMessageSimulatorImpl"));
}
else
GlobalValue::Bind("SimulatorImplementationType",
StringValue("ns3::NullMessageSimulatorImpl"));
}
else
{
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::DistributedSimulatorImpl"));
GlobalValue::Bind("SimulatorImplementationType",
StringValue("ns3::DistributedSimulatorImpl"));
}
// Enable parallel simulator with the command line arguments
MtpInterface::Enable ();
MpiInterface::Enable (&argc, &argv);
// Enable parallel simulator with the command line arguments
MtpInterface::Enable();
MpiInterface::Enable(&argc, &argv);
SinkTracer::Init ();
SinkTracer::Init();
if (verbose)
if (verbose)
{
LogComponentEnable ("PacketSink", (LogLevel)(LOG_LEVEL_INFO | LOG_PREFIX_NODE | LOG_PREFIX_TIME));
LogComponentEnable("PacketSink",
(LogLevel)(LOG_LEVEL_INFO | LOG_PREFIX_NODE | LOG_PREFIX_TIME));
}
uint32_t systemId = MpiInterface::GetSystemId ();
uint32_t systemCount = MpiInterface::GetSize ();
uint32_t systemId = MpiInterface::GetSystemId();
uint32_t systemCount = MpiInterface::GetSize();
// Check for valid distributed parameters.
// Must have 2 and only 2 Logical Processors (LPs)
if (systemCount != 2)
// Check for valid distributed parameters.
// Must have 2 and only 2 Logical Processors (LPs)
if (systemCount != 2)
{
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
return 1;
std::cout << "This simulation requires 2 and only 2 logical processors." << std::endl;
return 1;
}
// Some default values
Config::SetDefault ("ns3::OnOffApplication::PacketSize", UintegerValue (512));
Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue ("1Mbps"));
Config::SetDefault ("ns3::OnOffApplication::MaxBytes", UintegerValue (512));
// Some default values
Config::SetDefault("ns3::OnOffApplication::PacketSize", UintegerValue(512));
Config::SetDefault("ns3::OnOffApplication::DataRate", StringValue("1Mbps"));
Config::SetDefault("ns3::OnOffApplication::MaxBytes", UintegerValue(512));
// Create leaf nodes on left with system id 0
NodeContainer leftLeafNodes;
leftLeafNodes.Create (4, 0);
// Create leaf nodes on left with system id 0
NodeContainer leftLeafNodes;
leftLeafNodes.Create(4, 0);
// Create router nodes. Left router
// with system id 0, right router with
// system id 1
NodeContainer routerNodes;
Ptr<Node> routerNode1 = CreateObject<Node> (0);
Ptr<Node> routerNode2 = CreateObject<Node> (1);
routerNodes.Add (routerNode1);
routerNodes.Add (routerNode2);
// Create router nodes. Left router
// with system id 0, right router with
// system id 1
NodeContainer routerNodes;
Ptr<Node> routerNode1 = CreateObject<Node>(0);
Ptr<Node> routerNode2 = CreateObject<Node>(1);
routerNodes.Add(routerNode1);
routerNodes.Add(routerNode2);
// Create leaf nodes on right with system id 1
NodeContainer rightLeafNodes;
rightLeafNodes.Create (4, 1);
// Create leaf nodes on right with system id 1
NodeContainer rightLeafNodes;
rightLeafNodes.Create(4, 1);
PointToPointHelper routerLink;
routerLink.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
routerLink.SetChannelAttribute ("Delay", StringValue ("5ms"));
PointToPointHelper routerLink;
routerLink.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
routerLink.SetChannelAttribute("Delay", StringValue("5ms"));
PointToPointHelper leafLink;
leafLink.SetDeviceAttribute ("DataRate", StringValue ("1Mbps"));
leafLink.SetChannelAttribute ("Delay", StringValue ("2ms"));
PointToPointHelper leafLink;
leafLink.SetDeviceAttribute("DataRate", StringValue("1Mbps"));
leafLink.SetChannelAttribute("Delay", StringValue("2ms"));
// Add link connecting routers
NetDeviceContainer routerDevices;
routerDevices = routerLink.Install (routerNodes);
// Add link connecting routers
NetDeviceContainer routerDevices;
routerDevices = routerLink.Install(routerNodes);
// Add links for left side leaf nodes to left router
NetDeviceContainer leftRouterDevices;
NetDeviceContainer leftLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
// Add links for left side leaf nodes to left router
NetDeviceContainer leftRouterDevices;
NetDeviceContainer leftLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer temp = leafLink.Install (leftLeafNodes.Get (i), routerNodes.Get (0));
leftLeafDevices.Add (temp.Get (0));
leftRouterDevices.Add (temp.Get (1));
NetDeviceContainer temp = leafLink.Install(leftLeafNodes.Get(i), routerNodes.Get(0));
leftLeafDevices.Add(temp.Get(0));
leftRouterDevices.Add(temp.Get(1));
}
// Add links for right side leaf nodes to right router
NetDeviceContainer rightRouterDevices;
NetDeviceContainer rightLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
// Add links for right side leaf nodes to right router
NetDeviceContainer rightRouterDevices;
NetDeviceContainer rightLeafDevices;
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer temp = leafLink.Install (rightLeafNodes.Get (i), routerNodes.Get (1));
rightLeafDevices.Add (temp.Get (0));
rightRouterDevices.Add (temp.Get (1));
NetDeviceContainer temp = leafLink.Install(rightLeafNodes.Get(i), routerNodes.Get(1));
rightLeafDevices.Add(temp.Get(0));
rightRouterDevices.Add(temp.Get(1));
}
InternetStackHelper stack;
if (nix)
InternetStackHelper stack;
if (nix)
{
Ipv4NixVectorHelper nixRouting;
stack.SetRoutingHelper (nixRouting); // has effect on the next Install ()
Ipv4NixVectorHelper nixRouting;
stack.SetRoutingHelper(nixRouting); // has effect on the next Install ()
}
stack.InstallAll ();
stack.InstallAll();
Ipv4InterfaceContainer routerInterfaces;
Ipv4InterfaceContainer leftLeafInterfaces;
Ipv4InterfaceContainer leftRouterInterfaces;
Ipv4InterfaceContainer rightLeafInterfaces;
Ipv4InterfaceContainer rightRouterInterfaces;
Ipv4InterfaceContainer routerInterfaces;
Ipv4InterfaceContainer leftLeafInterfaces;
Ipv4InterfaceContainer leftRouterInterfaces;
Ipv4InterfaceContainer rightLeafInterfaces;
Ipv4InterfaceContainer rightRouterInterfaces;
Ipv4AddressHelper leftAddress;
leftAddress.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4AddressHelper leftAddress;
leftAddress.SetBase("10.1.1.0", "255.255.255.0");
Ipv4AddressHelper routerAddress;
routerAddress.SetBase ("10.2.1.0", "255.255.255.0");
Ipv4AddressHelper routerAddress;
routerAddress.SetBase("10.2.1.0", "255.255.255.0");
Ipv4AddressHelper rightAddress;
rightAddress.SetBase ("10.3.1.0", "255.255.255.0");
Ipv4AddressHelper rightAddress;
rightAddress.SetBase("10.3.1.0", "255.255.255.0");
// Router-to-Router interfaces
routerInterfaces = routerAddress.Assign (routerDevices);
// Router-to-Router interfaces
routerInterfaces = routerAddress.Assign(routerDevices);
// Left interfaces
for (uint32_t i = 0; i < 4; ++i)
// Left interfaces
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer ndc;
ndc.Add (leftLeafDevices.Get (i));
ndc.Add (leftRouterDevices.Get (i));
Ipv4InterfaceContainer ifc = leftAddress.Assign (ndc);
leftLeafInterfaces.Add (ifc.Get (0));
leftRouterInterfaces.Add (ifc.Get (1));
leftAddress.NewNetwork ();
NetDeviceContainer ndc;
ndc.Add(leftLeafDevices.Get(i));
ndc.Add(leftRouterDevices.Get(i));
Ipv4InterfaceContainer ifc = leftAddress.Assign(ndc);
leftLeafInterfaces.Add(ifc.Get(0));
leftRouterInterfaces.Add(ifc.Get(1));
leftAddress.NewNetwork();
}
// Right interfaces
for (uint32_t i = 0; i < 4; ++i)
// Right interfaces
for (uint32_t i = 0; i < 4; ++i)
{
NetDeviceContainer ndc;
ndc.Add (rightLeafDevices.Get (i));
ndc.Add (rightRouterDevices.Get (i));
Ipv4InterfaceContainer ifc = rightAddress.Assign (ndc);
rightLeafInterfaces.Add (ifc.Get (0));
rightRouterInterfaces.Add (ifc.Get (1));
rightAddress.NewNetwork ();
NetDeviceContainer ndc;
ndc.Add(rightLeafDevices.Get(i));
ndc.Add(rightRouterDevices.Get(i));
Ipv4InterfaceContainer ifc = rightAddress.Assign(ndc);
rightLeafInterfaces.Add(ifc.Get(0));
rightRouterInterfaces.Add(ifc.Get(1));
rightAddress.NewNetwork();
}
if (!nix)
if (!nix)
{
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
}
if (tracing == true)
if (tracing == true)
{
if (systemId == 0)
if (systemId == 0)
{
routerLink.EnablePcap("router-left", routerDevices, true);
leafLink.EnablePcap("leaf-left", leftLeafDevices, true);
routerLink.EnablePcap("router-left", routerDevices, true);
leafLink.EnablePcap("leaf-left", leftLeafDevices, true);
}
if (systemId == 1)
if (systemId == 1)
{
routerLink.EnablePcap("router-right", routerDevices, true);
leafLink.EnablePcap("leaf-right", rightLeafDevices, true);
routerLink.EnablePcap("router-right", routerDevices, true);
leafLink.EnablePcap("leaf-right", rightLeafDevices, true);
}
}
// Create a packet sink on the right leafs to receive packets from left leafs
// Create a packet sink on the right leafs to receive packets from left leafs
uint16_t port = 50000;
if (systemId == 1)
uint16_t port = 50000;
if (systemId == 1)
{
Address sinkLocalAddress (InetSocketAddress (Ipv4Address::GetAny (), port));
PacketSinkHelper sinkHelper ("ns3::UdpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp;
for (uint32_t i = 0; i < 4; ++i)
Address sinkLocalAddress(InetSocketAddress(Ipv4Address::GetAny(), port));
PacketSinkHelper sinkHelper("ns3::UdpSocketFactory", sinkLocalAddress);
ApplicationContainer sinkApp;
for (uint32_t i = 0; i < 4; ++i)
{
sinkApp.Add (sinkHelper.Install (rightLeafNodes.Get (i)));
if (testing)
sinkApp.Add(sinkHelper.Install(rightLeafNodes.Get(i)));
if (testing)
{
sinkApp.Get (i)->TraceConnectWithoutContext ("RxWithAddresses", MakeCallback (&SinkTracer::SinkTrace));
sinkApp.Get(i)->TraceConnectWithoutContext("RxWithAddresses",
MakeCallback(&SinkTracer::SinkTrace));
}
}
sinkApp.Start (Seconds (1.0));
sinkApp.Stop (Seconds (5));
sinkApp.Start(Seconds(1.0));
sinkApp.Stop(Seconds(5));
}
// Create the OnOff applications to send
if (systemId == 0)
// Create the OnOff applications to send
if (systemId == 0)
{
OnOffHelper clientHelper ("ns3::UdpSocketFactory", Address ());
clientHelper.SetAttribute
("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1]"));
clientHelper.SetAttribute
("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0]"));
OnOffHelper clientHelper("ns3::UdpSocketFactory", Address());
clientHelper.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
clientHelper.SetAttribute("OffTime",
StringValue("ns3::ConstantRandomVariable[Constant=0]"));
ApplicationContainer clientApps;
for (uint32_t i = 0; i < 4; ++i)
ApplicationContainer clientApps;
for (uint32_t i = 0; i < 4; ++i)
{
AddressValue remoteAddress
(InetSocketAddress (rightLeafInterfaces.GetAddress (i), port));
clientHelper.SetAttribute ("Remote", remoteAddress);
clientApps.Add (clientHelper.Install (leftLeafNodes.Get (i)));
AddressValue remoteAddress(InetSocketAddress(rightLeafInterfaces.GetAddress(i), port));
clientHelper.SetAttribute("Remote", remoteAddress);
clientApps.Add(clientHelper.Install(leftLeafNodes.Get(i)));
}
clientApps.Start (Seconds (1.0));
clientApps.Stop (Seconds (5));
clientApps.Start(Seconds(1.0));
clientApps.Stop(Seconds(5));
}
Simulator::Stop (Seconds (5));
Simulator::Run ();
Simulator::Destroy ();
Simulator::Stop(Seconds(5));
Simulator::Run();
Simulator::Destroy();
if (testing)
if (testing)
{
SinkTracer::Verify (4);
SinkTracer::Verify(4);
}
// Exit the MPI execution environment
MpiInterface::Disable ();
return 0;
// Exit the MPI execution environment
MpiInterface::Disable();
return 0;
}

View File

@@ -25,351 +25,372 @@
// This object contains static methods that provide an easy interface
// to the necessary MPI information.
#include <iostream>
#include <iomanip>
#include <list>
#include "granted-time-window-mpi-interface.h"
#include "mpi-receiver.h"
#include "mpi-interface.h"
#include "ns3/node.h"
#include "ns3/node-list.h"
#include "ns3/net-device.h"
#include "ns3/simulator.h"
#include "ns3/simulator-impl.h"
#include "ns3/nstime.h"
#include "mpi-interface.h"
#include "mpi-receiver.h"
#include "ns3/log.h"
#include "ns3/net-device.h"
#include "ns3/node-list.h"
#include "ns3/node.h"
#include "ns3/nstime.h"
#include "ns3/simulator-impl.h"
#include "ns3/simulator.h"
#include <iomanip>
#include <iostream>
#include <list>
#ifdef NS3_MTP
#include "ns3/mtp-interface.h"
#endif
#include <mpi.h>
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("GrantedTimeWindowMpiInterface");
NS_OBJECT_ENSURE_REGISTERED (GrantedTimeWindowMpiInterface);
SentBuffer::SentBuffer ()
namespace ns3
{
m_buffer = 0;
m_request = 0;
NS_LOG_COMPONENT_DEFINE("GrantedTimeWindowMpiInterface");
NS_OBJECT_ENSURE_REGISTERED(GrantedTimeWindowMpiInterface);
SentBuffer::SentBuffer()
{
m_buffer = 0;
m_request = 0;
}
SentBuffer::~SentBuffer ()
SentBuffer::~SentBuffer()
{
delete [] m_buffer;
delete[] m_buffer;
}
uint8_t*
SentBuffer::GetBuffer ()
SentBuffer::GetBuffer()
{
return m_buffer;
return m_buffer;
}
void
SentBuffer::SetBuffer (uint8_t* buffer)
SentBuffer::SetBuffer(uint8_t* buffer)
{
m_buffer = buffer;
m_buffer = buffer;
}
MPI_Request*
SentBuffer::GetRequest ()
SentBuffer::GetRequest()
{
return &m_request;
return &m_request;
}
uint32_t GrantedTimeWindowMpiInterface::g_sid = 0;
uint32_t GrantedTimeWindowMpiInterface::g_size = 1;
bool GrantedTimeWindowMpiInterface::g_enabled = false;
bool GrantedTimeWindowMpiInterface::g_mpiInitCalled = false;
uint32_t GrantedTimeWindowMpiInterface::g_rxCount = 0;
uint32_t GrantedTimeWindowMpiInterface::g_txCount = 0;
uint32_t GrantedTimeWindowMpiInterface::g_sid = 0;
uint32_t GrantedTimeWindowMpiInterface::g_size = 1;
bool GrantedTimeWindowMpiInterface::g_enabled = false;
bool GrantedTimeWindowMpiInterface::g_mpiInitCalled = false;
uint32_t GrantedTimeWindowMpiInterface::g_rxCount = 0;
uint32_t GrantedTimeWindowMpiInterface::g_txCount = 0;
std::list<SentBuffer> GrantedTimeWindowMpiInterface::g_pendingTx;
MPI_Request* GrantedTimeWindowMpiInterface::g_requests;
char** GrantedTimeWindowMpiInterface::g_pRxBuffers;
MPI_Comm GrantedTimeWindowMpiInterface::g_communicator = MPI_COMM_WORLD;
bool GrantedTimeWindowMpiInterface::g_freeCommunicator = false;;
char** GrantedTimeWindowMpiInterface::g_pRxBuffers;
MPI_Comm GrantedTimeWindowMpiInterface::g_communicator = MPI_COMM_WORLD;
bool GrantedTimeWindowMpiInterface::g_freeCommunicator = false;
;
#ifdef NS3_MTP
std::atomic<bool> GrantedTimeWindowMpiInterface::g_sending (false);
std::atomic<bool> GrantedTimeWindowMpiInterface::g_sending(false);
#endif
TypeId
GrantedTimeWindowMpiInterface::GetTypeId (void)
TypeId
GrantedTimeWindowMpiInterface::GetTypeId(void)
{
static TypeId tid = TypeId ("ns3::GrantedTimeWindowMpiInterface")
.SetParent<Object> ()
.SetGroupName ("Mpi")
;
return tid;
static TypeId tid =
TypeId("ns3::GrantedTimeWindowMpiInterface").SetParent<Object>().SetGroupName("Mpi");
return tid;
}
void
GrantedTimeWindowMpiInterface::Destroy ()
GrantedTimeWindowMpiInterface::Destroy()
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION(this);
for (uint32_t i = 0; i < GetSize (); ++i)
for (uint32_t i = 0; i < GetSize(); ++i)
{
delete [] g_pRxBuffers[i];
delete[] g_pRxBuffers[i];
}
delete [] g_pRxBuffers;
delete [] g_requests;
delete[] g_pRxBuffers;
delete[] g_requests;
g_pendingTx.clear ();
g_pendingTx.clear();
}
uint32_t
GrantedTimeWindowMpiInterface::GetRxCount ()
GrantedTimeWindowMpiInterface::GetRxCount()
{
NS_ASSERT (g_enabled);
return g_rxCount;
NS_ASSERT(g_enabled);
return g_rxCount;
}
uint32_t
GrantedTimeWindowMpiInterface::GetTxCount ()
GrantedTimeWindowMpiInterface::GetTxCount()
{
NS_ASSERT (g_enabled);
return g_txCount;
NS_ASSERT(g_enabled);
return g_txCount;
}
uint32_t
GrantedTimeWindowMpiInterface::GetSystemId ()
GrantedTimeWindowMpiInterface::GetSystemId()
{
NS_ASSERT (g_enabled);
return g_sid;
NS_ASSERT(g_enabled);
return g_sid;
}
uint32_t
GrantedTimeWindowMpiInterface::GetSize ()
GrantedTimeWindowMpiInterface::GetSize()
{
NS_ASSERT (g_enabled);
return g_size;
NS_ASSERT(g_enabled);
return g_size;
}
bool
GrantedTimeWindowMpiInterface::IsEnabled ()
GrantedTimeWindowMpiInterface::IsEnabled()
{
return g_enabled;
return g_enabled;
}
MPI_Comm
GrantedTimeWindowMpiInterface::GetCommunicator()
{
NS_ASSERT (g_enabled);
return g_communicator;
NS_ASSERT(g_enabled);
return g_communicator;
}
void
GrantedTimeWindowMpiInterface::Enable (int* pargc, char*** pargv)
GrantedTimeWindowMpiInterface::Enable(int* pargc, char*** pargv)
{
NS_LOG_FUNCTION (this << pargc << pargv);
NS_LOG_FUNCTION(this << pargc << pargv);
NS_ASSERT (g_enabled == false);
NS_ASSERT(g_enabled == false);
// Initialize the MPI interface
MPI_Init (pargc, pargv);
Enable (MPI_COMM_WORLD);
g_mpiInitCalled = true;
g_enabled = true;
// Initialize the MPI interface
MPI_Init(pargc, pargv);
Enable(MPI_COMM_WORLD);
g_mpiInitCalled = true;
g_enabled = true;
}
void
GrantedTimeWindowMpiInterface::Enable (MPI_Comm communicator)
GrantedTimeWindowMpiInterface::Enable(MPI_Comm communicator)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION(this);
NS_ASSERT (g_enabled == false);
NS_ASSERT(g_enabled == false);
// Standard MPI practice is to duplicate the communicator for
// library to use. Library communicates in isolated communication
// context.
MPI_Comm_dup (communicator, &g_communicator);
g_freeCommunicator = true;
// Standard MPI practice is to duplicate the communicator for
// library to use. Library communicates in isolated communication
// context.
MPI_Comm_dup(communicator, &g_communicator);
g_freeCommunicator = true;
MPI_Barrier (g_communicator);
MPI_Barrier(g_communicator);
int mpiSystemId;
int mpiSize;
MPI_Comm_rank (g_communicator, &mpiSystemId);
MPI_Comm_size (g_communicator, &mpiSize);
g_sid = mpiSystemId;
g_size = mpiSize;
int mpiSystemId;
int mpiSize;
MPI_Comm_rank(g_communicator, &mpiSystemId);
MPI_Comm_size(g_communicator, &mpiSize);
g_sid = mpiSystemId;
g_size = mpiSize;
g_enabled = true;
// Post a non-blocking receive for all peers
g_pRxBuffers = new char*[g_size];
g_requests = new MPI_Request[g_size];
for (uint32_t i = 0; i < GetSize (); ++i)
g_enabled = true;
// Post a non-blocking receive for all peers
g_pRxBuffers = new char*[g_size];
g_requests = new MPI_Request[g_size];
for (uint32_t i = 0; i < GetSize(); ++i)
{
g_pRxBuffers[i] = new char[MAX_MPI_MSG_SIZE];
MPI_Irecv (g_pRxBuffers[i], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
g_communicator, &g_requests[i]);
g_pRxBuffers[i] = new char[MAX_MPI_MSG_SIZE];
MPI_Irecv(g_pRxBuffers[i],
MAX_MPI_MSG_SIZE,
MPI_CHAR,
MPI_ANY_SOURCE,
0,
g_communicator,
&g_requests[i]);
}
}
void
GrantedTimeWindowMpiInterface::SendPacket (Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev)
GrantedTimeWindowMpiInterface::SendPacket(Ptr<Packet> p,
const Time& rxTime,
uint32_t node,
uint32_t dev)
{
NS_LOG_FUNCTION (this << p << rxTime.GetTimeStep () << node << dev);
NS_LOG_FUNCTION(this << p << rxTime.GetTimeStep() << node << dev);
#ifdef NS3_MTP
while (g_sending.exchange (true, std::memory_order_acquire))
;
while (g_sending.exchange(true, std::memory_order_acquire))
;
#endif
SentBuffer sendBuf;
g_pendingTx.push_back (sendBuf);
std::list<SentBuffer>::reverse_iterator i = g_pendingTx.rbegin (); // Points to the last element
SentBuffer sendBuf;
g_pendingTx.push_back(sendBuf);
std::list<SentBuffer>::reverse_iterator i = g_pendingTx.rbegin(); // Points to the last element
uint32_t serializedSize = p->GetSerializedSize ();
uint8_t* buffer = new uint8_t[serializedSize + 16];
i->SetBuffer (buffer);
// Add the time, dest node and dest device
uint64_t t = rxTime.GetInteger ();
uint64_t* pTime = reinterpret_cast <uint64_t *> (buffer);
*pTime++ = t;
uint32_t* pData = reinterpret_cast<uint32_t *> (pTime);
*pData++ = node;
*pData++ = dev;
// Serialize the packet
p->Serialize (reinterpret_cast<uint8_t *> (pData), serializedSize);
uint32_t serializedSize = p->GetSerializedSize();
uint8_t* buffer = new uint8_t[serializedSize + 16];
i->SetBuffer(buffer);
// Add the time, dest node and dest device
uint64_t t = rxTime.GetInteger();
uint64_t* pTime = reinterpret_cast<uint64_t*>(buffer);
*pTime++ = t;
uint32_t* pData = reinterpret_cast<uint32_t*>(pTime);
*pData++ = node;
*pData++ = dev;
// Serialize the packet
p->Serialize(reinterpret_cast<uint8_t*>(pData), serializedSize);
// Find the system id for the destination node
Ptr<Node> destNode = NodeList::GetNode (node);
// Find the system id for the destination node
Ptr<Node> destNode = NodeList::GetNode(node);
#ifdef NS3_MTP
uint32_t nodeSysId = destNode->GetSystemId () & 0xFFFF;
uint32_t nodeSysId = destNode->GetSystemId() & 0xFFFF;
#else
uint32_t nodeSysId = destNode->GetSystemId ();
uint32_t nodeSysId = destNode->GetSystemId();
#endif
MPI_Isend (reinterpret_cast<void *> (i->GetBuffer ()), serializedSize + 16, MPI_CHAR, nodeSysId,
0, g_communicator, (i->GetRequest ()));
g_txCount++;
MPI_Isend(reinterpret_cast<void*>(i->GetBuffer()),
serializedSize + 16,
MPI_CHAR,
nodeSysId,
0,
g_communicator,
(i->GetRequest()));
g_txCount++;
#ifdef NS3_MTP
g_sending.store(false, std::memory_order_release);
g_sending.store(false, std::memory_order_release);
#endif
}
void
GrantedTimeWindowMpiInterface::ReceiveMessages ()
GrantedTimeWindowMpiInterface::ReceiveMessages()
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_FUNCTION_NOARGS();
// Poll the non-block reads to see if data arrived
while (true)
// Poll the non-block reads to see if data arrived
while (true)
{
int flag = 0;
int index = 0;
MPI_Status status;
int flag = 0;
int index = 0;
MPI_Status status;
MPI_Testany (MpiInterface::GetSize (), g_requests, &index, &flag, &status);
if (!flag)
MPI_Testany(MpiInterface::GetSize(), g_requests, &index, &flag, &status);
if (!flag)
{
break; // No more messages
break; // No more messages
}
int count;
MPI_Get_count (&status, MPI_CHAR, &count);
g_rxCount++; // Count this receive
int count;
MPI_Get_count(&status, MPI_CHAR, &count);
g_rxCount++; // Count this receive
// Get the meta data first
uint64_t* pTime = reinterpret_cast<uint64_t *> (g_pRxBuffers[index]);
uint64_t time = *pTime++;
uint32_t* pData = reinterpret_cast<uint32_t *> (pTime);
uint32_t node = *pData++;
uint32_t dev = *pData++;
// Get the meta data first
uint64_t* pTime = reinterpret_cast<uint64_t*>(g_pRxBuffers[index]);
uint64_t time = *pTime++;
uint32_t* pData = reinterpret_cast<uint32_t*>(pTime);
uint32_t node = *pData++;
uint32_t dev = *pData++;
Time rxTime (time);
Time rxTime(time);
count -= sizeof (time) + sizeof (node) + sizeof (dev);
count -= sizeof(time) + sizeof(node) + sizeof(dev);
Ptr<Packet> p = Create<Packet> (reinterpret_cast<uint8_t *> (pData), count, true);
Ptr<Packet> p = Create<Packet>(reinterpret_cast<uint8_t*>(pData), count, true);
// Find the correct node/device to schedule receive event
Ptr<Node> pNode = NodeList::GetNode (node);
Ptr<MpiReceiver> pMpiRec = 0;
uint32_t nDevices = pNode->GetNDevices ();
for (uint32_t i = 0; i < nDevices; ++i)
// Find the correct node/device to schedule receive event
Ptr<Node> pNode = NodeList::GetNode(node);
Ptr<MpiReceiver> pMpiRec = 0;
uint32_t nDevices = pNode->GetNDevices();
for (uint32_t i = 0; i < nDevices; ++i)
{
Ptr<NetDevice> pThisDev = pNode->GetDevice (i);
if (pThisDev->GetIfIndex () == dev)
Ptr<NetDevice> pThisDev = pNode->GetDevice(i);
if (pThisDev->GetIfIndex() == dev)
{
pMpiRec = pThisDev->GetObject<MpiReceiver> ();
break;
pMpiRec = pThisDev->GetObject<MpiReceiver>();
break;
}
}
NS_ASSERT (pNode && pMpiRec);
NS_ASSERT(pNode && pMpiRec);
// Schedule the rx event
// Schedule the rx event
#ifdef NS3_MTP
MtpInterface::GetSystem (pNode->GetSystemId () >> 16)
->ScheduleAt (pNode->GetId (), rxTime, MakeEvent (&MpiReceiver::Receive, pMpiRec, p));
MtpInterface::GetSystem(pNode->GetSystemId() >> 16)
->ScheduleAt(pNode->GetId(), rxTime, MakeEvent(&MpiReceiver::Receive, pMpiRec, p));
#else
Simulator::ScheduleWithContext (pNode->GetId (), rxTime - Simulator::Now (),
&MpiReceiver::Receive, pMpiRec, p);
Simulator::ScheduleWithContext(pNode->GetId(),
rxTime - Simulator::Now(),
&MpiReceiver::Receive,
pMpiRec,
p);
#endif
// Re-queue the next read
MPI_Irecv (g_pRxBuffers[index], MAX_MPI_MSG_SIZE, MPI_CHAR, MPI_ANY_SOURCE, 0,
g_communicator, &g_requests[index]);
// Re-queue the next read
MPI_Irecv(g_pRxBuffers[index],
MAX_MPI_MSG_SIZE,
MPI_CHAR,
MPI_ANY_SOURCE,
0,
g_communicator,
&g_requests[index]);
}
}
void
GrantedTimeWindowMpiInterface::TestSendComplete ()
GrantedTimeWindowMpiInterface::TestSendComplete()
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_FUNCTION_NOARGS();
std::list<SentBuffer>::iterator i = g_pendingTx.begin ();
while (i != g_pendingTx.end ())
std::list<SentBuffer>::iterator i = g_pendingTx.begin();
while (i != g_pendingTx.end())
{
MPI_Status status;
int flag = 0;
MPI_Test (i->GetRequest (), &flag, &status);
std::list<SentBuffer>::iterator current = i; // Save current for erasing
i++; // Advance to next
if (flag)
MPI_Status status;
int flag = 0;
MPI_Test(i->GetRequest(), &flag, &status);
std::list<SentBuffer>::iterator current = i; // Save current for erasing
i++; // Advance to next
if (flag)
{ // This message is complete
g_pendingTx.erase (current);
g_pendingTx.erase(current);
}
}
}
void
GrantedTimeWindowMpiInterface::Disable ()
GrantedTimeWindowMpiInterface::Disable()
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_FUNCTION_NOARGS();
if (g_freeCommunicator)
if (g_freeCommunicator)
{
MPI_Comm_free (&g_communicator);
g_freeCommunicator = false;
MPI_Comm_free(&g_communicator);
g_freeCommunicator = false;
}
// ns-3 should MPI finalize only if ns-3 was used to initialize
if (g_mpiInitCalled)
// ns-3 should MPI finalize only if ns-3 was used to initialize
if (g_mpiInitCalled)
{
int flag = 0;
MPI_Initialized (&flag);
if (flag)
int flag = 0;
MPI_Initialized(&flag);
if (flag)
{
MPI_Finalize ();
MPI_Finalize();
}
else
else
{
NS_FATAL_ERROR ("Cannot disable MPI environment without Initializing it first");
NS_FATAL_ERROR("Cannot disable MPI environment without Initializing it first");
}
g_mpiInitCalled = false;
g_mpiInitCalled = false;
}
g_enabled = false;
g_enabled = false;
}
} // namespace ns3

View File

@@ -28,18 +28,18 @@
#ifndef NS3_GRANTED_TIME_WINDOW_MPI_INTERFACE_H
#define NS3_GRANTED_TIME_WINDOW_MPI_INTERFACE_H
#include <stdint.h>
#include <atomic>
#include <list>
#include "ns3/nstime.h"
#include "ns3/buffer.h"
#include "mpi.h"
#include "parallel-communication-interface.h"
#include "mpi.h"
#include "ns3/buffer.h"
#include "ns3/nstime.h"
namespace ns3 {
#include <atomic>
#include <list>
#include <stdint.h>
namespace ns3
{
/**
* maximum MPI message size for easy
@@ -57,26 +57,26 @@ const uint32_t MAX_MPI_MSG_SIZE = 2000;
*/
class SentBuffer
{
public:
SentBuffer ();
~SentBuffer ();
public:
SentBuffer();
~SentBuffer();
/**
* \return pointer to sent buffer
*/
uint8_t* GetBuffer ();
/**
* \param buffer pointer to sent buffer
*/
void SetBuffer (uint8_t* buffer);
/**
* \return MPI request
*/
MPI_Request* GetRequest ();
/**
* \return pointer to sent buffer
*/
uint8_t* GetBuffer();
/**
* \param buffer pointer to sent buffer
*/
void SetBuffer(uint8_t* buffer);
/**
* \return MPI request
*/
MPI_Request* GetRequest();
private:
uint8_t* m_buffer; /**< The buffer. */
MPI_Request m_request; /**< The MPI request handle. */
private:
uint8_t* m_buffer; /**< The buffer. */
MPI_Request m_request; /**< The MPI request handle. */
};
class Packet;
@@ -94,87 +94,87 @@ class HybridSimulatorImpl;
*/
class GrantedTimeWindowMpiInterface : public ParallelCommunicationInterface, Object
{
public:
/**
* Register this type.
* \return The object TypeId.
*/
static TypeId GetTypeId (void);
public:
/**
* Register this type.
* \return The object TypeId.
*/
static TypeId GetTypeId(void);
// Inherited
virtual void Destroy ();
virtual uint32_t GetSystemId ();
virtual uint32_t GetSize ();
virtual bool IsEnabled ();
virtual void Enable (int* pargc, char*** pargv);
virtual void Enable (MPI_Comm communicator);
virtual void Disable();
virtual void SendPacket (Ptr<Packet> p, const Time &rxTime, uint32_t node, uint32_t dev);
virtual MPI_Comm GetCommunicator();
// Inherited
virtual void Destroy();
virtual uint32_t GetSystemId();
virtual uint32_t GetSize();
virtual bool IsEnabled();
virtual void Enable(int* pargc, char*** pargv);
virtual void Enable(MPI_Comm communicator);
virtual void Disable();
virtual void SendPacket(Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev);
virtual MPI_Comm GetCommunicator();
/*
* The granted time window implementation is a collaboration of several
* classes. Methods that should be invoked only by the
* collaborators are private to restrict use.
* It is not intended for state to be shared.
*/
friend ns3::DistributedSimulatorImpl;
friend ns3::HybridSimulatorImpl;
/*
* The granted time window implementation is a collaboration of several
* classes. Methods that should be invoked only by the
* collaborators are private to restrict use.
* It is not intended for state to be shared.
*/
friend ns3::DistributedSimulatorImpl;
friend ns3::HybridSimulatorImpl;
/**
* Check for received messages complete
*/
static void ReceiveMessages ();
/**
* Check for completed sends
*/
static void TestSendComplete ();
/**
* \return received count in packets
*/
static uint32_t GetRxCount ();
/**
* \return transmitted count in packets
*/
static uint32_t GetTxCount ();
/**
* Check for received messages complete
*/
static void ReceiveMessages();
/**
* Check for completed sends
*/
static void TestSendComplete();
/**
* \return received count in packets
*/
static uint32_t GetRxCount();
/**
* \return transmitted count in packets
*/
static uint32_t GetTxCount();
/** System ID (rank) for this task. */
static uint32_t g_sid;
/** Size of the MPI COM_WORLD group. */
static uint32_t g_size;
/** System ID (rank) for this task. */
static uint32_t g_sid;
/** Size of the MPI COM_WORLD group. */
static uint32_t g_size;
/** Total packets received. */
static uint32_t g_rxCount;
/** Total packets received. */
static uint32_t g_rxCount;
/** Total packets sent. */
static uint32_t g_txCount;
/** Total packets sent. */
static uint32_t g_txCount;
/** Has this interface been enabled. */
static bool g_enabled;
/** Has this interface been enabled. */
static bool g_enabled;
/**
* Has MPI Init been called by this interface.
* Alternatively user supplies a communicator.
*/
static bool g_mpiInitCalled;
/**
* Has MPI Init been called by this interface.
* Alternatively user supplies a communicator.
*/
static bool g_mpiInitCalled;
/** Pending non-blocking receives. */
static MPI_Request* g_requests;
/** Pending non-blocking receives. */
static MPI_Request* g_requests;
/** Data buffers for non-blocking reads. */
static char** g_pRxBuffers;
/** Data buffers for non-blocking reads. */
static char** g_pRxBuffers;
/** List of pending non-blocking sends. */
static std::list<SentBuffer> g_pendingTx;
/** List of pending non-blocking sends. */
static std::list<SentBuffer> g_pendingTx;
/** MPI communicator being used for ns-3 tasks. */
static MPI_Comm g_communicator;
/** MPI communicator being used for ns-3 tasks. */
static MPI_Comm g_communicator;
/** Did ns-3 create the communicator? Have to free it. */
static bool g_freeCommunicator;
/** Did ns-3 create the communicator? Have to free it. */
static bool g_freeCommunicator;
#ifdef NS3_MTP
static std::atomic<bool> g_sending;
static std::atomic<bool> g_sending;
#endif
};

View File

@@ -1,437 +1,451 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "hybrid-simulator-impl.h"
#include "granted-time-window-mpi-interface.h"
#include "mpi-interface.h"
#include "ns3/channel.h"
#include "ns3/simulator.h"
#include "ns3/node.h"
#include "ns3/mtp-interface.h"
#include "ns3/node-container.h"
#include "ns3/node-list.h"
#include "ns3/node.h"
#include "ns3/simulator.h"
#include "ns3/uinteger.h"
#include "ns3/mtp-interface.h"
#include <mpi.h>
#include <algorithm>
#include <mpi.h>
#include <queue>
#include <thread>
namespace ns3 {
NS_LOG_COMPONENT_DEFINE ("HybridSimulatorImpl");
NS_OBJECT_ENSURE_REGISTERED (HybridSimulatorImpl);
HybridSimulatorImpl::HybridSimulatorImpl ()
namespace ns3
{
NS_LOG_FUNCTION (this);
MtpInterface::Enable (1, 0);
m_myId = MpiInterface::GetSystemId ();
m_systemCount = MpiInterface::GetSize ();
NS_LOG_COMPONENT_DEFINE("HybridSimulatorImpl");
// Allocate the LBTS message buffer
m_pLBTS = new LbtsMessage[m_systemCount];
m_smallestTime = Seconds (0);
m_globalFinished = false;
NS_OBJECT_ENSURE_REGISTERED(HybridSimulatorImpl);
HybridSimulatorImpl::HybridSimulatorImpl()
{
NS_LOG_FUNCTION(this);
MtpInterface::Enable(1, 0);
m_myId = MpiInterface::GetSystemId();
m_systemCount = MpiInterface::GetSize();
// Allocate the LBTS message buffer
m_pLBTS = new LbtsMessage[m_systemCount];
m_smallestTime = Seconds(0);
m_globalFinished = false;
}
HybridSimulatorImpl::~HybridSimulatorImpl ()
HybridSimulatorImpl::~HybridSimulatorImpl()
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION(this);
}
TypeId
HybridSimulatorImpl::GetTypeId (void)
HybridSimulatorImpl::GetTypeId(void)
{
static TypeId tid =
TypeId ("ns3::HybridSimulatorImpl")
.SetParent<SimulatorImpl> ()
.SetGroupName ("Mtp")
.AddConstructor<HybridSimulatorImpl> ()
.AddAttribute ("MaxThreads", "The maximum threads used in simulation",
UintegerValue (std::thread::hardware_concurrency ()),
MakeUintegerAccessor (&HybridSimulatorImpl::m_maxThreads),
MakeUintegerChecker<uint32_t> (1))
.AddAttribute ("MinLookahead", "The minimum lookahead in a partition",
TimeValue (TimeStep (1)),
MakeTimeAccessor (&HybridSimulatorImpl::m_minLookahead),
MakeTimeChecker (TimeStep (0)));
return tid;
static TypeId tid = TypeId("ns3::HybridSimulatorImpl")
.SetParent<SimulatorImpl>()
.SetGroupName("Mtp")
.AddConstructor<HybridSimulatorImpl>()
.AddAttribute("MaxThreads",
"The maximum threads used in simulation",
UintegerValue(std::thread::hardware_concurrency()),
MakeUintegerAccessor(&HybridSimulatorImpl::m_maxThreads),
MakeUintegerChecker<uint32_t>(1))
.AddAttribute("MinLookahead",
"The minimum lookahead in a partition",
TimeValue(TimeStep(1)),
MakeTimeAccessor(&HybridSimulatorImpl::m_minLookahead),
MakeTimeChecker(TimeStep(0)));
return tid;
}
void
HybridSimulatorImpl::Destroy ()
HybridSimulatorImpl::Destroy()
{
while (!m_destroyEvents.empty ())
while (!m_destroyEvents.empty())
{
Ptr<EventImpl> ev = m_destroyEvents.front ().PeekEventImpl ();
m_destroyEvents.pop_front ();
NS_LOG_LOGIC ("handle destroy " << ev);
if (!ev->IsCancelled ())
Ptr<EventImpl> ev = m_destroyEvents.front().PeekEventImpl();
m_destroyEvents.pop_front();
NS_LOG_LOGIC("handle destroy " << ev);
if (!ev->IsCancelled())
{
ev->Invoke ();
ev->Invoke();
}
}
MtpInterface::Disable ();
MpiInterface::Destroy ();
MtpInterface::Disable();
MpiInterface::Destroy();
}
bool
HybridSimulatorImpl::IsFinished (void) const
HybridSimulatorImpl::IsFinished(void) const
{
return m_globalFinished;
return m_globalFinished;
}
bool
HybridSimulatorImpl::IsLocalFinished (void) const
HybridSimulatorImpl::IsLocalFinished(void) const
{
return MtpInterface::isFinished ();
return MtpInterface::isFinished();
}
void
HybridSimulatorImpl::Stop (void)
HybridSimulatorImpl::Stop(void)
{
NS_LOG_FUNCTION (this);
for (uint32_t i = 0; i < MtpInterface::GetSize (); i++)
NS_LOG_FUNCTION(this);
for (uint32_t i = 0; i < MtpInterface::GetSize(); i++)
{
MtpInterface::GetSystem (i)->Stop ();
MtpInterface::GetSystem(i)->Stop();
}
}
void
HybridSimulatorImpl::Stop (Time const &delay)
HybridSimulatorImpl::Stop(const Time& delay)
{
NS_LOG_FUNCTION (this << delay.GetTimeStep ());
Simulator::Schedule (delay, &Simulator::Stop);
NS_LOG_FUNCTION(this << delay.GetTimeStep());
Simulator::Schedule(delay, &Simulator::Stop);
}
EventId
HybridSimulatorImpl::Schedule (Time const &delay, EventImpl *event)
HybridSimulatorImpl::Schedule(const Time& delay, EventImpl* event)
{
NS_LOG_FUNCTION (this << delay.GetTimeStep () << event);
return MtpInterface::GetSystem ()->Schedule (delay, event);
NS_LOG_FUNCTION(this << delay.GetTimeStep() << event);
return MtpInterface::GetSystem()->Schedule(delay, event);
}
void
HybridSimulatorImpl::ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *event)
HybridSimulatorImpl::ScheduleWithContext(uint32_t context, const Time& delay, EventImpl* event)
{
NS_LOG_FUNCTION (this << context << delay.GetTimeStep () << event);
NS_LOG_FUNCTION(this << context << delay.GetTimeStep() << event);
if (MtpInterface::GetSize () == 1)
if (MtpInterface::GetSize() == 1)
{
// initialization stage, do not schedule remote
LogicalProcess *local = MtpInterface::GetSystem ();
local->ScheduleWithContext (local, context, delay, event);
// initialization stage, do not schedule remote
LogicalProcess* local = MtpInterface::GetSystem();
local->ScheduleWithContext(local, context, delay, event);
}
else
else
{
LogicalProcess *remote =
MtpInterface::GetSystem (NodeList::GetNode (context)->GetSystemId () >> 16);
MtpInterface::GetSystem ()->ScheduleWithContext (remote, context, delay, event);
LogicalProcess* remote =
MtpInterface::GetSystem(NodeList::GetNode(context)->GetSystemId() >> 16);
MtpInterface::GetSystem()->ScheduleWithContext(remote, context, delay, event);
}
}
EventId
HybridSimulatorImpl::ScheduleNow (EventImpl *event)
HybridSimulatorImpl::ScheduleNow(EventImpl* event)
{
return Schedule (TimeStep (0), event);
return Schedule(TimeStep(0), event);
}
EventId
HybridSimulatorImpl::ScheduleDestroy (EventImpl *event)
HybridSimulatorImpl::ScheduleDestroy(EventImpl* event)
{
EventId id (Ptr<EventImpl> (event, false), GetMaximumSimulationTime ().GetTimeStep (), 0xffffffff,
EventId::DESTROY);
MtpInterface::CriticalSection cs;
m_destroyEvents.push_back (id);
return id;
EventId id(Ptr<EventImpl>(event, false),
GetMaximumSimulationTime().GetTimeStep(),
0xffffffff,
EventId::DESTROY);
MtpInterface::CriticalSection cs;
m_destroyEvents.push_back(id);
return id;
}
void
HybridSimulatorImpl::Remove (const EventId &id)
HybridSimulatorImpl::Remove(const EventId& id)
{
if (id.GetUid () == EventId::DESTROY)
if (id.GetUid() == EventId::DESTROY)
{
// destroy events.
for (std::list<EventId>::iterator i = m_destroyEvents.begin (); i != m_destroyEvents.end ();
i++)
// destroy events.
for (std::list<EventId>::iterator i = m_destroyEvents.begin(); i != m_destroyEvents.end();
i++)
{
if (*i == id)
if (*i == id)
{
m_destroyEvents.erase (i);
break;
m_destroyEvents.erase(i);
break;
}
}
}
else
else
{
MtpInterface::GetSystem ()->Remove (id);
MtpInterface::GetSystem()->Remove(id);
}
}
void
HybridSimulatorImpl::Cancel (const EventId &id)
HybridSimulatorImpl::Cancel(const EventId& id)
{
if (!IsExpired (id))
if (!IsExpired(id))
{
id.PeekEventImpl ()->Cancel ();
id.PeekEventImpl()->Cancel();
}
}
bool
HybridSimulatorImpl::IsExpired (const EventId &id) const
HybridSimulatorImpl::IsExpired(const EventId& id) const
{
if (id.GetUid () == EventId::DESTROY)
if (id.GetUid() == EventId::DESTROY)
{
// destroy events.
if (id.PeekEventImpl () == 0 || id.PeekEventImpl ()->IsCancelled ())
// destroy events.
if (id.PeekEventImpl() == 0 || id.PeekEventImpl()->IsCancelled())
{
return true;
return true;
}
for (std::list<EventId>::const_iterator i = m_destroyEvents.begin ();
i != m_destroyEvents.end (); i++)
for (std::list<EventId>::const_iterator i = m_destroyEvents.begin();
i != m_destroyEvents.end();
i++)
{
if (*i == id)
if (*i == id)
{
return false;
return false;
}
}
return true;
return true;
}
else
else
{
return MtpInterface::GetSystem ()->IsExpired (id);
return MtpInterface::GetSystem()->IsExpired(id);
}
}
void
HybridSimulatorImpl::Run (void)
HybridSimulatorImpl::Run(void)
{
NS_LOG_FUNCTION (this);
NS_LOG_FUNCTION(this);
Partition ();
MtpInterface::RunBefore ();
Partition();
MtpInterface::RunBefore();
m_globalFinished = false;
while (!m_globalFinished)
m_globalFinished = false;
while (!m_globalFinished)
{
GrantedTimeWindowMpiInterface::ReceiveMessages ();
GrantedTimeWindowMpiInterface::TestSendComplete ();
MtpInterface::CalculateSmallestTime ();
LbtsMessage lMsg (GrantedTimeWindowMpiInterface::GetRxCount (),
GrantedTimeWindowMpiInterface::GetTxCount (), m_myId, IsLocalFinished (),
MtpInterface::GetSmallestTime ());
m_pLBTS[m_myId] = lMsg;
MPI_Allgather (&lMsg, sizeof (LbtsMessage), MPI_BYTE, m_pLBTS, sizeof (LbtsMessage), MPI_BYTE,
MpiInterface::GetCommunicator ());
m_smallestTime = m_pLBTS[0].GetSmallestTime ();
GrantedTimeWindowMpiInterface::ReceiveMessages();
GrantedTimeWindowMpiInterface::TestSendComplete();
MtpInterface::CalculateSmallestTime();
LbtsMessage lMsg(GrantedTimeWindowMpiInterface::GetRxCount(),
GrantedTimeWindowMpiInterface::GetTxCount(),
m_myId,
IsLocalFinished(),
MtpInterface::GetSmallestTime());
m_pLBTS[m_myId] = lMsg;
MPI_Allgather(&lMsg,
sizeof(LbtsMessage),
MPI_BYTE,
m_pLBTS,
sizeof(LbtsMessage),
MPI_BYTE,
MpiInterface::GetCommunicator());
m_smallestTime = m_pLBTS[0].GetSmallestTime();
// The totRx and totTx counts insure there are no transient
// messages; If totRx != totTx, there are transients,
// 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 ();
// The totRx and totTx counts insure there are no transient
// messages; If totRx != totTx, there are transients,
// 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();
// calculate smallest time of all hosts
for (uint32_t i = 1; i < m_systemCount; ++i)
// calculate smallest time of all hosts
for (uint32_t i = 1; i < m_systemCount; ++i)
{
if (m_pLBTS[i].GetSmallestTime () < m_smallestTime)
if (m_pLBTS[i].GetSmallestTime() < m_smallestTime)
{
m_smallestTime = m_pLBTS[i].GetSmallestTime ();
m_smallestTime = m_pLBTS[i].GetSmallestTime();
}
totRx += m_pLBTS[i].GetRxCount ();
totTx += m_pLBTS[i].GetTxCount ();
m_globalFinished &= m_pLBTS[i].IsFinished ();
totRx += m_pLBTS[i].GetRxCount();
totTx += m_pLBTS[i].GetTxCount();
m_globalFinished &= m_pLBTS[i].IsFinished();
}
MtpInterface::SetSmallestTime (m_smallestTime);
MtpInterface::SetSmallestTime(m_smallestTime);
// Global halting condition is all nodes have empty queue's and
// no messages are in-flight.
m_globalFinished &= totRx == totTx;
// Global halting condition is all nodes have empty queue's and
// no messages are in-flight.
m_globalFinished &= totRx == totTx;
// Execute next event if it is within the current time window.
// Local task may be completed.
if (totRx == totTx && !IsLocalFinished ())
// Execute next event if it is within the current time window.
// Local task may be completed.
if (totRx == totTx && !IsLocalFinished())
{ // Safe to process
MtpInterface::ProcessOneRound ();
MtpInterface::ProcessOneRound();
}
}
MtpInterface::RunAfter ();
MtpInterface::RunAfter();
}
Time
HybridSimulatorImpl::Now (void) const
HybridSimulatorImpl::Now(void) const
{
// Do not add function logging here, to avoid stack overflow
return MtpInterface::GetSystem ()->Now ();
// Do not add function logging here, to avoid stack overflow
return MtpInterface::GetSystem()->Now();
}
Time
HybridSimulatorImpl::GetDelayLeft (const EventId &id) const
HybridSimulatorImpl::GetDelayLeft(const EventId& id) const
{
if (IsExpired (id))
if (IsExpired(id))
{
return TimeStep (0);
return TimeStep(0);
}
else
else
{
return MtpInterface::GetSystem ()->GetDelayLeft (id);
return MtpInterface::GetSystem()->GetDelayLeft(id);
}
}
Time
HybridSimulatorImpl::GetMaximumSimulationTime (void) const
HybridSimulatorImpl::GetMaximumSimulationTime(void) const
{
return Time::Max () / 2;
return Time::Max() / 2;
}
void
HybridSimulatorImpl::SetScheduler (ObjectFactory schedulerFactory)
HybridSimulatorImpl::SetScheduler(ObjectFactory schedulerFactory)
{
NS_LOG_FUNCTION (this << schedulerFactory);
for (uint32_t i = 0; i < MtpInterface::GetSize (); i++)
NS_LOG_FUNCTION(this << schedulerFactory);
for (uint32_t i = 0; i < MtpInterface::GetSize(); i++)
{
MtpInterface::GetSystem (i)->SetScheduler (schedulerFactory);
MtpInterface::GetSystem(i)->SetScheduler(schedulerFactory);
}
m_schedulerTypeId = schedulerFactory.GetTypeId ();
m_schedulerTypeId = schedulerFactory.GetTypeId();
}
uint32_t
HybridSimulatorImpl::GetSystemId () const
HybridSimulatorImpl::GetSystemId() const
{
return m_myId;
return m_myId;
}
uint32_t
HybridSimulatorImpl::GetContext (void) const
HybridSimulatorImpl::GetContext(void) const
{
return MtpInterface::GetSystem ()->GetContext ();
return MtpInterface::GetSystem()->GetContext();
}
uint64_t
HybridSimulatorImpl::GetEventCount (void) const
HybridSimulatorImpl::GetEventCount(void) const
{
uint64_t eventCount = 0;
for (uint32_t i = 0; i < MtpInterface::GetSize (); i++)
uint64_t eventCount = 0;
for (uint32_t i = 0; i < MtpInterface::GetSize(); i++)
{
eventCount += MtpInterface::GetSystem (i)->GetEventCount ();
eventCount += MtpInterface::GetSystem(i)->GetEventCount();
}
return eventCount;
return eventCount;
}
void
HybridSimulatorImpl::DoDispose (void)
HybridSimulatorImpl::DoDispose(void)
{
delete[] m_pLBTS;
SimulatorImpl::DoDispose ();
delete[] m_pLBTS;
SimulatorImpl::DoDispose();
}
void
HybridSimulatorImpl::Partition ()
HybridSimulatorImpl::Partition()
{
NS_LOG_FUNCTION (this);
uint32_t localSystemId = 0;
NodeContainer nodes = NodeContainer::GetGlobal ();
bool *visited = new bool[nodes.GetN ()]{false};
std::queue<Ptr<Node>> q;
NS_LOG_FUNCTION(this);
uint32_t localSystemId = 0;
NodeContainer nodes = NodeContainer::GetGlobal();
bool* visited = new bool[nodes.GetN()]{false};
std::queue<Ptr<Node>> q;
// perform a BFS on the whole network topo to assign each node a localSystemId
for (NodeContainer::Iterator it = nodes.Begin (); it != nodes.End (); it++)
// perform a BFS on the whole network topo to assign each node a localSystemId
for (NodeContainer::Iterator it = nodes.Begin(); it != nodes.End(); it++)
{
Ptr<Node> node = *it;
if (!visited[node->GetId ()] && node->GetSystemId () == m_myId)
Ptr<Node> node = *it;
if (!visited[node->GetId()] && node->GetSystemId() == m_myId)
{
q.push (node);
localSystemId++;
while (!q.empty ())
q.push(node);
localSystemId++;
while (!q.empty())
{
// pop from BFS queue
node = q.front ();
q.pop ();
visited[node->GetId ()] = true;
// assign this node the current localSystemId
node->SetSystemId (localSystemId << 16 | m_myId);
NS_LOG_INFO ("node " << node->GetId () << " is set to local system "
<< localSystemId);
// pop from BFS queue
node = q.front();
q.pop();
visited[node->GetId()] = true;
// assign this node the current localSystemId
node->SetSystemId(localSystemId << 16 | m_myId);
NS_LOG_INFO("node " << node->GetId() << " is set to local system "
<< localSystemId);
for (uint32_t i = 0; i < node->GetNDevices (); i++)
for (uint32_t i = 0; i < node->GetNDevices(); i++)
{
Ptr<NetDevice> localNetDevice = node->GetDevice (i);
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
Ptr<NetDevice> localNetDevice = node->GetDevice(i);
Ptr<Channel> channel = localNetDevice->GetChannel();
if (channel == 0)
{
continue;
continue;
}
// cut-off p2p links for partition
if (localNetDevice->IsPointToPoint ())
// cut-off p2p links for partition
if (localNetDevice->IsPointToPoint())
{
TimeValue delay;
channel->GetAttribute ("Delay", delay);
// if delay is below threshold, do not cut-off
if (delay.Get () >= m_minLookahead)
TimeValue delay;
channel->GetAttribute("Delay", delay);
// if delay is below threshold, do not cut-off
if (delay.Get() >= m_minLookahead)
{
continue;
continue;
}
}
// grab the adjacent nodes
for (uint32_t j = 0; j < channel->GetNDevices (); j++)
// grab the adjacent nodes
for (uint32_t j = 0; j < channel->GetNDevices(); j++)
{
Ptr<Node> remote = channel->GetDevice (j)->GetNode ();
// if it's not visited, and not remote, add it to the current partition
if (!visited[remote->GetId ()] && node->GetSystemId () == m_myId)
Ptr<Node> remote = channel->GetDevice(j)->GetNode();
// if it's not visited, and not remote, add it to the current partition
if (!visited[remote->GetId()] && node->GetSystemId() == m_myId)
{
q.push (remote);
q.push(remote);
}
}
}
}
}
}
delete[] visited;
delete[] visited;
// after the partition, we finally know the system count
uint32_t systemCount = localSystemId;
uint32_t threadCount = std::min (m_maxThreads, systemCount);
NS_LOG_INFO ("Partition done! " << systemCount << " systems share " << threadCount << " threads");
// after the partition, we finally know the system count
uint32_t systemCount = localSystemId;
uint32_t threadCount = std::min(m_maxThreads, systemCount);
NS_LOG_INFO("Partition done! " << systemCount << " systems share " << threadCount
<< " threads");
// create new systems
Ptr<Scheduler> events = MtpInterface::GetSystem ()->GetPendingEvents ();
MtpInterface::Disable ();
MtpInterface::Enable (threadCount, systemCount);
// create new systems
Ptr<Scheduler> events = MtpInterface::GetSystem()->GetPendingEvents();
MtpInterface::Disable();
MtpInterface::Enable(threadCount, systemCount);
// set scheduler
ObjectFactory schedulerFactory;
schedulerFactory.SetTypeId (m_schedulerTypeId);
for (uint32_t i = 0; i <= systemCount; i++)
// set scheduler
ObjectFactory schedulerFactory;
schedulerFactory.SetTypeId(m_schedulerTypeId);
for (uint32_t i = 0; i <= systemCount; i++)
{
MtpInterface::GetSystem (i)->SetScheduler (schedulerFactory);
MtpInterface::GetSystem(i)->SetScheduler(schedulerFactory);
}
// transfer events to new system
while (!events->IsEmpty ())
// transfer events to new system
while (!events->IsEmpty())
{
Scheduler::Event ev = events->RemoveNext ();
// invoke initialization events (at time 0) by their insertion order
// since they may not be in the same system, causing error
if (ev.key.m_ts == 0)
Scheduler::Event ev = events->RemoveNext();
// invoke initialization events (at time 0) by their insertion order
// since they may not be in the same system, causing error
if (ev.key.m_ts == 0)
{
MtpInterface::GetSystem (ev.key.m_context == Simulator::NO_CONTEXT
? 0
: NodeList::GetNode (ev.key.m_context)->GetSystemId () >> 16)
->InvokeNow (ev);
MtpInterface::GetSystem(ev.key.m_context == Simulator::NO_CONTEXT
? 0
: NodeList::GetNode(ev.key.m_context)->GetSystemId() >> 16)
->InvokeNow(ev);
}
else if (ev.key.m_context == Simulator::NO_CONTEXT)
else if (ev.key.m_context == Simulator::NO_CONTEXT)
{
Schedule (TimeStep (ev.key.m_ts), ev.impl);
Schedule(TimeStep(ev.key.m_ts), ev.impl);
}
else
else
{
ScheduleWithContext (ev.key.m_context, TimeStep (ev.key.m_ts), ev.impl);
ScheduleWithContext(ev.key.m_context, TimeStep(ev.key.m_ts), ev.impl);
}
}
}

View File

@@ -12,59 +12,60 @@
#include <list>
namespace ns3 {
namespace ns3
{
class HybridSimulatorImpl : public SimulatorImpl
{
public:
static TypeId GetTypeId (void);
public:
static TypeId GetTypeId(void);
/** Default constructor. */
HybridSimulatorImpl ();
/** Destructor. */
~HybridSimulatorImpl ();
/** Default constructor. */
HybridSimulatorImpl();
/** Destructor. */
~HybridSimulatorImpl();
// virtual from SimulatorImpl
virtual void Destroy ();
virtual bool IsFinished (void) const;
virtual void Stop (void);
virtual void Stop (Time const &delay);
virtual EventId Schedule (Time const &delay, EventImpl *event);
virtual void ScheduleWithContext (uint32_t context, Time const &delay, EventImpl *event);
virtual EventId ScheduleNow (EventImpl *event);
virtual EventId ScheduleDestroy (EventImpl *event);
virtual void Remove (const EventId &id);
virtual void Cancel (const EventId &id);
virtual bool IsExpired (const EventId &id) const;
virtual void Run (void);
virtual Time Now (void) const;
virtual Time GetDelayLeft (const EventId &id) const;
virtual Time GetMaximumSimulationTime (void) const;
virtual void SetScheduler (ObjectFactory schedulerFactory);
virtual uint32_t GetSystemId (void) const;
virtual uint32_t GetContext (void) const;
virtual uint64_t GetEventCount (void) const;
// virtual from SimulatorImpl
virtual void Destroy();
virtual bool IsFinished(void) const;
virtual void Stop(void);
virtual void Stop(const Time& delay);
virtual EventId Schedule(const Time& delay, EventImpl* event);
virtual void ScheduleWithContext(uint32_t context, const Time& delay, EventImpl* event);
virtual EventId ScheduleNow(EventImpl* event);
virtual EventId ScheduleDestroy(EventImpl* event);
virtual void Remove(const EventId& id);
virtual void Cancel(const EventId& id);
virtual bool IsExpired(const EventId& id) const;
virtual void Run(void);
virtual Time Now(void) const;
virtual Time GetDelayLeft(const EventId& id) const;
virtual Time GetMaximumSimulationTime(void) const;
virtual void SetScheduler(ObjectFactory schedulerFactory);
virtual uint32_t GetSystemId(void) const;
virtual uint32_t GetContext(void) const;
virtual uint64_t GetEventCount(void) const;
private:
// Inherited from Object
virtual void DoDispose (void);
private:
// Inherited from Object
virtual void DoDispose(void);
bool IsLocalFinished (void) const;
bool IsLocalFinished(void) const;
/** Are all parallel instances completed. */
bool m_globalFinished;
/** Are all parallel instances completed. */
bool m_globalFinished;
LbtsMessage *m_pLBTS;
uint32_t m_myId; /**< MPI rank. */
uint32_t m_systemCount; /**< MPI communicator size. */
Time m_smallestTime; /**< End of current window. */
LbtsMessage* m_pLBTS;
uint32_t m_myId; /**< MPI rank. */
uint32_t m_systemCount; /**< MPI communicator size. */
Time m_smallestTime; /**< End of current window. */
void Partition ();
void Partition();
uint32_t m_maxThreads;
Time m_minLookahead;
TypeId m_schedulerTypeId;
std::list<EventId> m_destroyEvents;
uint32_t m_maxThreads;
Time m_minLookahead;
TypeId m_schedulerTypeId;
std::list<EventId> m_destroyEvents;
};
} // namespace ns3

View File

@@ -26,130 +26,130 @@
#include "mpi-interface.h"
#include <ns3/global-value.h>
#include <ns3/string.h>
#include <ns3/log.h>
#include "null-message-mpi-interface.h"
#include "granted-time-window-mpi-interface.h"
#include "null-message-mpi-interface.h"
namespace ns3 {
#include <ns3/global-value.h>
#include <ns3/log.h>
#include <ns3/string.h>
NS_LOG_COMPONENT_DEFINE ("MpiInterface");
namespace ns3
{
NS_LOG_COMPONENT_DEFINE("MpiInterface");
ParallelCommunicationInterface* MpiInterface::g_parallelCommunicationInterface = 0;
void
MpiInterface::Destroy ()
MpiInterface::Destroy()
{
NS_ASSERT (g_parallelCommunicationInterface);
g_parallelCommunicationInterface->Destroy ();
NS_ASSERT(g_parallelCommunicationInterface);
g_parallelCommunicationInterface->Destroy();
}
uint32_t
MpiInterface::GetSystemId ()
MpiInterface::GetSystemId()
{
if ( g_parallelCommunicationInterface )
return g_parallelCommunicationInterface->GetSystemId ();
else
return 0;
if (g_parallelCommunicationInterface)
return g_parallelCommunicationInterface->GetSystemId();
else
return 0;
}
uint32_t
MpiInterface::GetSize ()
MpiInterface::GetSize()
{
if ( g_parallelCommunicationInterface )
return g_parallelCommunicationInterface->GetSize ();
else
return 1;
if (g_parallelCommunicationInterface)
return g_parallelCommunicationInterface->GetSize();
else
return 1;
}
bool
MpiInterface::IsEnabled ()
MpiInterface::IsEnabled()
{
if (g_parallelCommunicationInterface)
if (g_parallelCommunicationInterface)
{
return g_parallelCommunicationInterface->IsEnabled ();
return g_parallelCommunicationInterface->IsEnabled();
}
else
else
{
return false;
return false;
}
}
void
MpiInterface::SetParallelSimulatorImpl (void)
MpiInterface::SetParallelSimulatorImpl(void)
{
StringValue simulationTypeValue;
bool useDefault = true;
StringValue simulationTypeValue;
bool useDefault = true;
if (GlobalValue::GetValueByNameFailSafe ("SimulatorImplementationType", simulationTypeValue))
if (GlobalValue::GetValueByNameFailSafe("SimulatorImplementationType", simulationTypeValue))
{
std::string simulationType = simulationTypeValue.Get ();
std::string simulationType = simulationTypeValue.Get();
// Set communication interface based on the simulation type being used.
// Defaults to synchronous.
if (simulationType.compare ("ns3::NullMessageSimulatorImpl") == 0)
// Set communication interface based on the simulation type being used.
// Defaults to synchronous.
if (simulationType.compare("ns3::NullMessageSimulatorImpl") == 0)
{
g_parallelCommunicationInterface = new NullMessageMpiInterface ();
useDefault = false;
g_parallelCommunicationInterface = new NullMessageMpiInterface();
useDefault = false;
}
else if (simulationType.compare ("ns3::DistributedSimulatorImpl") == 0 || simulationType.compare("ns3::HybridSimulatorImpl") == 0)
else if (simulationType.compare("ns3::DistributedSimulatorImpl") == 0 ||
simulationType.compare("ns3::HybridSimulatorImpl") == 0)
{
g_parallelCommunicationInterface = new GrantedTimeWindowMpiInterface ();
useDefault = false;
g_parallelCommunicationInterface = new GrantedTimeWindowMpiInterface();
useDefault = false;
}
}
// User did not specify a valid parallel simulator; use the default.
if (useDefault)
// User did not specify a valid parallel simulator; use the default.
if (useDefault)
{
g_parallelCommunicationInterface = new GrantedTimeWindowMpiInterface ();
GlobalValue::Bind ("SimulatorImplementationType",
StringValue ("ns3::DistributedSimulatorImpl"));
NS_LOG_WARN ("SimulatorImplementationType was set to non-parallel simulator; setting type to ns3::DistributedSimulatorImp");
g_parallelCommunicationInterface = new GrantedTimeWindowMpiInterface();
GlobalValue::Bind("SimulatorImplementationType",
StringValue("ns3::DistributedSimulatorImpl"));
NS_LOG_WARN("SimulatorImplementationType was set to non-parallel simulator; setting type "
"to ns3::DistributedSimulatorImp");
}
}
void
MpiInterface::Enable (int* pargc, char*** pargv)
MpiInterface::Enable(int* pargc, char*** pargv)
{
SetParallelSimulatorImpl();
SetParallelSimulatorImpl ();
g_parallelCommunicationInterface->Enable (pargc, pargv);
g_parallelCommunicationInterface->Enable(pargc, pargv);
}
void
MpiInterface::Enable (MPI_Comm communicator)
MpiInterface::Enable(MPI_Comm communicator)
{
SetParallelSimulatorImpl ();
g_parallelCommunicationInterface->Enable (communicator);
SetParallelSimulatorImpl();
g_parallelCommunicationInterface->Enable(communicator);
}
void
MpiInterface::SendPacket (Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev)
MpiInterface::SendPacket(Ptr<Packet> p, const Time& rxTime, uint32_t node, uint32_t dev)
{
NS_ASSERT (g_parallelCommunicationInterface);
g_parallelCommunicationInterface->SendPacket (p, rxTime, node, dev);
NS_ASSERT(g_parallelCommunicationInterface);
g_parallelCommunicationInterface->SendPacket(p, rxTime, node, dev);
}
MPI_Comm
MpiInterface::GetCommunicator()
{
NS_ASSERT (g_parallelCommunicationInterface);
return g_parallelCommunicationInterface->GetCommunicator ();
NS_ASSERT(g_parallelCommunicationInterface);
return g_parallelCommunicationInterface->GetCommunicator();
}
void
MpiInterface::Disable ()
MpiInterface::Disable()
{
NS_ASSERT (g_parallelCommunicationInterface);
g_parallelCommunicationInterface->Disable ();
delete g_parallelCommunicationInterface;
g_parallelCommunicationInterface = 0;
NS_ASSERT(g_parallelCommunicationInterface);
g_parallelCommunicationInterface->Disable();
delete g_parallelCommunicationInterface;
g_parallelCommunicationInterface = 0;
}
} // namespace ns3