Search code examples
c++multithreadingstdthreadns-3

Parallel simulations using NS3 and std::thread


I am using the NS3 framework to run Wi-Fi simulations with various configurations. I want to use std::thread to run many (hundreds) of simulations simultaneously, within one process.

Here is a my code, with some configuration redacted:

void simulation(RateAdaptation    rate_adaptation,
                const bool        channel_fading,
                // In meters, between AP and station.
                const uint32_t    distance)
{
  ns3::SeedManager::SetSeed(++seed);

  ns3::NodeContainer station_node, ap_node;
  station_node.Create(1);
  ap_node.Create(1);

  ns3::YansWifiChannelHelper channel;
  channel.SetPropagationDelay("ns3::ConstantSpeedPropagationDelayModel");
  channel.AddPropagationLoss( "ns3::LogDistancePropagationLossModel");



  // About 130 lines of more configuration for the simulation and
  // function parameters.



  ns3::Simulator::Stop(ns3::Seconds(10.0));

  ns3::Ptr<ns3::FlowMonitor> flowmon;
  ns3::FlowMonitorHelper *flowmonHelper = new ns3::FlowMonitorHelper();
  flowmon = flowmonHelper->InstallAll();

  ns3::Simulator::Run();
  ns3::Simulator::Destroy();
  flow_output(flowmon, flowmonHelper);
}

int main(int argc, char *argv[])
{
  std::vector<std::thread> jobs;

  for (uint32_t i = 0; i < 20; ++i)
  {
    uint32_t varying_distance = 5*(i+1);

    jobs.push_back(std::thread(simulation,
                               RateAdaptation::Aarf,
                               false,
                               varying_distance));
  }

  for (auto it = jobs.begin(); it < jobs.end(); ++it)
  {
    it.join();
  }

  return 0;
}

When I run this code for just one job in jobs, it works perfect, but for any larger number (say two), I get output like this:

assert failed. cond="SystemThread::Equals (m_main)", msg="Simulator::ScheduleDestroy Thread-unsafe invocation!", file=../src/core/model/default-simulator-impl.cc, line=289
terminate called without an active exception
Command ['[redacted]'] terminated with signal SIGIOT. Run it under a debugger to get more information (./waf --run <program> --comm    and-template="gdb --args %s <args>").

And indeed running it in Valgrind returns hundreds of problems.

Two questions:

  • Is it possible that I'm doing something wrong, and NS3 should support this?
  • Is it known that NS3 can't run multiple simulations in parallel?

Solution

  • The short answer: you can't do this with ns-3.

    The long answer: use multiple processes instead of multiple threads (the ns-3 library maintains global state that is not protected from multiple thread concurency).

    I would suggest using the ns-3 python wrappers to easily setup parallel multiprocessing jobs. It might not be entirely trivial if you want to perform tracing beyond the default tracing setup (in this case, you will probably need to do your own tracing in C++ and the topology setup in python)