Apply clang-format to modified code for ease of merging
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user