Параллельное моделирование с использованием NS3 и std::thread

Я использую инфраструктуру NS3 для запуска симуляций Wi-Fi с различными конфигурациями. Я хочу использовать std::thread для одновременного запуска многих (сотней) симуляций в одном процессе.

Вот мой код с отредактированной конфигурацией:

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;
}

Когда я запускаю этот код только для одного задания в jobs, он работает идеально, но для любого большего числа (скажем, двух) я получаю следующий вывод:

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>").

И действительно, запуск его в Valgrind возвращает сотни проблем.

Два вопроса:

  • Возможно ли, что я что-то делаю не так, и NS3 должен это поддерживать?
  • Известно ли, что NS3 не может запускать несколько симуляций параллельно?

person Blake    schedule 22.02.2016    source источник


Ответы (2)


Короткий ответ: вы не можете сделать это с ns-3.

Длинный ответ: используйте несколько процессов вместо нескольких потоков (библиотека ns-3 поддерживает глобальное состояние, которое не защищено от параллелизма нескольких потоков).

Я бы предложил использовать обертки Python ns-3 для простой настройки параллельных многопроцессорных заданий. Это может быть не совсем тривиально, если вы хотите выполнить трассировку за пределами настройки трассировки по умолчанию (в этом случае вам, вероятно, потребуется выполнить собственную трассировку на C++ и настройку топологии на python).

person mathieu    schedule 23.02.2016
comment
Спасибо за ответ! - person Blake; 24.02.2016

Моя работа заключалась в том, чтобы закомментировать 2 проверки утверждений в default-simulator-impl.cc, после чего новые потоки работали нормально:

DefaultSimulatorImpl::Schedule (постоянное время и задержка, EventImpl *event) {

// NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::Schedule Thread-unsafe вызов!"); // строка 231 ... }

DefaultSimulatorImpl::ScheduleNow {

// NS_ASSERT_MSG (SystemThread::Equals (m_main), "Simulator::ScheduleNow Thread-unsafe вызов!"); // строка 284 ... }

Затем запустите valgring, чтобы проверить потенциальные проблемы гонки/памяти.

person Mak    schedule 26.02.2016
comment
Это сработало, как задумано. Однако я заметил более низкую скорость передачи данных в дочерних потоках. Таким образом, похоже, что ns-3 по-прежнему дает больше времени для планирования основному потоку. - person Mak; 27.02.2016
comment
Это худшая идея. ns-3 не работает в многопоточной среде, если вы не убедитесь, что все ваши вызовы ns-3 происходят из одного и того же потока (того, который вызывает Simulator::Run ). Множественные вызовы ns-3 из нескольких потоков в лучшем случае будут генерировать случайный мусор, потому что глубоко внутри ns-3 скрыто общее состояние и общие кэши. - person mathieu; 10.03.2016
comment
Зачем ограничивать его однопоточной реализацией... я видел код, связанный с несколькими потоками, датированный примерно 2009 годом; groups.google.com/forum/#!searchin/ns-3-users/$20multithread/ - person Mak; 11.03.2016