简介:网络切片仿真.rar 面向5G通信网络方向的研究生、科研人员与网络工程师,聚焦共享物理基础设施上多虚拟网络的定制化建模与性能评估。资源围绕网络切片概念、NFV与SDN虚拟化技术、SLA服务等级协议、资源分配、安全隔离、动态调整与自愈能力等核心知识点展开,并覆盖eMBB、URLLC、IoT等典型5G应用场景,适合作为仿真实验与课题研究的参考素材。压缩包共67个文件,约280KB,以m脚本、ot模型、c源码、obj目标文件为主,辅以exp、lib、dll、seq、prj等工程与配置文件,构成一套可运行的仿真工程结构。目前已有1031人学习下载。读者可从中获取网络切片建模思路、资源调度与性能评估的仿真框架,以及面向标准化与互操作性的验证参考,便于在Omnet++、ns-3等平台之外拓展自建仿真方案,快速复现并优化切片部署流程。
1. 网络切片仿真.rar 里到底装了什么:从一次资源分配翻车说起
很多人第一次拿到「网络切片仿真.rar」这类资源包,第一反应是解压找入口脚本,结果跑起来发现时延曲线像心电图,带宽利用率却低得可怜。问题往往不在代码本身,而在于没搞清网络切片仿真的核心矛盾:同一套物理设施上,eMBB、URLLC、mMTC 三类业务对资源的需求是互相打架的。URLLC 要的是毫秒级时延和极高可靠性,eMBB 要的是吞吐,mMTC 要的是连接密度和低功耗。仿真要做的,就是在这些冲突目标之间找到可量化的折中方案。
这个资源包适合两类人:一类是刚接触 5G/6G 网络切片、需要一套能跑通的最小仿真环境来理解资源分配逻辑的工程师;另一类是做算法验证的研究者,想在不依赖真实基站的前提下,快速对比不同切片调度策略的 KPI 差异。它解决的不是「怎么建一个商用切片网络」,而是「怎么在本地用可控参数复现切片资源竞争、隔离和优先级调度的全过程」。如果你指望解压后一键出论文级图表,那大概率会失望;但如果你想搞清楚每个参数背后的物理含义,这套东西值得花时间拆开看。
2. 切片仿真的三个核心模块:业务模型、资源网格与调度器
2.1 业务模型:三类切片的流量到底怎么生成
网络切片仿真的第一步不是写调度算法,而是把业务流建模对。常见做法是用泊松过程生成 eMBB 的大包流,用确定性到达间隔加极短包长模拟 URLLC 的周期性控制指令,用 Beta 分布或帕累托分布刻画 mMTC 的突发小包。很多资源包里会带一个traffic_generator.py或类似文件,核心逻辑通常长这样:
import numpy as np def generate_embb_traffic(duration_ms, arrival_rate, avg_pkt_size): """eMBB: 泊松到达,包长服从指数分布""" n_pkts = np.random.poisson(arrival_rate * duration_ms / 1000.0) arrival_times = np.sort(np.random.uniform(0, duration_ms, n_pkts)) pkt_sizes = np.random.exponential(avg_pkt_size, n_pkts) return arrival_times, pkt_sizes def generate_urllc_traffic(duration_ms, period_ms, pkt_size): """URLLC: 确定性周期到达,包长固定""" arrival_times = np.arange(0, duration_ms, period_ms) pkt_sizes = np.full(len(arrival_times), pkt_size) return arrival_times, pkt_sizes def generate_mmtc_traffic(duration_ms, n_devices, burst_prob): """mMTC: 每个设备以一定概率突发小包""" arrival_times, pkt_sizes = [], [] for _ in range(n_devices): t = 0 while t < duration_ms: if np.random.rand() < burst_prob: arrival_times.append(t) pkt_sizes.append(np.random.randint(20, 200)) t += np.random.exponential(100) # 平均100ms一次机会 return np.array(arrival_times), np.array(pkt_sizes)这段代码的关键参数是arrival_rate、period_ms和burst_prob。arrival_rate决定 eMBB 的负载强度,单位是包/秒,设大了会直接把资源网格打满;period_ms是 URLLC 的命根子,通常设 1ms 到 10ms,超过 10ms 就失去低时延意义;burst_prob控制 mMTC 的突发程度,设 0.01 以下接近稀疏,设 0.1 以上会让调度器频繁触发拥塞控制。我一般会先把三类流量分开跑,确认各自的到达间隔和包长分布符合预期,再混在一起做资源竞争。
2.2 资源网格:时频二维网格怎么划
5G NR 的资源网格是时域符号乘以频域子载波。仿真里通常简化成「时隙 × 资源块」的二维矩阵,每个格子代表一个资源单元。资源包里的resource_grid.py一般会定义网格尺寸和每个切片的预留区域:
class ResourceGrid: def __init__(self, n_slots, n_rbs, scs_khz=15): self.n_slots = n_slots # 时隙数 self.n_rbs = n_rbs # 资源块数 self.scs = scs_khz # 子载波间隔 self.grid = np.zeros((n_slots, n_rbs)) # 0=空闲,>0表示被切片占用 self.slice_map = {} # 切片ID -> 预留RB范围 def reserve_slice(self, slice_id, rb_start, rb_end): """为切片预留静态资源""" self.slice_map[slice_id] = (rb_start, rb_end) self.grid[:, rb_start:rb_end] = slice_id def available_rbs(self, slot_idx, slice_id): """返回某时隙下该切片可用的RB索引""" if slice_id not in self.slice_map: return [] rb_start, rb_end = self.slice_map[slice_id] return [rb for rb in range(rb_start, rb_end) if self.grid[slot_idx, rb] == 0 or self.grid[slot_idx, rb] == slice_id]这里最容易被忽略的是scs_khz。15kHz 是默认值,但 URLLC 场景常用 30kHz 或 60kHz 来缩短符号长度,从而降低调度粒度。如果你在仿真里把 scs 设成 60kHz,时隙长度会从 1ms 缩到 0.25ms,URLLC 的周期到达就能落在更细的时间颗粒上。另一个坑是reserve_slice的静态预留方式:它简单直接,但资源利用率低,因为预留的 RB 在切片空闲时别人也用不了。实际仿真里更常见的是半静态预留加动态共享,后面章节会展开。
2.3 调度器:比例公平、最大载干比还是轮询
调度器是切片仿真的灵魂。资源包里通常至少带一个scheduler.py,实现比例公平(PF)、最大载干比(Max C/I)或轮询(RR)中的一种。PF 是最常用的基线,因为它兼顾吞吐和公平性:
def proportional_fair_scheduler(users, rb_alloc, slot_idx): """比例公平调度:按瞬时速率/平均速率的比值排序""" metrics = [] for u in users: instant_rate = estimate_rate(u, rb_alloc, slot_idx) avg_rate = u.get_avg_rate() if avg_rate == 0: metrics.append((u, float('inf'))) else: metrics.append((u, instant_rate / avg_rate)) metrics.sort(key=lambda x: x[1], reverse=True) return [u for u, _ in metrics]estimate_rate依赖信道质量指示(CQI),仿真里常用简化的香农公式或查表法。get_avg_rate是滑动窗口平均,窗口长度一般设 100 到 1000 个时隙。窗口太短,调度器会频繁切换用户,导致信令开销大;窗口太长,公平性变差,边缘用户容易被饿死。我一般先用 500 个时隙跑一轮,看每个切片的用户速率分布是否合理,再微调窗口长度。
3. 用 Python 在本地跑通切片仿真的最小闭环
3.1 环境准备与依赖安装
这套仿真不依赖任何专用硬件,一台普通开发机就能跑。推荐 Python 3.9 以上,核心依赖只有 numpy、scipy 和 matplotlib。如果资源包里带了requirements.txt,直接:
python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate pip install -r requirements.txt如果没有 requirements.txt,手动装:
pip install numpy scipy matplotlib注意不要用 Python 3.12 以下的 3.7/3.8,因为部分 numpy 版本对np.random.Generator的支持不一致,会导致随机种子复现失败。我习惯在脚本开头固定种子:
rng = np.random.default_rng(42)这样每次跑出来的流量和信道都一致,方便对比不同调度策略。
3.2 主仿真循环:从时隙推进到 KPI 采集
主循环的结构通常是「生成流量 → 映射到切片 → 调度 → 资源分配 → 计算 KPI → 推进时隙」。一个最小可跑的例子:
from resource_grid import ResourceGrid from traffic_generator import generate_embb_traffic, generate_urllc_traffic from scheduler import proportional_fair_scheduler def run_simulation(n_slots=1000, n_rbs=50): grid = ResourceGrid(n_slots, n_rbs) grid.reserve_slice('embb', 0, 30) grid.reserve_slice('urllc', 30, 40) grid.reserve_slice('mmtc', 40, 50) embb_arr, embb_sz = generate_embb_traffic(n_slots, 200, 1500) urllc_arr, urllc_sz = generate_urllc_traffic(n_slots, 1, 50) kpi = {'embb_throughput': [], 'urllc_latency': [], 'mmtc_loss': []} for slot in range(n_slots): # 收集本时隙到达的包 embb_pkts = [(t, s) for t, s in zip(embb_arr, embb_sz) if int(t) == slot] urllc_pkts = [(t, s) for t, s in zip(urllc_arr, urllc_sz) if int(t) == slot] # 调度与资源分配(简化:按切片顺序分配) # ... 省略具体分配逻辑 ... # 采集 KPI kpi['embb_throughput'].append(sum(s for _, s in embb_pkts) / 1e6) kpi['urllc_latency'].append(len(urllc_pkts) * 0.5) # 简化时延模型 return kpi这段代码里n_slots=1000对应 1 秒的仿真时长(15kHz 下每时隙 1ms)。n_rbs=50是频域资源块数,对应 10MHz 带宽左右。reserve_slice的边界要保证不重叠,否则后面的切片会覆盖前面的。KPI 采集部分,eMBB 看吞吐,URLLC 看时延,mMTC 看丢包率,这三个指标不能混在一起看,必须分切片统计。
3.3 结果可视化:三条曲线说明切片隔离效果
跑完仿真后,用 matplotlib 画三张图:eMBB 吞吐随时间变化、URLLC 时延的累积分布(CDF)、mMTC 丢包率随设备数变化。URLLC 的 CDF 图最能说明问题:如果 99% 分位时延超过 1ms,说明资源预留不够或者调度优先级没设对。我一般会先画 CDF,再回头调reserve_slice的 RB 范围和调度器权重。
import matplotlib.pyplot as plt def plot_urllc_cdf(latencies): sorted_lat = np.sort(latencies) cdf = np.arange(1, len(sorted_lat) + 1) / len(sorted_lat) plt.plot(sorted_lat, cdf) plt.xlabel('Latency (ms)') plt.ylabel('CDF') plt.axvline(x=1.0, color='r', linestyle='--', label='1ms target') plt.legend() plt.show()axvline那条红线是 URLLC 的 1ms 目标线,如果 CDF 曲线在 0.99 处还没到红线左边,就得考虑增加 URLLC 的预留 RB 或者提高其调度优先级。
4. 避坑指南:切片仿真里最容易翻车的五个地方
4.1 现象:URLLC 时延突然飙到几十毫秒
原因:eMBB 流量突发时占用了 URLLC 的预留 RB,或者调度器没有严格优先级。解决:在reserve_slice里给 URLLC 留足 RB,并在调度器里加硬优先级判断,URLLC 包未调度完不调度 eMBB。
4.2 现象:mMTC 丢包率始终为 0,看起来太完美
原因:mMTC 的流量生成概率设得太低,或者设备数太少,根本没触发拥塞。解决:把burst_prob调到 0.05 以上,设备数设到 1000 以上,再看丢包率是否上升。
4.3 现象:仿真跑得特别慢,1000 个时隙要几分钟
原因:每个时隙都在用 Python 循环遍历所有包,复杂度是 O(n_slots × n_pkts)。解决:用 numpy 向量化,把包按到达时隙预分组,或者用 numba 加速关键循环。
4.4 现象:不同随机种子下 KPI 波动巨大
原因:仿真时长太短,统计样本不足。解决:把n_slots加到 10000 以上,或者跑 10 次不同种子取平均。
4.5 现象:eMBB 吞吐曲线周期性掉底
原因:URLLC 的周期到达与 eMBB 的调度周期发生了共振,导致某些时隙资源被完全抢占。解决:给 URLLC 和 eMBB 设置不同的调度周期,或者引入动态资源共享机制。
5. 进阶技巧:用半静态预留加动态共享提升资源利用率
静态预留的缺点是资源浪费,动态共享的缺点是隔离性差。折中方案是半静态预留:给每个切片一个保底 RB 数,剩余 RB 作为共享池,按优先级动态分配。实现上,在ResourceGrid里加一个shared_pool列表,调度时先满足保底,再从共享池里按权重分配。
class SemiStaticGrid(ResourceGrid): def __init__(self, n_slots, n_rbs, shared_ratio=0.2): super().__init__(n_slots, n_rbs) n_shared = int(n_rbs * shared_ratio) self.shared_pool = list(range(n_rbs - n_shared, n_rbs)) self.guaranteed = {sid: (start, end) for sid, (start, end) in self.slice_map.items()} def allocate_shared(self, slot_idx, slice_weights): """按权重分配共享RB""" total_w = sum(slice_weights.values()) alloc = {} for sid, w in slice_weights.items(): n = int(len(self.shared_pool) * w / total_w) alloc[sid] = self.shared_pool[:n] return allocshared_ratio=0.2表示 20% 的 RB 作为共享池,这个值可以根据业务动态调整:URLLC 负载高时降到 0.1,eMBB 突发多时升到 0.3。验证方法是对比静态预留和半静态预留下的资源利用率与 URLLC 时延 99% 分位,如果利用率提升超过 15% 而时延分位恶化不超过 10%,就说明折中方案有效。
我自己的习惯是每次改完参数先跑三组:纯静态、纯动态、半静态,用同一组随机种子,看三条 CDF 曲线的分离程度。分离越大,说明切片隔离越明显;如果三条线几乎重合,那说明调度器根本没起作用,得回去检查优先级逻辑。希望帮到你。
本文还有配套的精品资源,点击获取