ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

D2D信道仿真:从链路到系统的资源分配与干扰建模

D2D信道仿真:从链路到系统的资源分配与干扰建模

简介:面向无线通信方向的学习者与研究人员,这份 MATLAB 仿真资料聚焦 D2D 通信的信道建模与资源分配问题,适合已具备一定 MATLAB 基础、希望动手复现启发式算法求解频谱分配的中高级读者。资源包共 22 个文件,以 20 个 .m 脚本为主体,辅以 2 个 .asv 自动备份文件,压缩包约 16KB,体积轻量但结构完整。代码覆盖信道建模、路径损耗计算、用户与 D2D 对生成、干扰距离与干扰量统计、随机算法与启发式算法实现、最优方案求解及主流程调度等模块,可支撑从信道仿真到资源分配对比实验的完整链路。已有 1214 人学习下载,说明其在 D2D 仿真入门与课程设计场景中具有一定参考价值。读者可据此理解瑞利衰落、阴影衰落等信道条件下的性能评估思路,对比随机分配与启发式算法的吞吐量、干扰表现,并在此基础上改写参数、扩展算法或验证自己的资源分配策略。

1. D2D 信道仿真:为什么“链路能通”和“系统能跑”是两回事

很多人第一次做 D2D 信道仿真,都会掉进同一个坑:单条链路的误码率曲线画得漂漂亮亮,信噪比一拉高就乖乖往下掉,看起来一切正常;可一旦把几十对 D2D 用户塞进同一个小区,加上资源分配,系统吞吐不升反降,甚至比不用 D2D 还差。这不是代码写错了,而是链路级仿真和系统级仿真根本是两套东西。链路级关心的是“这一对收发之间,给定信道模型,误码率是多少”;系统级关心的是“多对用户共享频谱时,干扰怎么叠加、资源怎么分、谁该复用谁该退让”。D2D 信道仿真的价值,恰恰在于把这两层接起来:用 MATLAB 把路径损耗、阴影衰落、小尺度衰落的信道建模做扎实,再把资源分配策略放进去跑,才能看出复用增益到底被干扰吃掉了多少。搞懂这套机制,你才知道自己画的曲线为什么“好看但没用”。

2. 信道建模的底层逻辑:从大尺度到小尺度的叠加顺序

2.1 为什么必须先算路径损耗再叠衰落

D2D 信道不是单一模型,而是三层增益的乘积:大尺度路径损耗、阴影衰落、小尺度快衰落。常见的实现思路是先把距离相关的路径损耗算出来,再乘上对数正态分布的阴影项,最后叠上瑞利或莱斯分布的小尺度项。顺序不能乱,因为小尺度衰落的归一化功率是 1,它只改变瞬时幅度,不改变平均功率;如果你先叠衰落再算路径损耗,平均接收功率就会被错误缩放,后面算信干噪比时全盘偏移。

% 大尺度路径损耗:D2D 常用近距离模型,距离单位米 d = max(dist, 1); % 避免 log(0) PL_dB = 38.46 + 20*log10(d) + 18.4*log10(fc/1e9); % 视距近似 % 阴影衰落:对数正态,标准差 sigma_sf shadow_dB = sigma_sf * randn(size(d)); % 小尺度瑞利衰落:复高斯,功率归一化 h_small = (randn(size(d)) + 1j*randn(size(d))) / sqrt(2); % 总信道增益(线性) gain_linear = 10.^(-(PL_dB + shadow_dB)/10) .* abs(h_small).^2;

这段代码里fc是载频,sigma_sf一般取 4 到 8 dB,取决于场景。关键点在最后一行:路径损耗和阴影是 dB 域相加后转线性,小尺度衰落是线性域直接乘。很多人把h_small也转成 dB 再相加,结果功率对不上,误码率曲线整体平移几个 dB,排查半天以为是调制解调写错了。我一般会在这里加一句断言,检查mean(abs(h_small).^2)是否接近 1,作为仿真前的自检。

2.2 小尺度衰落为什么用瑞利而不是直接给个随机数

瑞利衰落的物理含义是“没有直射径、多径散射充分”的场景,D2D 在遮挡较多的环境下正好符合。它的复高斯实现之所以被广泛采用,是因为两个独立高斯变量的模服从瑞利分布,相位均匀分布,这跟多径叠加的统计特性一致。如果你图省事直接rand()一个幅度,分布是均匀的,深衰落出现的概率被严重低估,系统级仿真里干扰的尾部特性就失真了。莱斯衰落则用于存在直射径的情况,用K因子控制直射分量占比,K越大越接近高斯信道。D2D 近距离视距场景下,K取 3 到 10 dB 是常见做法。

2.3 阴影衰落的相关性为什么不能忽略

独立同分布的阴影假设在链路级没问题,但系统级仿真里,同一对 D2D 用户在不同资源块上的阴影是相关的,不同用户之间的阴影也可能相关。忽略相关性会让干扰的方差被高估,资源分配算法显得“过于保守”。常见的处理是给阴影项加一个空间相关矩阵,用 Cholesky 分解生成相关随机变量。这一步在 MATLAB 里就是chol加矩阵乘法,但很多人直接跳过,导致后面调度算法的性能对比失去意义。

3. 资源分配放进仿真:干扰怎么算、复用怎么判

3.1 信干噪比的完整计算链路

系统级仿真的核心是每个资源块上每个接收端的 SINR。D2D 复用蜂窝上行资源时,D2D 接收端受到两类干扰:复用同一资源块的蜂窝用户,以及其他复用同一块的 D2D 对。计算顺序是:先确定资源分配矩阵,再逐块累加干扰功率,最后算 SINR。

% alloc: N_user x N_rb 的 0/1 分配矩阵 % P_tx: 发射功率向量, gain: 信道增益矩阵 (tx, rx) SINR = zeros(N_user, N_rb); for rb = 1:N_rb active = find(alloc(:, rb)); for rx = active' signal = P_tx(rx) * gain(rx, rx); interference = 0; for tx = active' if tx ~= rx interference = interference + P_tx(tx) * gain(tx, rx); end end SINR(rx, rb) = signal / (interference + noise_power); end end

这里gain(tx, rx)是发射端tx到接收端rx的信道增益,注意索引方向别写反,否则干扰算成了有用信号。noise_power用kTB加噪声系数算,别直接拍一个常数。这段循环在用户数多时会慢,常见的优化是把干扰项写成矩阵乘法,但初版用循环更不容易出错,先跑通再优化。

3.2 复用判据:距离门限还是干扰门限

资源分配里最常见的复用判据是“D2D 对之间的距离大于某个门限才允许复用”,这个门限来自干扰容限的推导。但更严谨的做法是直接算干扰门限:如果 D2D 对复用某蜂窝用户资源后,蜂窝用户的 SINR 下降不超过某个阈值,才允许复用。距离门限是干扰门限的简化版,实现简单但保守。仿真里两种都值得跑一遍对比,你会看到距离门限在用户分布不均匀时明显吃亏。

3.3 调度算法为什么不能只看瞬时 SINR

比例公平调度在 D2D 场景下要同时考虑蜂窝用户和 D2D 用户的历史吞吐。只按瞬时 SINR 排序会让边缘用户饿死,系统总吞吐好看但公平性崩盘。常见的实现是维护每个用户的平均吞吐,用瞬时速率除以平均速率作为优先级。这个平均值的更新系数决定了“记忆长度”,系数太小调度抖动大,太大则响应慢。仿真里这个参数要跟资源分配周期匹配,否则对比不同算法时结论不可靠。

4. 仿真避坑:那些让曲线“看起来对但实际错”的细节

4.1 现象:误码率曲线在高信噪比处出现平台

原因通常是干扰被当成了噪声,或者小尺度衰落的样本数不够。瑞利衰落的深衰落需要足够多的独立样本才能统计出来,如果每个信噪比点只跑几百个符号,高信噪比处的误码率会被少数深衰落样本主导,曲线出现平台。解决方法是每个点至少跑 1e5 个符号,或者用解析的瑞利误码率公式做交叉验证。

4.2 现象:系统吞吐随 D2D 对数增加先升后降,但降得太早

原因多半是干扰计算里漏了 D2D 对之间的相互干扰,只算了蜂窝对 D2D 的干扰。D2D 对密集时,彼此之间的干扰才是主要矛盾。检查interference累加循环是否覆盖了所有同资源块的发射端,别只遍历蜂窝用户。

4.3 现象:不同随机种子下结论翻转

原因是样本数不足或阴影相关性没处理。系统级仿真的随机性来源多,单次蒙特卡洛的方差很大。常见做法是每个配置跑至少 50 次独立拓扑,取平均并给出置信区间。如果两次种子结果差很多,先加样本数,再检查阴影生成是否每次重新抽样。

4.4 现象:资源分配矩阵出现全零行或全零列

原因是分配算法的约束没写全,比如每个 D2D 对最多复用一个资源块,但代码里允许了一个对占多个块,导致其他用户无块可用。在分配后加一行检查all(sum(alloc, 2) > 0),不满足就报错,比事后看吞吐异常再回头找快得多。

5. 设计取舍:仿真精度和跑得动之间怎么选

信道仿真里最贵的不是公式,是样本数和循环层数。链路级要精度就得堆符号数,系统级要统计显著性就得堆拓扑数,两者乘起来很容易让一次仿真跑上几个小时。我的经验是分层验证:先用少量样本确认信道生成和 SINR 计算的逻辑正确,比如单用户单资源块的手算对比;再放大样本跑性能曲线。小尺度衰落用解析模型生成而不是逐个符号仿真,能省一个数量级的時間,代价是失去符号级定时细节,但对资源分配的性能对比影响很小。

另一个取舍是阴影相关性的建模复杂度。全相关矩阵最准但构造麻烦,简化为同一用户跨资源块相关、用户间独立,在多数对比场景下够用。关键是在报告结论时写清楚用了哪种假设,否则别人复现不出来,血泪经验就是曾经因为没写阴影假设,被追问到重新跑了一遍全部仿真。

取舍点高精度做法跑得动的做法适用场景
小尺度衰落符号级逐样本生成解析分布直接抽样资源分配对比
阴影相关性全相关矩阵用户内相关、用户间独立中等规模拓扑
蒙特卡洛次数200 次以上50 次加置信区间初步筛选算法

从那以后我每次搭 D2D 仿真,都强制先跑一个“单链路手算对比”的小脚本,确认路径损耗、阴影、衰落的叠加顺序和功率归一化没问题,再往上叠资源分配。这个习惯帮我省掉了无数次“曲线不对但不知道错在哪”的排查。希望帮到你。

本文还有配套的精品资源,点击获取

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进