☰
D2D通信模式选择原理与MATLAB仿真实践指南
2026/10/21 3:20:50 网站建设 项目流程

1. D2D模式选择到底在选什么

1.1 三种模式与系统模型

做通信方向的同学,大概率绕不开一个词——D2D通信,也就是Device-to-Device,终端直通。简单说,你手里的手机不发到基站,而是直接发给旁边另一台手机,这就是D2D。模式选择,是D2D方向里最经典、也最容易出成果的切入点之一,而MATLAB则是做这类系统级仿真最顺手的工具,没有之一。

为什么需要模式选择?因为D2D用户并不是永远都适合直通。两台设备离得近,直通当然划算,能把数据从基站那绕开的路径缩短一大截,时延低、链路质量好,基站负载也轻。但如果两台设备隔着半个小区,直通链路的信号衰减得厉害,这时候老老实实走蜂窝模式反而更稳。所以模式选择干的事就一句话:根据当前信道状态和干扰环境,给每个D2D用户对决定用哪种通信模式。

我习惯把模式归纳成三种:蜂窝模式(也就是走基站中转)、专用D2D模式(用专门的频谱资源直通)、复用D2D模式(复用蜂窝用户的同频资源直通)。第三种模式还能细分复用上行还是下行,通常复用上行是最常见的,因为基站是集中式接收端,调度和干扰控制相对好做,而且蜂窝上行频谱利用率往往不高,给D2D用的空间大。

做仿真之前,先把系统模型搭清楚。我建议用单小区场景起步,基站放在中心,小区半径按典型城区宏站设成250米到500米之间。蜂窝用户随机撒在小区里,D2D用户对随机撒在小区里且每对之间距离不超过某个值,比如30米或50米。模型里需要考虑四条链路:基站到蜂窝用户的下行链路、蜂窝用户到基站的上行链路、D2D发射端到D2D接收端的直通链路、以及跨链路干扰——复用模式下,蜂窝用户会干扰D2D接收端,D2D发射端也会干扰基站接收。搞清楚这四条链路的关系,整个仿真的物理基础就立住了。

实际动手前我想多说一句:模式选择不是单纯的阈值判断,它的本质是资源分配策略。你让多少D2D对进入复用模式,就会给蜂窝链路引入多少干扰;你让多少D2D对进入专用模式,就要占用多少专用频谱;全推到蜂窝模式,D2D带来的增益又归零。所以仿真的目标函数和约束条件,比模式判断本身更重要。

1.2 判决准则的设计思路

模式选择的判决逻辑,常见的做法有三类。第一类是距离准则,最简单——D2D对之间的几何距离小于某个门限,就允许直通。二是SINR门限准则——D2D接收端算一下自己实际收到的信号噪声干扰比,大于等于某个门限就切到D2D模式。三是最大化效用准则——分别算蜂窝模式和D2D模式的吞吐量或频谱效率,谁高选谁。

三种准则不是互斥的,实际仿真里经常组合用。我做这套仿真的时候,主体逻辑是“先距离初筛,再SINR精判”。距离初筛把明显不适合直通的远距离对排除掉,节省计算量,也符合实际部署策略——网络侧不可能对所有远端做高精度信道估计。SINR精判则负责真实链路质量校验:就算距离近,如果附近恰好有一个发射功率很大的蜂窝用户,D2D接收端受干扰很强,也应该回退到蜂窝模式。

这里有个仿真新手常犯的认知误区:SINR门限定成一个全局固定值,这其实不太合理。不同D2D对的业务需求、目标QoS都不同,门限应该跟着业务走。比如语音业务门限低一点没关系,视频业务门限就得调高。所以仿真参数表里,我特意把SINR门限做成一个可扫描的向量,方便后面看趋势,而不是锁死一个数。

准则设计完之后,还有一个绕不开的问题:判决周期。模式选择应该隔多久做一次?实时做信令开销太大,隔太久又跟不上信道变化。典型的做法是慢速判决,在几百毫秒到数秒的粒度上做模式切换,仿真里用快照(Snapshot)来模拟这一点。

2. 仿真框架设计与MATLAB代码骨架

2.1 模块划分与数据流

这套仿真我从一开始就定了四个模块:系统初始化模块、信道生成模块、模式选择模块、性能统计模块。

系统初始化模块负责定义所有公共参数,包括小区拓扑参数、用户发射功率、噪声系数、带宽、路径损耗模型系数。信道生成模块负责给每条链路算大尺度衰落和小尺度衰落。模式选择模块读入信道矩阵和干扰矩阵,输出每个D2D对的模式决策。性能统计模块算吞吐量、中断概率、频谱效率这些指标。

模块间的数据流是这样的:初始化模块输出参数结构体,信道生成模块读入参数,输出所有链路的信道增益矩阵。模式选择模块读入信道增益矩阵,结合发射功率算SINR,输出模式标签向量。统计模块读模式标签和SINR计算结果,汇总成性能指标。这个数据流跑通之后,后面换信道模型、换判决准则都很方便,不用大改代码。很多同学写仿真喜欢从头到尾一个脚本梭哈,参数一多就乱套。我自己也是踩了几次改参数的坑之后,才下定决心把模块划分清楚。

2.2 核心代码:系统初始化与信道生成

初始化模块先定义参数结构体,我贴一段我实战用过的配置,参数取值都是以典型LTE系统为基础的参考值,换场景时扫一眼就知道改哪些地方。

%% 系统参数初始化 clear; clc; close all; % 拓扑参数 para.cellRadius = 250; % 小区半径(m) para.numCU = 20; % 蜂窝用户数 para.numD2D = 10; % D2D对数量 para.dD2DMax = 50; % D2D对最大通信距离(m) % 功率参数 para.Pc = 23; % 蜂窝用户发射功率(dBm) para.Pd = 20; % D2D发射端发射功率(dBm) para.Pbs = 46; % 基站发射功率(dBm) % 噪声与带宽 para.N0dBm = -174 + 10*log10(180e3); % 单RB噪声功率(dBm),考虑了180kHz带宽 para.BW = 180e3; % 子信道带宽(Hz) % 信道模型参数 para.pathLossFactor = 37.6; % 路径损耗指数 para.shadowStd = 8; % 阴影衰落标准差(dB) para.alpha = 3.68; % D2D近场路径损耗指数

噪声功率那行是仿真的细节关键。很多人直接用-174dBm/Hz的噪声谱密度,忘了乘带宽,算出来的SINR和吞吐量全部偏大,结果图漂亮得不真实,投稿或答辩时经不起细问。我一般先取-174dBm/Hz,换算成单个资源块180kHz下的噪声功率,算出来大约是-121.4dBm,再把接收机噪声系数加上去,比如加7dB,最终落到-114.4dBm左右。这个细节直接决定你仿真结论的可信度,务必注意。

信道生成模块,我按经验把链路分成两类:蜂窝链路和D2D链路。蜂窝链路距离长,用宏小区路径损耗模型;D2D链路距离短,用自由空间为主、额外计入阴影衰落。代码可以这么写:

%% 信道生成函数 function H = generateChannel(para, d_LOS, shadowEn) % d_LOS: 链路距离向量(m) % shadowEn: 阴影衰落向量(dB) % 返回线性功率域信道增益 PL_dB = 128.1 + 37.6*log10(d_LOS/1000); % 宏小区城区模型 H = 10.^(-(PL_dB + shadowEn)/10); end

D2D链路因为距离短,我会稍微降低路径损耗指数,模拟近场传播环境更好、绕射更少的特点。这组参数做到“看起来合理”很容易,但要“经得起推敲”就得在论文里写清楚模型选择依据。我的体会是,参数不要随手编,至少对着参考模型校准一次。

2.3 核心代码:模式选择与SINR计算

模式选择模块是整个仿真的心脏,它做的事是:把当前所有用户的位置、信道增益、发射功率拿来,逐个候选项算SINR,然后做判决。

SINR的计算要分链路。蜂窝用户上行到基站这条链路,基站侧收到的信号来自蜂窝用户,干扰则来自正在复用同一块频谱的所有D2D发射端。D2D链路的接收端,收到的信号来自配对D2D发射端,干扰则来自复用同一块频谱的蜂窝用户以及其他D2D对。这段干扰关系如果没理清楚,后面的结果全是乱的。我贴一下模式选择和SINR计算的核心代码:

%% 模式选择:距离初筛 + SINR精判 modeFlag = zeros(1, para.numD2D); % 0=蜂窝模式, 1=D2D模式 for k = 1:para.numD2D % 距离初筛 d_d2d = norm(d2dPos(2*k-1,:) - d2dPos(2*k,:)); if d_d2d > dTh modeFlag(k) = 0; continue; end % 干扰计算(复用上行场景) I_d2d = 0; for m = 1:para.numCU I_d2d = I_d2d + Pc * H_d2d_to_cu(m,k); end sinr_d2d = Pd * H_d2d_link(k) / (I_d2d + N0); if sinr_d2d >= gammaTh modeFlag(k) = 1; else modeFlag(k) = 0; end end

注意到这段代码里,干扰项累加用的是线性功率域,而信道增益H是线性值。很多同学在干扰计算那一步把dB和线性搞混,导致干扰算出来不是大几个数量级就是小几个数量级。我的建议是:整个仿真里只有两个地方允许出现dB——参数输入和结果画图,中间运算全部用线性值。这是我在反复修改代码之后立下的规矩。

吞吐量统计就简单了,用香农公式:

%% 吞吐量计算 rateD2D = BW * log2(1 + sinr_d2d); % bps

做的事情不多,但每一步都有坑。下面我会把参数配置和完整流程串一遍。

3. 参数配置与仿真流程

3.1 一组可以直接抄的基础参数表

完整参数是仿真的地基,我把一套能稳定跑出趋势、又贴近真实系统的参数列出来。这些参数的取值依据参考了典型蜂窝网络的公开配置,也兼顾了仿真收敛速度,适合第一版跑通用。

参数数值说明
载波频率2 GHz典型LTE频段
系统带宽10 MHz仿真按子信道调度
子信道带宽180 kHz一个资源块的带宽
小区半径250 m单基站三扇区小区中的单扇区近似
蜂窝用户数20单扇区典型负载
D2D对数量10可扫描变量
D2D最大距离10~80 m距离初筛门限
蜂窝用户发射功率23 dBm典型LTE终端的最大发射功率
D2D发射功率20 dBm略低于普通蜂窝终端,减少干扰
基站发射功率46 dBm宏站典型值
噪声系数7 dB接收端典型值
路径损耗指数37.6城区宏小区参考值
阴影衰落标准差8 dB对数正态分布

dD2DMax这里做个扫描,10米到80米,步长10米,每次蒙特卡洛跑1000个快照。之所以选快照式仿真而不是连续时域仿真,是因为模式选择本身就是慢速判决,信道在一个快照周期内认为不变,这个假设在低速场景下完全成立。快照式仿真在MATLAB里实现简单,运行效率也高,第一版先用它跑通,后续要加时间相关性再扩展。

仿真前必须明确一件事:随机种子。我习惯于在每个快照开始前用rng(seed)固定当前快照的随机数种子。如果完全不固定种子,两次仿真的平均吞吐量可能差3%~5%,看起来没多少,但画曲线时毛刺特别多,原因就是不同运行之间的随机性没对齐。固定种子之后,对比不同参数曲线时,除了被扫描参数以外所有随机因素完全一致,曲线平滑度立刻上一个档次。这个技巧很小,但是对结果图的美观度和可信度都是实质性的提升。

3.2 蒙特卡洛仿真完整流程

蒙特卡洛循环是整个仿真的骨架。我不会把整个循环体都写在脚本里,而是拆成三层:外层快照循环、中层用户遍历、内层资源复用计算。

外层快照循环,每个快照做一次拓扑生成和信道生成。拓扑生成要注意均匀撒点,蜂窝用户用sqrt(rand)*cellRadius控制径向分布,这样弧形面积和随机数概率密度是对应的,用户在小区的分布才是均匀的。直接rand*cellRadius会让用户集中在圆心附近,这是仿真新手几乎必踩的坑。D2D对生成时,每对的距离要限制在dD2DMax范围内,可以这么实现:先随机生成一个方向角,再在[0, dD2DMax]里取随机距离,两个端点落在圆内即可。

中层用户遍历,是对所有D2D对逐个做模式判决。前面模式选择模块的代码已经展示了这部分逻辑。内层资源复用计算,我考虑到多个D2D对可能复用同一份频谱,这时候D2D对之间的共信道干扰也要算进去。

为了控制复杂度,第一版我安排每个D2D对随机独立分配一份频谱资源,不主动做频谱复用优化。这样干扰关系就只有“D2D对 vs 蜂窝用户”这一层,逻辑清晰,适合验证模式选择算法本身。等模式选择跑稳定了,再把“多个D2D对复用同一资源”的干扰处理加进去,一次只加一个变量,出问题也好定位。

%% 蒙特卡洛主循环框架 % 外层快照循环 Nsnap = 1000; % 快照数 snrAcc = zeros(1, Nsnap); % 每快照的平均D2D SINR for snap = 1:Nsnap rng(snap); % 固定快照随机种子 % 1. 生成用户位置 % 2. 生成信道增益矩阵 % 3. 预分配模式标签 % 4. 遍历D2D对,做模式选择 % 5. 统计本快照的吞吐量与中断数 end % 平均统计 avgSINR = mean(snrAcc);

循环跑完之后,统计所有快照的模式标签分布比例、平均SINR、平均吞吐量和中断概率,保存成向量,方便后面扫描参数时做对比。

4. 从仿真结果里真正能读到什么

4.1 基准场景分析与趋势判断

先跑一个基准场景:D2D对距离上限50米,SINR门限设为3dB,复用上行频谱。结果会有几个明显特征。第一,D2D对距离一旦超过某个临界值,模式选择算法几乎全部判到蜂窝模式;第二,D2D对的SINR出现一个明显的分层——处于复用模式的D2D对平均SINR可能就10dB出头,而蜂窝模式虽然更稳,但它占用基站资源,系统总吞吐量上不去;第三,随着D2D对数量增加,系统频谱效率先升后降,因为D2D对带来的新增频谱资源被它制造的干扰消耗掉了。

有个判断很直接:把整个系统总吞吐量画出来,和“全部用户走蜂窝模式”的基准曲线对比,两条线交叉的位置就是D2D的“盈亏平衡点”。在D2D对数量少时,D2D带来的增益完全来自复用蜂窝空闲频谱;但D2D对超过一定密度后,复用导致的干扰会让蜂窝用户吞吐量明显下降,总吞吐量反而跌破蜂窝基准。这个折中趋势是D2D领域非常经典的结论,仿真能把它复现出来,说明你的平台可信度很高。

模式比例的统计也值得仔细看。我扫过一组结果:在D2D最大距离20米时,约88%的D2D对能进入D2D模式;到80米时,这个比例降到50%以下。这个结论本身不稀奇,有趣的是中间曲线的形态——不是线性下降,而是在40到60米之间出现一个较陡的跌落段。原因在于距离不仅影响直通链路质量,还影响D2D发射端与基站之间的干扰距离,两者共同作用导致模式切换的概率密度在该区间集中释放。这个物理机制用一句话总结就是:模式选择收敛的临界区间,往往藏在几何距离和干扰距离的交汇处。

4.2 参数敏感性:SINR门限与发射功率的博弈

SINR门限是模式选择里最直接可控的参数。我把门限从0dB扫到10dB后发现一张很典型的曲线:门限越低,复用模式的D2D对越多,D2D总吞吐量越高,但蜂窝用户SINR下降得厉害;门限越高,D2D接入率下降,系统总吞吐量反而因蜂窝链路变稳而保持平稳。这个权衡不是简单单调的,最佳门限落在一个中间区域,大约3到5dB。

发射功率的敏感性也非常值得做一组实验。D2D发射功率每提高3dB,D2D链路吞吐量大约提升10%到15%,但当你把D2D发射功率设到和蜂窝用户相同时,蜂窝用户在中高负载下的SINR损失开始变得不可忽略。仿真到这一步,功率控制这个方向就自然浮现出来——不是让D2D对傻乎乎地全功率发射,而是每对根据目标SINR反向调节发射功率,能用最低功率满足门限才是最优策略。

这组敏感性分析做完,整个仿真的“故事线”就完整了:先是模式选择的判决逻辑,然后是D2D带来的系统增益,最后是干扰管控带来的优化空间。这套链路跑明白之后,论文或者项目报告的框架基本就立住了。

5. 常见问题与排查技巧实录

5.1 仿真结果离奇时的排查顺序

这套仿真我前前后后写了三版,每一版都遇到了些让人挠头的问题。第一类是吞吐量数值离谱。最典型的表现是曲线图上吞吐量达到几百Mbps甚至Gbps,这在180kHz带宽下不可能实现。排查顺序如下:先看带宽有没有乘错,再看到底用没用电平域归一化。如果你在用log2(1 + SINR)时SINR单位还是dB而不是线性倍率,算出来的吞吐量会大得离谱。这条规则我已经撞过两次墙,现在每换一个场景就直接在SINR后面加实时检查。

第二类表现是中断概率始终为零。D2D的SINR在高信道质量下当然不高,中断概率为零要么说明你的发射功率设得过高,要么说明SINR门限设得太低。我建议从极端参数开始排查——把D2D发射功率降10dB,如果结果图纹丝不动,说明信道增益或者噪声计算那块链路没接上。

第三类问题是结果曲线毛刺太多。前面提过,先检查随机种子有没有统一;再检查快照数是不是太少了。快照数低于300时,曲线波动可能超过10%,很多趋势根本看不出来。我一般把快照数定在1000以上,复杂场景5000也不嫌多,反正单快照计算量不大,循环跑得快。

5.2 代码提速与可复现性优化

MATLAB做蒙特卡洛仿真,性能瓶颈几乎都出在循环和信道重算上。我实测下来两个优化收益最大。一是预先分配所有大数组。在快照循环开始之前,H_d2d = zeros(numD2D, numCU)这类预分配一定要做。不做预分配的话,数组反复动态扩容,1000快照跑下来慢得离谱。二是向量化干扰求和。把内层用户遍历的干扰累加改成矩阵乘法,I = sum(Pc * H, 2)这种写法比for循环快好几倍。我第一版代码跑1000快照要40多秒,优化后8秒跑完,肉眼可见的差距。

可复现性方面,我养成了一个习惯:每次仿真运行前把当前所有随机数种子和参数结构体保存成.mat文件。这样即使后面算法改坏了,只要回滚到种子文件就能精确还原之前的图。很多同学用rng shuffle跑仿真,结果曲线复现不了,每次运行结果都不一样,审稿人或者导师要求复现时就很被动。

最后分享一个小工具:把扫描参数的循环封装成单独函数,用parfor做并行加速。要注意的是parfor里每个worker要独立设置随机种子,否则多个worker可能生成完全相同的随机序列,那结果就废了。用rng(seed + workerId * offset)的方式隔离每个worker的随机序列,实测下来并行加速能到4到6倍,1000快照的扫描任务能在一分钟内跑完。

还有一个很容易被忽略的问题:分布式随机数生成的一致性。如果每个快照里撒点的顺序变了,后面即使固定了种子,结果也和之前不同。所以我习惯用三层随机流——外层快照种子、中层用户位置种子、内层信道衰落种子,三层独立管理,这样改动任何模块都不会影响到其他模块的随机一致性。这招是我在多次对比试验中发现结果总差一点后琢磨出来的,现在已成为我碰任何大型仿真都保持的固定习惯。

5.3 一套避坑清单,照着做省一周时间

最后整理一个避坑清单,都是实测过的经验,照着检查能省大量返工时间。

检查项常见问题建议做法
用户撒点用rand直接乘半径,用户集中在中心用sqrt(rand)*cellRadius做均匀撒点
噪声功率忘记乘带宽或用错单位噪声功率=谱密度+10log10(带宽)+噪声系数
SINR单位用dB值直接代入香农公式全链路线性域计算,只在输入输出做dB换算
频谱分配所有D2D对复用同一资源,干扰爆炸先做正交分配,再加复用干扰
随机种子快照间不固定,曲线抖动大每快照固定种子,种子随快照索引递增
预分配大数组未预分配,运行慢所有矩阵进循环前预先zeros

这套避坑思路不光适用于D2D模式选择仿真,对任何基于MATLAB的无线通信系统级仿真都通用。我个人在做这套仿真时最大的体会是:仿真平台本身写起来并不难,真正花时间的全在细节排查上。你能把每个异常结果都解释清楚,这套代码才算真正属于你了。后续扩展的方向也很明确——加入功率控制、多用户调度、非正交资源分配,把模式选择和资源分配联合建模,这套平台都能直接接着用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询