尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

5G网络切片仿真:从业务流建模到RB资源分配与p99时延验证

5G网络切片仿真:从业务流建模到RB资源分配与p99时延验证 简介这份网络切片仿真资源包面向5G通信网络方向的研究人员、高校师生及工程技术人员用于在共享物理基础设施上模拟多个独立逻辑网络的部署、资源分配与性能评估。内容围绕网络切片核心知识展开涵盖NFV与SDN虚拟化技术、SLA服务等级协议设计、计算存储通信资源分配、切片安全隔离机制以及动态调整与自愈能力等关键议题并涉及自动驾驶、远程医疗、智能工厂等5G典型应用场景的性能预测与优化。资源包共67个文件约280KB以m脚本、ot工程文件、c源码、obj目标文件为主辅以exp、lib、dll、prj等工程配置与库文件构成一套可运行的仿真工程结构便于读者直接加载分析切片模型与调度流程。目前已有1029人学习下载适合希望借助仿真手段深入理解网络切片架构、验证资源管理策略并探索未来通信网络演进的读者参考使用。1. 网络切片仿真.rar一个压缩包背后5G 切片验证到底在仿什么你拿到一个叫「网络切片仿真.rar」的压缩包解压后大概率是一堆 MATLAB 脚本、Python 文件或者 NS-3 的 tcl 配置。别急着双击运行先想清楚一件事网络切片仿真的核心不是「跑起来」而是「在单台机器上复现多租户共享物理网络时每个切片的 SLA 能不能被单独验证」。这解决的是真实 5G 核心网和接入网设备太贵、切片隔离策略调一次要等一周的问题。适合谁做 5G 切片算法验证的研究生、需要给客户演示切片隔离效果但拿不到现网资源的售前工程师、以及想从零理解「无线资源怎么按切片切」的开发者。这个压缩包里的东西本质是一套可复现的沙盒让你在本地把 eMBB、URLLC、mMTC 三种切片混跑看谁抢了谁的资源。2. 先搞懂切片仿真的三层建模从业务流到资源块2.1 为什么不能直接用真实核心网做切片验证真实 5G 网络里网络切片横跨终端、无线接入网、承载网、核心网四个域。你要验证一个 URLLC 切片在拥塞时能不能保住 1ms 时延得同时改 RAN 的调度权重、核心网 UPF 的 QoS Flow 映射、传输网的 VLAN 优先级。现网里动任何一层都要走变更流程而且三张切片同时跑出了问题根本不知道是哪层先崩的。仿真环境的价值在于把四层压缩成三个可独立控制的模块——业务模型、资源模型、调度策略。业务模型决定每个切片产生什么样的包大小、周期、突发性资源模型决定物理层有多少 RB、多少带宽、多少 MEC 算力调度策略决定这些资源怎么分。压缩包里不管用什么语言写的骨架一定是这三块。常见做法是用 Python 写业务流生成和统计用 MATLAB 写调度算法用 NS-3 做包级仿真。但如果你拿到的包只有一种语言大概率是纯 MATLAB 或者纯 Python 的简化模型牺牲了包级精度换可读性。2.2 业务流建模eMBB、URLLC、mMTC 的参数差异在哪三种切片的业务特征完全不同仿真里必须用不同的随机过程描述。eMBB 是高速下载包大、持续、对时延不敏感但对速率敏感URLLC 是工业控制指令包小、周期短、对时延和可靠性极度敏感mMTC 是传感器上报包极小、并发数巨大、对时延几乎无要求。下面是一个业务流生成的最小 Python 示例我一般用这个结构做快速验证import numpy as np def generate_embb_traffic(duration_ms, packet_size_bytes1500, interval_ms1): eMBB: 大包、连续发送模拟视频流或 FTP 下载 num_packets int(duration_ms / interval_ms) # 包大小加 10% 抖动模拟编码速率变化 sizes np.random.normal(packet_size_bytes, packet_size_bytes * 0.1, num_packets) timestamps np.arange(0, duration_ms, interval_ms) return timestamps, sizes.astype(int) def generate_urllc_traffic(duration_ms, packet_size_bytes64, period_ms1): URLLC: 小包、严格周期模拟工业控制指令 num_packets int(duration_ms / period_ms) # 周期抖动控制在 5% 以内否则时延统计会失真 jitter np.random.uniform(-0.05, 0.05, num_packets) * period_ms timestamps np.arange(0, duration_ms, period_ms) jitter sizes np.full(num_packets, packet_size_bytes) return timestamps, sizes def generate_mmtc_traffic(num_devices, duration_ms, report_interval_ms1000): mMTC: 海量设备、稀疏上报模拟传感器 all_timestamps [] all_sizes [] for _ in range(num_devices): # 每个设备的上报时刻加随机偏移避免所有设备同时发 offset np.random.uniform(0, report_interval_ms) ts np.arange(offset, duration_ms, report_interval_ms) all_timestamps.extend(ts) all_sizes.extend(np.random.randint(20, 50, len(ts))) return np.array(all_timestamps), np.array(all_sizes)逻辑说明eMBB 用正态分布加抖动因为真实视频流的包大小随编码内容波动URLLC 的周期抖动必须很小否则你测出来的时延抖动其实是业务源自己产生的不是网络调度导致的mMTC 的关键是设备间的相位偏移如果所有设备从 0 时刻开始周期上报会在仿真开始瞬间产生一个巨大的突发把资源模型冲垮。参数怎么改packet_size_bytes按你实际要模拟的业务改eMBB 常见 1500URLLC 常见 32 到 200mMTC 常见 20 到 100。interval_ms或period_ms决定负载强度改小就是加压。num_devices在 mMTC 里直接决定并发连接数一般从 100 起步逐步加到 1000 看资源模型什么时候崩。2.3 资源模型RB 怎么分给不同切片无线侧的资源单位是 RBResource Block时域 1ms、频域 180kHz。一个 20MHz 带宽的载波有 100 个 RB。仿真里你不需要真的去算 OFDM 符号但必须把 RB 抽象成「时间-频率二维网格」然后按切片分配。常见做法有两种静态预留和动态共享。静态预留是给每个切片固定分 RB比如 eMBB 60 个、URLLC 20 个、mMTC 20 个。优点是隔离性好缺点是资源利用率低。动态共享是所有切片抢同一个 RB 池按调度算法实时分配。优点是利用率高缺点是隔离性靠算法保证算法翻车就全崩。我一般先用静态预留跑通确认业务模型和统计逻辑没问题再切到动态共享调算法。下面是一个 RB 网格分配的简化实现class RBGrid: def __init__(self, num_rbs100, num_ttis1000): # 每个 TTI 是一个 1ms 的调度周期 self.grid np.zeros((num_ttis, num_rbs)) # 0 表示空闲1/2/3 表示切片 ID self.num_rbs num_rbs self.num_ttis num_ttis def allocate_static(self, slice_id, start_rb, num_allocated): 静态分配从 start_rb 开始连续分配 num_allocated 个 RB self.grid[:, start_rb:start_rb num_allocated] slice_id def allocate_dynamic(self, tti, slice_priorities, demands): 动态分配按优先级和需求在每个 TTI 重新分配 remaining_rbs self.num_rbs # 按优先级从高到低排序URLLC 优先级最高 sorted_slices sorted(slice_priorities.items(), keylambda x: -x[1]) for slice_id, _ in sorted_slices: if remaining_rbs 0: break alloc min(demands.get(slice_id, 0), remaining_rbs) # 从当前 TTI 的空闲 RB 里找连续块分配 free_rbs np.where(self.grid[tti] 0)[0] if len(free_rbs) alloc: self.grid[tti, free_rbs[:alloc]] slice_id remaining_rbs - alloc逻辑说明grid的每一行是一个 TTI每一列是一个 RB。静态分配直接切片简单但浪费。动态分配每个 TTI 重新算slice_priorities里 URLLC 给最高值比如 3eMBB 给 2mMTC 给 1。demands是每个切片当前 TTI 需要的 RB 数由业务模型推算。参数怎么改num_rbs按带宽改20MHz 对应 10010MHz 对应 50。num_ttis是仿真总时长1000 就是 1 秒。动态分配里slice_priorities的数值决定抢占顺序但注意如果 URLLC 一直占满eMBB 会饿死实际调的时候要加一个最小保障 RB 数。3. 用 Python 把切片仿真跑起来从环境搭建到出图3.1 环境依赖和目录结构压缩包解压后不管原来是什么结构我建议整理成下面这样方便后续改参数和复现slice_sim/ ├── config/ │ └── slice_config.yaml # 切片参数、业务参数、资源参数 ├── src/ │ ├── traffic.py # 业务流生成 │ ├── resource.py # RB 网格和分配 │ ├── scheduler.py # 调度算法 │ └── metrics.py # 统计和出图 ├── run_sim.py # 主入口 └── requirements.txt依赖只需要 numpy、matplotlib、pyyaml。如果你拿到的包里有 NS-3 或 MATLAB 代码Python 部分可以当预处理和后处理用核心仿真还在原环境跑。pip install numpy matplotlib pyyaml3.2 配置文件怎么写把参数从代码里抽出来把参数写死在代码里是复现的噩梦。我一般用 YAML 管所有可调参数slices: embb: priority: 2 packet_size: 1500 interval_ms: 1 static_rbs: 60 urllc: priority: 3 packet_size: 64 period_ms: 1 static_rbs: 20 mmtc: priority: 1 num_devices: 500 report_interval_ms: 1000 static_rbs: 20 simulation: duration_ms: 1000 num_rbs: 100 mode: static # static 或 dynamic逻辑说明priority只在动态模式生效static_rbs只在静态模式生效。duration_ms和num_rbs是全局参数。改模式只需要改一个字段不用动代码。参数怎么改先跑静态模式确认三种切片的业务流都正常生成再切动态模式看调度效果。num_devices从 500 开始如果仿真太慢就降到 100如果看不出拥塞就加到 1000。3.3 主仿真循环和统计指标主循环按 TTI 推进每个 TTI 做三件事生成业务包、分配 RB、记录统计。下面是一个最小可运行的主循环import yaml import numpy as np from src.traffic import generate_embb_traffic, generate_urllc_traffic, generate_mmtc_traffic from src.resource import RBGrid def run_simulation(config_path): with open(config_path) as f: cfg yaml.safe_load(f) sim_cfg cfg[simulation] num_ttis sim_cfg[duration_ms] grid RBGrid(num_rbssim_cfg[num_rbs], num_ttisnum_ttis) # 生成各切片业务流 embb_ts, embb_sizes generate_embb_traffic(num_ttis, cfg[slices][embb][packet_size]) urllc_ts, urllc_sizes generate_urllc_traffic(num_ttis, cfg[slices][urllc][packet_size]) mmtc_ts, mmtc_sizes generate_mmtc_traffic( cfg[slices][mmtc][num_devices], num_ttis, cfg[slices][mmtc][report_interval_ms] ) # 统计每个切片的成功传输包数和时延 stats {embb: {tx: 0, delay: []}, urllc: {tx: 0, delay: []}, mmtc: {tx: 0, delay: []}} for tti in range(num_ttis): # 静态模式RB 已经预分配好直接算每个切片能传多少包 if sim_cfg[mode] static: embb_rbs cfg[slices][embb][static_rbs] urllc_rbs cfg[slices][urllc][static_rbs] mmtc_rbs cfg[slices][mmtc][static_rbs] else: # 动态模式按优先级和需求分配这里简化为按比例 total sim_cfg[num_rbs] embb_rbs int(total * 0.6) urllc_rbs int(total * 0.2) mmtc_rbs int(total * 0.2) # 每个 RB 每个 TTI 能承载的字节数简化按 1000 字节算 bytes_per_rb 1000 for slice_name, rbs, ts, sizes in [ (embb, embb_rbs, embb_ts, embb_sizes), (urllc, urllc_rbs, urllc_ts, urllc_sizes), (mmtc, mmtc_rbs, mmtc_ts, mmtc_sizes), ]: capacity rbs * bytes_per_rb # 找当前 TTI 到达的包 mask (ts tti) (ts tti 1) arrived_sizes sizes[mask] arrived_ts ts[mask] for pkt_size, pkt_ts in zip(arrived_sizes, arrived_ts): if capacity pkt_size: capacity - pkt_size stats[slice_name][tx] 1 stats[slice_name][delay].append(tti - pkt_ts) else: break # 容量不够后面的包排队或丢弃 return stats if __name__ __main__: stats run_simulation(config/slice_config.yaml) for name, s in stats.items(): delays s[delay] if delays: print(f{name}: tx{s[tx]}, avg_delay{np.mean(delays):.2f}ms, p99_delay{np.percentile(delays, 99):.2f}ms) else: print(f{name}: tx0)逻辑说明bytes_per_rb是简化假设真实值取决于 MCS 和调制方式但做趋势验证够用。每个 TTI 检查哪些包到达按容量依次传输。delay是当前 TTI 减去包生成时刻单位 ms。p99 时延是 URLLC 切片最关键的指标平均值会被大量小时延包拉低看不出问题。参数怎么改bytes_per_rb改大就是信道条件好改小就是信道差。动态模式里的比例分配可以换成真正的调度算法比如按优先级排序后依次满足。num_ttis改大跑更长时间但注意统计时延的数组会变长内存不够就分批统计。3.4 出图把三个切片的时延 CDF 画在一张图上import matplotlib.pyplot as plt def plot_cdf(stats): plt.figure(figsize(8, 5)) for name, s in stats.items(): delays np.sort(s[delay]) if len(delays) 0: continue cdf np.arange(1, len(delays) 1) / len(delays) plt.plot(delays, cdf, labelf{name} (n{len(delays)})) plt.xlabel(Delay (ms)) plt.ylabel(CDF) plt.legend() plt.grid(True, alpha0.3) plt.savefig(slice_delay_cdf.png, dpi150) plt.show()逻辑说明CDF 图能一眼看出 URLLC 的时延是不是集中在 1ms 以内eMBB 是不是有长尾。如果 URLLC 的 CDF 在 1ms 处只有 80%说明有 20% 的包超时调度算法需要调。参数怎么改dpi改大出图更清晰figsize按需调。如果三个切片的时延量级差太多可以用对数坐标但 URLLC 的 1ms 要求用线性坐标更直观。4. 避坑切片仿真里最容易翻车的 5 个地方4.1 现象URLLC 时延统计出来是 0.5ms但实际业务要求 1ms 内看起来达标了原因业务流生成时URLLC 包的生成时刻和 TTI 边界对齐了。比如包在 t0.0ms 生成第一个 TTI 是 0 到 1ms传输完成时刻算作 1ms时延是 1ms。但如果包在 t0.9ms 生成同样在第一个 TTI 传完时延只有 0.1ms。平均下来时延被拉低但最坏情况可能超过 1ms。解决统计时延要用「包生成时刻到传输完成时刻」的差值而不是「TTI 序号差」。并且必须看 p99 或最大值不能只看平均。我一般会在业务流生成时加一个随机相位偏移让包到达时刻均匀分布在 TTI 内避免对齐带来的统计偏差。4.2 现象动态调度模式下mMTC 切片几乎传不出去包原因mMTC 优先级最低动态分配时 URLLC 和 eMBB 先把 RB 抢完mMTC 只能捡剩下的。如果 URLLC 和 eMBB 的负载都很高mMTC 会长期饿死。解决给每个切片设一个最小保障 RB 数不管优先级多低先扣掉保障部分再参与动态竞争。或者在调度算法里加一个老化机制等待时间越长的包优先级越高。我一般用最小保障加简单轮询先保证没有切片完全饿死再调优先级。4.3 现象仿真跑完发现 eMBB 的吞吐量远低于理论值原因bytes_per_rb设得太保守或者 RB 分配时没有考虑 MIMO 和载波聚合。真实 5G 一个 RB 在 20MHz 带宽、256QAM、4x4 MIMO 下能承载的字节数远大于 1000。解决bytes_per_rb按实际配置算。简化公式是bytes_per_rb 12 子载波 × 14 符号 × 调制阶数 × 码率 / 8。256QAM 调制阶数是 8码率 0.9 左右算下来一个 RB 约 1500 到 2000 字节。如果开了 MIMO再乘层数。但注意这是峰值实际调度时还要考虑控制信道开销和参考信号打八折比较稳妥。4.4 现象改了配置文件里的参数但仿真结果完全没变原因代码里硬编码了参数YAML 文件只是摆设。或者主入口读的是另一个配置文件。解决在run_simulation开头加一行打印把读到的配置输出出来确认参数生效。我一般会在每个模块初始化时打印关键参数比如print(fURLLC period: {cfg[slices][urllc][period_ms]}ms)。如果打印值和配置文件不一致说明读错了文件或者被代码覆盖了。4.5 现象仿真跑得特别慢1000 个 TTI 要跑好几分钟原因每个 TTI 都在做全量数组扫描或者业务流生成时用了 Python 循环而不是 numpy 向量化。解决把业务流生成全部向量化generate_mmtc_traffic里的 for 循环改成 numpy 的np.repeat和np.tile。主循环里找当前 TTI 到达的包不要每次扫全量数组提前按时间排序后用指针推进。如果还是慢把统计部分改成只在最后做一次中间只记录原始数据。5. 进阶用置信区间判断仿真结果是不是「玄学」仿真跑出来的数字最怕的是「这次 URLLC 达标了下次又不达标」。单次仿真的结果受随机种子影响很大尤其是 URLLC 的 p99 时延可能因为几个包的随机抖动就超标。我一般会跑 20 次不同随机种子的仿真然后算均值和 95% 置信区间。def run_multiple_seeds(config_path, num_runs20): all_p99 {embb: [], urllc: [], mmtc: []} for seed in range(num_runs): np.random.seed(seed) stats run_simulation(config_path) for name, s in stats.items(): if s[delay]: all_p99[name].append(np.percentile(s[delay], 99)) for name, values in all_p99.items(): values np.array(values) mean np.mean(values) ci_low np.percentile(values, 2.5) ci_high np.percentile(values, 97.5) print(f{name}: p99 mean{mean:.2f}ms, 95% CI[{ci_low:.2f}, {ci_high:.2f}]) return all_p99逻辑说明np.random.seed(seed)保证每次运行的随机序列不同但可复现。np.percentile(values, 2.5)和97.5给出 95% 置信区间。如果 URLLC 的 p99 置信区间上限超过 1ms说明你的调度算法在坏情况下保不住时延要求需要加冗余或改优先级。参数怎么改num_runs至少 20条件允许跑 50 次。如果置信区间太宽说明随机性太大要么增加仿真时长要么检查业务流模型是不是有周期性突发没被平滑掉。我自己的习惯是任何切片仿真结果只要 p99 的置信区间宽度超过均值的 20%就不下结论先加仿真次数或者查业务流模型。这个习惯帮我省了很多「以为算法有效其实只是随机种子好」的后悔药。希望帮到你。本文还有配套的精品资源点击获取
返回列表