2023-09-16

基于 ns-3 的 Unison 网络仿真器

本文介绍一款面向 ns-3 的快速、对用户透明的并行仿真器实现——Unison

Unison 采用细粒度划分与负载自适应调度,用户无需额外配置,即可轻松对模型进行多线程并行仿真。 同时,细粒度划分降低了缓存缺失,负载自适应调度最小化了线程间的相互等待时间,从而实现高效并行。 有关 Unison 的更多信息可参见我们的 EuroSys ’24 论文

支持的 ns-3 版本:≥ 3.36.1。 我们会持续让 Unison 适配 ns-3 的最新版本。 你可以通过 unison-* 标签找到各个支持 Unison 的 ns-3 版本。

快速开始

最快的上手方式是执行命令:

./ns3 configure --enable-mtp --enable-examples

此时编译配置为默认模式(使用 -O2 -g 编译选项)。 若希望使用 -O3 优化编译并关闭所有日志输出,请添加 -d optimized 参数。

--enable-mtp 选项将启用多线程并行。 你可以在可选功能列表中查看是否出现 Multithreaded Simulation : ON,以确认 Unison 已启用。

现在,我们分别编译并运行默认串行仿真与并行仿真(使用 4 线程)的 DCTCP 示例:

./ns3 build dctcp-example dctcp-example-mtp
time ./ns3 run dctcp-example
time ./ns3 run dctcp-example-mtp

dctcp-example 仿真通常需要 4–5 分钟,dctcp-example-mtp 只需 1–2 分钟,具体取决于硬件与编译配置。 *.dat 文件中的输出应与源文件中的注释一致。

拓扑规模越大、流量越大,Unison 的加速效果越显著。 如果你希望用它仿真胖树(fat-tree)、BCube、二维环网(2D-torus)等拓扑,请参考运行评估

为现有代码加速

为了理解 Unison 如何作用于你的模型代码,我们对比上述示例的两个版本源文件:

diff examples/tcp/dctcp-example.cc examples/mtp/dctcp-example-mtp.cc

可以看到,只需在现有模型代码中引入头文件 ns3/mtp-interface.h,并在 main 函数开头添加一行:

MtpInterface::Enable(numberOfThreads);

即可启用 Unison。

参数 numberOfThreads 是可选的。 若省略,线程数将自动选择,且不超过系统可用硬件线程的最大值。 若希望在现有 MPI 程序上启用 Unison 进行分布式仿真以进一步加速,请将上述代码放在 MPI 初始化之前,且不要在代码中显式指定仿真器实现。 对于这种与 MPI 混合的仿真,配置 ns-3 时还需要添加 --enable-mpi 选项。

Unison 解决了 ns-3 架构中大量线程安全问题。 大多数情况下你无需自行处理这些问题,除非你使用了内置流量监控(flow-monitor)之外的自定义全局统计量。 对于后者,如果多个节点可能访问你的全局统计量,可以用 std::atomic<> 将其替换为原子变量。 在采集 Pcap 等追踪数据时,强烈建议为每个节点生成独立输出文件,而非单一追踪文件。 对于复杂的自定义数据结构,可在方法开头添加:

MtpInterface::CriticalSection cs;

来创建临界区。

示例

除 DCTCP 示例外,你还可以在 examples/mtp 中找到其他适配示例。 同时,Unison 也支持手动划分,最简示例位于 src/mtp/examples/simple-mtp.cc。 对于与 MPI 混合的仿真,最简示例位于 src/mpi/examples/simple-hybrid.cc

我们还为 Unison、传统 MPI 并行仿真与混合仿真提供了三个详细的胖树示例:

名称路径所需配置选项运行命令
fat-tree-mtpsrc/mtp/examples/fat-tree-mtp.cc--enable-mtp --enable-examples(不含 --enable-mpi./ns3 run "fat-tree-mtp --thread=4"
fat-tree-mpisrc/mpi/examples/fat-tree-mpi.cc--enable-mpi --enable-examples(不含 --enable-mtp./ns3 run fat-tree-mpi --command-template "mpirun -np 4 %s"
fat-tree-hybridsrc/mpi/examples/fat-tree-hybrid.cc--enable-mtp --enable-mpi --enable-examples./ns3 run fat-tree-hybrid --command-template "mpirun -np 2 %s --thread=2"

你可以自由探索这些示例,对比代码改动,并调整 -np--thread 参数。

运行评估

若要评估 Unison,请切换到 unison-evaluations 分支,该分支基于 ns-3.36.1。 在该分支中,scratch 文件夹下包含多种拓扑模型。 每个拓扑都有大量可配置参数。 我们提供了工具脚本 exp.py 用于对比不同仿真器与参数, 同时提供 process.py 将原始实验数据转换为适合绘图的 CSV 文件。 更多细节请参见 该分支的 README

本次评估制品(基于 ns-3.36.1)的永久 DOI 索引为:10.5281/zenodo.10077300

模块文档

1. 概述

适用于 ns-3 的 Unison 主要在 mtp 模块中实现(位于 src/mtp/*),mtp 即多线程并行(multi-threaded parallelization)。 该模块包含三部分:并行仿真器实现 multithreaded-simulator-impl、面向用户的接口 mtp-interface,以及用于表示并行仿真中逻辑进程(LP)的 logical-process

所有逻辑进程(LP)与线程均存储在 mtp-interface 中。 它控制仿真进度、将 LP 调度到线程、并管理 LP 与线程的生命周期。 该接口还提供了一些方法与选项供用户调整仿真行为。

每个 LP 的逻辑在 logical-process 中实现。 它包含默认串行仿真器的大部分方法,以及一些用于并行仿真的辅助方法。

仿真器实现 multithreaded-simulator-impl 继承自基础仿真器。 它根据当前线程上下文,将对基础仿真器的调用转发到对应逻辑进程。 同时提供了用于拓扑自动细粒度划分的划分方法。

对于基于 MPI 的分布式仿真,我们在 mpi 模块中新增了 hybrid-simulator-impl(位于 src/mpi/model/hybrid-simulator-impl*)。 该仿真器同时使用 mtp-interfacempi-interface 协调本地 LP 与全局 MPI 通信。 我们还对模块进行了修改,使其在本地具备线程安全性。

2. 对 ns-3 架构的修改

mtpmpi 模块外,我们还对 ns-3 架构的以下部分进行了线程安全改造,并修复了部分 ns-3 漏洞。 你可以通过 git diff unison-* ns-* 查看每个支持 Unison 的 ns-3 版本的具体改动。

对构建系统的修改,用于提供 --enable-mtp 选项以启用/禁用 Unison:

ns3                                                |    2 +
CMakeLists.txt                                     |    1 +
build-support/custom-modules/ns3-configtable.cmake |    3 +
build-support/macros-and-definitions.cmake         |   10 +

core 模块的修改,使引用计数具备线程安全性:

src/core/CMakeLists.txt                            |    1 +
src/core/model/atomic-counter.h                    |   50 +
src/core/model/hash.h                              |   16 +
src/core/model/object.cc                           |    2 +
src/core/model/simple-ref-count.h                  |   11 +-

network 模块的修改,使数据包具备线程安全性:

src/network/model/buffer.cc                        |   15 +-
src/network/model/buffer.h                         |    7 +
src/network/model/byte-tag-list.cc                 |   14 +-
src/network/model/node.cc                          |    7 +
src/network/model/node.h                           |    7 +
src/network/model/packet-metadata.cc               |   26 +-
src/network/model/packet-metadata.h                |   14 +-
src/network/model/packet-tag-list.h                |   11 +-
src/network/model/socket.cc                        |    6 +

internet 模块的修改,使其线程安全并增加逐流 ECMP 路由:

src/internet/model/global-route-manager-impl.cc    |    2 +
src/internet/model/ipv4-global-routing.cc          |   32 +-
src/internet/model/ipv4-global-routing.h           |    8 +-
src/internet/model/ipv4-packet-info-tag.cc         |    2 +
src/internet/model/ipv6-packet-info-tag.cc         |    2 +
src/internet/model/tcp-option.cc                   |    2 +-

flow-monitor 模块的修改,使其线程安全:

src/flow-monitor/model/flow-monitor.cc             |   48 +
src/flow-monitor/model/flow-monitor.h              |    4 +
src/flow-monitor/model/ipv4-flow-classifier.cc     |   12 +
src/flow-monitor/model/ipv4-flow-classifier.h      |    5 +
src/flow-monitor/model/ipv4-flow-probe.cc          |    2 +
src/flow-monitor/model/ipv6-flow-classifier.cc     |   12 +
src/flow-monitor/model/ipv6-flow-classifier.h      |    5 +
src/flow-monitor/model/ipv6-flow-probe.cc          |    2 +

nix-vector-routing 模块的修改,使其线程安全:

src/nix-vector-routing/model/nix-vector-routing.cc |   92 ++
src/nix-vector-routing/model/nix-vector-routing.h  |    8 +

mpi 模块的修改,使其在混合仿真器下线程安全:

src/mpi/model/granted-time-window-mpi-interface.cc |   25 +
src/mpi/model/granted-time-window-mpi-interface.h  |    7 +
src/mpi/model/mpi-interface.cc                     |    3 +-

3. 日志

Unison 速度快的原因在于:它将网络以细粒度划分为多个逻辑进程(LP),并对其进行动态调度。 如需了解该流程的更多细节,可以启用以下日志组件:

LogComponentEnable("LogicalProcess", LOG_LEVEL_INFO);
LogComponentEnable("MultithreadedSimulatorImpl", LOG_LEVEL_INFO);

4. 高级选项

这些选项可以在 main 函数开头使用 ns-3 原生配置语法修改。

你也可以通过以下方式修改默认最大线程数:

Config::SetDefault("ns3::MultithreadedSimulatorImpl::MaxThreads", UintegerValue(8));
Config::SetDefault("ns3::HybridSimulatorImpl::MaxThreads", UintegerValue(8));

自动划分会切断延迟高于阈值的无状态链路。 该阈值基于所有链路的延迟自动计算。 若对划分结果不满意,可自定义阈值:

Config::SetDefault("ns3::MultithreadedSimulatorImpl::MinLookahead", TimeValue(NanoSeconds(500)));
Config::SetDefault("ns3::HybridSimulatorImpl::MinLookahead", TimeValue(NanoSeconds(500)));

调度方式决定每个逻辑进程的优先级(下一轮预估完成时间)。 共有五种可选策略:

  • ByExecutionTime:上一轮执行时间更长的 LP 优先级更高。
  • ByPendingEventCount:本轮待处理事件更多的 LP 优先级更高。
  • ByEventCount:与 ByPendingEventCount 含义相同。
  • BySimulationTime:当前仿真时钟更大的 LP 优先级更高。
  • None:不进行调度,按划分 ID 决定优先级。

大量实验表明,第一种通常性能更好。 你也可以根据需要选择:

GlobalValue::Bind("PartitionSchedulingMethod", StringValue("ByExecutionTime"));

默认情况下,划分数小于 16 时调度周期为 2,小于 256 时为 3,小于 4096 时为 4,依此类推。 因为划分越多,调度开销越大。 你也可以手动设置调度频率:

GlobalValue::Bind("PartitionSchedulingPeriod", UintegerValue(4));

引用与链接

如果你觉得代码有用,请考虑引用 我们的论文

@inproceedings{10.1145/3627703.3629574,
author = {Bai, Songyuan and Zheng, Hao and Tian, Chen and Wang, Xiaoliang and Liu, Chang and Jin, Xin and Xiao, Fu and Xiang, Qiao and Dou, Wanchun and Chen, Guihai},
title = {Unison: A Parallel-Efficient and User-Transparent Network Simulation Kernel},
year = {2024},
isbn = {9798400704376},
publisher = {Association for Computing Machinery},
address = {New York, NY, USA},
url = {https://doi.org/10.1145/3627703.3629574},
doi = {10.1145/3627703.3629574},
abstract = {Discrete-event simulation (DES) is a prevalent tool for evaluating network designs. Although DES offers full fidelity and generality, its slow performance limits its application. To speed up DES, many network simulators employ parallel discrete-event simulation (PDES). However, adapting existing network simulation models to PDES requires complex reconfigurations and often yields limited performance improvement. In this paper, we address this gap by proposing a parallel-efficient and user-transparent network simulation kernel, Unison, that adopts fine-grained partition and load-adaptive scheduling optimized for network scenarios. We prototype Unison based on ns-3. Existing network simulation models of ns-3 can be seamlessly transitioned to Unison. Testbed experiments on commodity servers demonstrate that Unison can achieve a 40\texttimes{} speedup over DES using 24 CPU cores, and a 10\texttimes{} speedup compared with existing PDES algorithms under the same CPU cores.},
booktitle = {Proceedings of the Nineteenth European Conference on Computer Systems},
pages = {115–131},
numpages = {17},
keywords = {Data center networks, Network simulation, Parallel discrete-event simulation},
location = {Athens, Greece},
series = {EuroSys '24}
}

以下链接可能对你有帮助: