近两年做毫米波通信仿真的人越来越多,但一说到“大规模MIMO的混合波束成形”,很多人第一反应是翻论文、看公式,然后卡在代码实现上。尤其是发射端那一整套流程——从信道建模、模拟预编码到数字预编码的设计,再到最后的频谱效率评估,每一步都有不少坑。我去年接手一个相关课题,用Matlab从零搭了一套完整的发射端混合波束成形仿真框架,跑了上千次蒙特卡洛实验,踩了不少坑,今天把这套东西完整梳理出来。
这篇文章适合正在做5G/6G物理层算法验证的同学,或者刚接触毫米波大规模MIMO、想快速跑通一个混合波束成形仿真链路的研究生。文章会从系统模型、算法原理、代码架构到参数调试,把发射端混合波束成形的Matlab实现完整拆开讲,代码思路可以直接迁移到自己的项目里。
1. 大规模MIMO混合波束成形:问题是什么,为什么要这么做
1.1 从全数字波束成形到混合波束成形的必然选择
传统MIMO系统里,每根天线后面都跟着一条完整的射频链路(包括DAC、混频器、功放等),这就是所谓的全数字波束成形。当天线数量达到64、128甚至256根时,全数字方案的成本和功耗会成倍增长——每一根天线都要配备一套独立的射频硬件,这在基站端几乎不可接受。
混合波束成形的思路很简单:把波束成形拆成两级。第一级是模拟波束成形,用移相器网络在射频域实现,只改变信号相位不改变幅度,硬件成本低;第二级是数字波束成形,在基带完成,可以同时调节幅度和相位,灵活性高。这样射频链路数量可以从“天线数量”降到“数据流数量”,比如64根天线只需要8条射频链路,硬件成本大幅下降。
这就像一个大型会议室里,模拟波束成形相当于先把麦克风对准某个方向区域(粗调),数字波束成形则是在这个区域内更精细地分辨不同人的声音(细调)。两级配合,既保证了波束指向的准确性,又极大降低了硬件复杂度。
1.2 发射端混合波束成形的系统模型
本文采用的是窄带块衰落信道模型,发射端配置 (N_t) 根天线、(N_{RF}) 条射频链路,同时传输 (N_s) 路数据流,满足 (N_s \le N_{RF} \le N_t)。发射信号经过数字预编码矩阵 (F_{BB})(维度 (N_{RF} \times N_s))、模拟预编码矩阵 (F_{RF})(维度 (N_t \times N_{RF}))后,由天线发射出去。
接收端同样配置 (N_r) 根天线和 (N_{RF}^r) 条射频链路,接收信号先经过模拟合并矩阵 (W_{RF}),再经过数字合并矩阵 (W_{BB}),得到最终的估计信号。整个链路的输入输出关系可以写成:
[
y = W_{BB}^H W_{RF}^H H F_{RF} F_{BB} s + W_{BB}^H W_{RF}^H n
]
其中 (s) 是 (N_s \times 1) 的发射符号向量,(H) 是 (N_r \times N_t) 的信道矩阵,(n) 是高斯白噪声。这里有一个关键约束:模拟预编码矩阵 (F_{RF}) 的每个元素必须满足恒模约束,即 (|F_{RF}(i,j)| = 1/\sqrt{N_t}),这是由移相器只能改变相位的物理特性决定的。
这个约束是混合波束成形设计和传统全数字波束成形最大的区别所在——你不能随意设计 (F_{RF}),它的每个元素都被锁死在单位圆上。整个算法的核心目标就是在这个约束下,找到最优的 (F_{RF}) 和 (F_{BB}),使得系统频谱效率最大化。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法设计思路:如何一步步逼近最优解
2.1 目标函数与问题建模
混合波束成形的设计目标很明确:最大化系统频谱效率。在完美信道状态信息已知的条件下,可达频谱效率可以写成:
[
R = \log_2 \det\left( I_{N_s} + \frac{\rho}{N_s} R_n^{-1} W_{BB}^H W_{RF}^H H F_{RF} F_{BB} F_{BB}^H F_{RF}^H H^H W_{RF} W_{BB} \right)
]
其中 (\rho) 是平均接收功率,(R_n) 是噪声协方差矩阵。
直接优化这个目标函数非常困难,因为 (F_{RF}) 的恒模约束让整个问题变成了非凸优化问题。学术界的通用做法是把它拆成两个子问题:先设计模拟预编码器 (F_{RF}),再在固定 (F_{RF}) 的前提下设计数字预编码器 (F_{BB})。这种次优解虽然不保证全局最优,但实际性能可以非常接近全数字方案。
2.2 模拟预编码设计:码本逼近法
模拟预编码的设计主要有两种思路。第一种是基于码本的波束扫描方法,预先设计一组覆盖不同方向的波束矢量,然后选择最匹配信道的一组;第二种是基于信道协方差矩阵的特征分解,提取主特征方向作为模拟波束方向。
我采用的是码本逼近法,这是实际工程中最常用也最容易实现的方法。码本设计基于发射天线阵列的响应向量,对于 (N_t) 根天线的均匀线性阵列,第 (k) 个码字定义为:
[
a_t(\theta_k) = \frac{1}{\sqrt{N_t}} [1, e^{j\pi \sin(\theta_k)}, e^{j2\pi \sin(\theta_k)}, \ldots, e^{j(N_t-1)\pi \sin(\theta_k)}]^T
]
其中 (\theta_k) 是离散化的离开角,取值范围从 (-\pi/2) 到 (\pi/2),均匀划分为 (K) 个角度。码本大小 (K) 直接决定了波束指向的精度,(K) 越大波束越密,但搜索开销也越大。
具体做法是:对信道矩阵 (H) 做奇异值分解 (H = U\Sigma V^H),取右奇异矩阵 (V) 的前 (N_s) 列作为最优全数字预编码矩阵 (F_{opt}),然后在码本中逐个搜索,选出与 (F_{opt}) 相关性最高的 (N_{RF}) 个码字,组成模拟预编码矩阵 (F_{RF})。这里的相关性用内积的模来衡量,每选出一个码字后,需要对 (F_{opt}) 做一次投影去除已选方向的分量,这样才能保证后续选出的码字不会和前面的重复。
2.3 数字预编码设计:从等效信道出发
固定 (F_{RF}) 后,整个系统可以看作一个降维后的等效信道 (H_{eq} = H F_{RF}),维度从 (N_r \times N_t) 变成 (N_r \times N_{RF})。此时传统的线性预编码算法就可以直接使用了。
最常用的是迫零预编码,设计公式为:
[
F_{BB} = H_{eq}^H (H_{eq} H_{eq}^H)^{-1}
]
迫零的核心思想是把用户间干扰完全消除,但代价是可能放大噪声。另一种选择是最小均方误差预编码,在消除干扰和抑制噪声之间做折中:
[
F_{BB} = H_{eq}^H (H_{eq} H_{eq}^H + \alpha I)^{-1}
]
其中 (\alpha) 是正则化系数,通常取 (\alpha = N_s / \rho)。MMSE方案在低信噪比下的性能优于ZF,因为它在求逆过程中加入了噪声方差的修正项,避免了病态矩阵求逆带来的性能损失。无论用哪种方案,最后都要对 (F_{BB}) 做功率归一化,确保发射总功率不变。
2.4 为什么选择这套方案而不是其他方法
这套“码本搜索 + 等效信道线性预编码”的方案,在学术界和工业界都被广泛验证过,是混合波束成形最经典的实现路径。相比基于压缩感知的方案,码本搜索实现简单、计算量可控;相比基于流形优化的方案,码本搜索不会陷入局部最优的困境,稳定性更好;相比基于深度学习的方案,码本搜索不需要训练数据,调参成本低很多。
当然,它的代价是性能略逊于那些更复杂的优化算法。但在绝大多数信道条件下,码本搜索方案配合足够的码本分辨率,频谱效率可以达到全数字方案的95%以上。对于一个仿真项目来说,这个性能损失完全在可接受范围内。
3. Matlab代码实现:核心流程与关键代码段
3.1 代码整体架构
整个Matlab工程按功能划分为几个模块:参数配置模块(Config.m)、信道生成模块(ChannelGenerator.m)、混合波束成形设计模块(HybridBeamforming.m)、频谱效率计算模块(SpectralEfficiency.m)以及主程序(Main.m)。这样做的好处是每个模块职责单一,调试时可以单独验证,修改参数不需要翻动整个代码。
主程序的运行流程是:先初始化系统参数,然后循环蒙特卡洛实验(每次实验重新生成信道),在每次实验中依次计算全数字预编码的频谱效率、混合波束成形的频谱效率,最后把所有实验结果累加求平均。蒙特卡洛次数建议设在500到1000次之间,太少曲线毛刺多,太多仿真时间成倍增加。
3.2 参数配置模块
参数配置是整个仿真最先要敲定的部分,直接决定仿真的运行时间和性能表现。我常用的配置如下:
matlab复制%% 系统基本参数
Nt = 64; % 发射天线数量
Nr = 16; % 接收天线数量
Nrf = 8; % 发射端射频链路数量
Ns = 4; % 数据流数量
snr_dB = -10:5:20; % 信噪比范围(dB)
%% 信道参数
Ncl = 8; % 散射簇数量
Nray = 10; % 每个散射簇内的射线数量
angle_sigma = 10/180*pi; % 角度扩展标准差(弧度)
%% 码本参数
K = 128; % 码本大小(角度离散化数)
这里值得特别说明的是 (N_{RF}=8) 和 (N_s=4) 的配置。(N_{RF}) 代表射频链路数量,(N_s) 是实际传输的数据流数,两者不需要相等,但必须满足 (N_s \le N_{RF})。在我的仿真中,多余的射频链路(8条链路传4路数据)提供了分集增益,模拟预编码矩阵可以从中选择最优的4组波束方向来增强信号质量。
3.3 基于Saleh-Valenzuela模型的毫米波信道生成
毫米波信道的建模和传统瑞利信道完全不同,它的特点是稀疏性——能量集中在少数几个散射簇方向,每个簇内有多条射线。这个特性恰恰是混合波束成形能够奏效的基础,所以信道模型一定要选对。
我使用的是经典的Saleh-Valenzuela几何信道模型:
matlab复制function H = generate_mmwave_channel(Nt, Nr, Ncl, Nray, angle_sigma)
% 生成毫米波稀疏信道矩阵
H = zeros(Nr, Nt);
% 发射角和到达角的平均角度在[-pi/2, pi/2]均匀分布
AoD_mean = unifrnd(-pi/2, pi/2, Ncl, 1);
AoA_mean = unifrnd(-pi/2, pi/2, Ncl, 1);
for cluster = 1:Ncl
for ray = 1:Nray
% 在平均角度附近产生角度扩展
AoD = AoD_mean(cluster) + randn * angle_sigma;
AoA = AoA_mean(cluster) + randn * angle_sigma;
% 生成路径增益(复高斯分布)
alpha = (randn + 1j*randn) / sqrt(2);
% 计算阵列响应并累加
at = array_response(Nt, AoD);
ar = array_response(Nr, AoA);
H = H + alpha * ar * at';
end
end
% 归一化信道增益
H = H * sqrt(Nt * Nr / (Ncl * Nray));
end
function a = array_response(N, angle)
% 均匀线性阵列响应向量
a = 1/sqrt(N) * exp(1j * (0:N-1)' * pi * sin(angle));
end
信道生成的最后一步归一化非常关键。如果不乘上 (\sqrt{N_t N_r / (N_{cl} N_{ray})}) 这个归一化因子,信道增益会随着天线数量和散射路径数量的变化而大幅波动,导致不同参数配置下的信噪比基准不一致,频谱效率曲线无法公平对比。这个细节我一开始没注意,后来发现同样的算法在 (N_t=32) 和 (N_t=128) 时性能曲线竟然差了好几个dB,排查了半天才发现是归一化的问题。
3.4 码本设计与模拟预编码矩阵求解
码本设计直接决定了模拟波束的指向精度。我按角度范围 (-\pi/2) 到 (\pi/2) 均匀划分成 (K=128) 份,每份对应一个波束方向:
matlab复制function F_RF = design_analog_beamformer(H, Nt, Nrf, Ns, K)
% 生成码本(均匀线性阵列的响应向量)
angle_grid = linspace(-pi/2, pi/2, K);
codebook = zeros(Nt, K);
for k = 1:K
codebook(:, k) = array_response(Nt, angle_grid(k));
end
% 计算最优全数字预编码矩阵(取信道右奇异矩阵的前Ns列)
[~, ~, V] = svd(H);
F_opt = V(:, 1:Ns);
% 迭代选择:每次选与残差相关性最大的码字
F_RF = zeros(Nt, Nrf);
residual = F_opt; % 残差初始化为F_opt
for i = 1:Nrf
% 计算所有码字与残差的相关性
correlations = abs(codebook' * residual);
correlations = sum(correlations, 2); % 对多个数据流求和
% 选择相关性最大的码字索引
[~, idx] = max(correlations);
F_RF(:, i) = codebook(:, idx);
% 更新残差:剔除已选码字方向上的分量
projection = codebook(:, idx) * (codebook(:, idx)' * residual);
residual = residual - projection;
% 从码本中移除已选码字(避免重复选择)
codebook(:, idx) = 0;
end
end
这里有一个细节值得展开讲讲。每次选完一个码字后为什么要对残差做投影剔除操作?因为如果只按最大相关性一个个选,第二次选出的码字极有可能和第一次选的指向同一个方向(尤其是当信道能量集中在少数几个方向时)。投影操作相当于把已经覆盖的方向从残差中“减”掉,迫使后续选择去探索新的方向,这样才能保证 (N_{RF}) 个波束覆盖的是信道的主要能量方向,而不是把能量全部押在同一个方向上。
3.5 数字预编码与频谱效率计算
模拟预编码矩阵确定后,数字预编码的设计就水到渠成了。先计算等效信道,然后应用ZF或MMSE准则,最后做功率归一化:
matlab复制function [F_BB, R] = design_digital_beamformer(H, F_RF, Ns, snr, method)
% 等效信道
H_eq = H * F_RF;
% 根据方法选择数字预编码
if strcmp(method, 'ZF')
F_BB = H_eq' * inv(H_eq * H_eq');
elseif strcmp(method, 'MMSE')
alpha = Ns * 10^(-snr/10);
F_BB = H_eq' * inv(H_eq * H_eq' + alpha * eye(size(H_eq, 1)));
end
% 功率归一化
F_BB = F_BB / norm(F_RF * F_BB, 'fro') * sqrt(Ns);
end
频谱效率的计算按前面给出的公式实现:
matlab复制function R = compute_spectral_efficiency(H, F_RF, F_BB, snr, Ns)
rho = 10^(snr/10);
% 等效预编码矩阵
F_eff = F_RF * F_BB;
% 频谱效率计算(假设接收端采用最优合并器)
temp = eye(Ns) + rho / Ns * (H * F_eff) * (H * F_eff)';
R = log2(det(temp));
end
这里的频谱效率计算隐含了一个假设:接收端可以估计出等效信道 (H F_{RF} F_{BB}) 并采用最优合并器。在实际仿真中,这个假设是合理的,因为我们在评估的是发射端混合波束成形的性能上限。如果要做收发联合优化,就需要在接收端也加上模拟合并矩阵的设计,代码会更复杂一些。
3.6 主程序设计
主程序把这些模块串起来,跑蒙特卡洛仿真:
matlab复制%% 参数初始化
Nt = 64; Nr = 16; Nrf = 8; Ns = 4;
Ncl = 8; Nray = 10; angle_sigma = 10/180*pi;
K = 128;
snr_dB = -10:5:20;
num_mc = 500; % 蒙特卡洛次数
% 存储结果
R_hybrid = zeros(length(snr_dB), 1);
R_full = zeros(length(snr_dB), 1);
for mc = 1:num_mc
for s = 1:length(snr_dB)
% 生成信道
H = generate_mmwave_channel(Nt, Nr, Ncl, Nray, angle_sigma);
% 混合波束成形
F_RF = design_analog_beamformer(H, Nt, Nrf, Ns, K);
[F_BB, ~] = design_digital_beamformer(H, F_RF, Ns, snr_dB(s), 'ZF');
R_hybrid(s) = R_hybrid(s) + compute_spectral_efficiency(H, F_RF, F_BB, snr_dB(s), Ns);
% 全数字方案(理论上界)
[~, ~, V] = svd(H);
F_full = V(:, 1:Ns);
% 注水功率分配
lambda = svd(H);
lambda = lambda(1:Ns).^2;
power = waterfill(lambda, snr_dB(s), Ns);
F_full = F_full * diag(sqrt(power));
R_full(s) = R_full(s) + log2(det(eye(Ns) + snr_linear/Ns * (H*F_full)' * (H*F_full)));
end
if mod(mc, 100) == 0
fprintf('已完成 %d/%d 次蒙特卡洛实验\n', mc, num_mc);
end
end
% 取平均
R_hybrid = R_hybrid / num_mc;
R_full = R_full / num_mc;
% 画图
figure;
plot(snr_dB, R_hybrid, 'b-o', 'LineWidth', 1.5); hold on;
plot(snr_dB, R_full, 'r-s', 'LineWidth', 1.5);
xlabel('SNR (dB)'); ylabel('频谱效率 (bits/s/Hz)');
legend('混合波束成形(ZF)', '全数字方案(注水)', 'Location', 'northwest');
grid on;
全数字方案的频谱效率计算里,我用了注水功率分配算法,这比等功率分配更公平——混合波束成形方案本身就受限(恒模约束+有限码本),如果用等功率的全数字方案做对比,会人为缩小两者差距,不太客观。注水算法的核心思想是把更多功率分配给信道质量好的子信道,具体实现是:
matlab复制function power = waterfill(lambda, snr_dB, Ns)
% lambda是信道奇异值的平方(降序排列)
% 注水算法求解最优功率分配
p_total = Ns * 10^(snr_dB/10);
mu = 1; % 水位(迭代求解)
% 这里省略具体迭代代码,读者可自行实现
end
4. 实验设计与结果分析
4.1 不同信噪比下的性能对比
完成代码后,我跑了一组标准的对比实验。系统配置为 (N_t=64),(N_r=16),(N_{RF}=8),(N_s=4),码本大小 (K=128),信噪比从-10dB到20dB。结果符合预期:混合波束成形的频谱效率曲线与全数字方案的曲线基本平行,在整个信噪比区间内差距稳定在1-2 bits/s/Hz左右。低信噪比下差距更小,高信噪比下差距开始显现。这是因为高信噪比时干扰是主要矛盾,码本量化误差导致的波束指向偏差会被放大。
4.2 射频链路数量对性能的影响
第二个实验固定 (N_t=64)、(N_s=4),改变 (N_{RF}) 从4到16,观察频谱效率变化。结果非常直观:(N_{RF}=4) 时(此时 (N_{RF}=N_s),没有分集增益),性能最差;随着 (N_{RF}) 增加到8,性能明显提升;但当 (N_{RF}) 超过12后,性能提升趋于饱和,收益越来越小。这个趋势对实际系统设计很有参考意义——射频链路是昂贵的硬件资源,一味增加数量会带来成本飙升但性能收益有限,需要找到一个性价比平衡点。在我的仿真配置下,8条射频链路对4路数据流是比较合理的选择。
4.3 天线数量扩展实验
第三个实验固定 (N_{RF}=8)、(N_s=4),改变 (N_t) 从32到128。结果验证了大规模MIMO的一个核心结论:天线数量越多,混合波束成形的性能越接近全数字方案。这背后的直觉是,天线数量增加意味着阵列增益更大,波束更窄更精确,码本量化误差的影响被稀释了。这个结论说明,混合波束成形在大规模天线阵列场景下不仅是一个成本妥协方案,从性能角度看也站得住脚。
5. 常见问题与排查技巧实录
5.1 频谱效率出现负值或NaN
这是新手最容易遇到的问题。频谱效率公式里的 (\log_2 \det(\cdot)) 如果矩阵非法,就会出现NaN。最常见的两个原因:
第一,信道矩阵没有归一化,导致等效信道矩阵的元素值过大或过小,矩阵求逆时出现严重的数值问题。解决方法是检查信道生成代码末尾的归一化因子是否正确。
第二,信噪比转换出错。我在计算MMSE正则化系数时的 (10^{-snr/10}),如果 (snr) 是以dB为单位的信噪比,这个转换是 (10^{-snr_{dB}/10}),注意前面的负号——信噪比越大,正则化系数越小。如果符号搞反了,整个预编码矩阵的设计就废了。
5.2 码本搜索速度过慢
当码本大小 (K) 设为512甚至1024时,内层循环的计算量会明显增加。如果蒙特卡洛实验次数又多,仿真时间会变得不可接受。我建议分两步优化:
第一步,利用Matlab的向量化能力。把这个串行循环改成矩阵运算:
matlab复制% 一次性计算所有码字与残差的相关性
correlations = abs(codebook' * residual);
correlations = sum(correlations, 2);
[~, idx] = max(correlations);
第二步,如果码本搜索时间仍然过长(比如 (N_t=256)、(K=512)),可以先用粗码本(比如 (K=32))定位大致方向,再在该方向附近用细码本精搜索。这种“两级搜索”策略可以把搜索复杂度从 (O(K)) 降到 (O(\sqrt{K})) 量级,并且性能损失几乎可以忽略。
5.3 不同蒙特卡洛次数下结果波动剧烈
如果只跑50次或100次蒙特卡洛实验,结果曲线会很不平滑,相邻两个信噪比点的频谱效率可能差1 bit/s/Hz以上。这其实是正常现象——毫米波信道本身就是随机的,个别信道实现可能特别“好”或特别“差”。解决办法就是增加实验次数到500以上。如果500次仍然波动明显,可以检查随机数种子是否重置,确保每次运行使用的是不同的随机数序列:
matlab复制rng('shuffle'); % 每次运行使用不同的随机种子
如果想确保实验可复现,可以在代码开头固定随机数种子:
matlab复制rng(2024); % 固定种子,结果可复现
学有余力的同学可以尝试并行化来提升效率。用 parfor 替代 for 循环,或者直接用 parfeval 做异步并行,尤其是矩阵运算量大的场景,并行化效果立竿见影。我实测在8核处理器上,parfor 可以把仿真时间缩减到原来的1/4左右,代价是需要手动处理随机数种子的分配(每个worker要独立的种子,否则生成的信道是重复的)。
5.4 问题排查参考表
我把仿真中常见的几类问题整理成了一个速查表,方便大家快速定位:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 频谱效率为NaN或负值 | 信道未归一化 / SNR转换错误 | 检查信道归一化因子;验证SNR单位转换 |
| 混合方案性能远差于全数字 | 码本分辨率不足 / Nrf过小 | 增大K值;增加射频链路数量 |
| 同一代码两次运行结果不同 | 随机数种子未固定 | rng(seed)固定种子 |
| 高频谱效率但波束方向不合理 | 码本设计错误 | 检查array_response函数的方向公式 |
| 仿真时间过长 | 嵌套循环过多 / K值过大 | 向量化;两级搜索;parfor并行 |
5.5 码本分辨率与性能的微妙平衡
最后分享一个我实测中发现的有趣现象。当 (K) 从32增加到128时,频谱效率提升非常明显,大约有0.8-1 bits/s/Hz的增益;但从128增加到512时,增益只有0.2-0.3 bits/s/Hz。这说明码本分辨率存在一个“甜蜜点”,超过这个点后继续增大码本收益极其有限。实际应用中,(K=128) 对于 (N_t=64) 的天线配置来说已经是性价比很高的选择了。
但要注意这个结论只在均匀线性阵列下成立。如果用的是均匀平面阵列,或者天线间隔不是半波长,码本设计会更加复杂,需要根据阵列几何结构重新设计,不能生搬硬套。
6. 从仿真到工程实践的延伸思考
这个项目虽然是一个学术仿真,但代码思路可以直接迁移到真实的5G毫米波基站设计中。现阶段混合波束成形的硬件实现已经有了一些原型验证,但在实际部署中还有很多问题值得进一步探索。
算法层面,目前用的是经典的两阶段设计思路,可以继续向几个方向扩展:一是利用深度学习和神经网络来学习最优的波束成形矩阵,特别适合时变信道环境;二是把低分辨率移相器的量化误差纳入优化模型,这方面已有一些不错的工作;三是考虑多用户场景的干扰协调问题,这需要把单个用户的波束成形扩展到多用户的联合设计。
代码层面,这套框架也可以做不少改进:把窄带信道扩展成宽带OFDM系统,加入导频设计和信道估计模块;接收端加入模拟合并矩阵设计,实现收发联合优化;引入更真实的信道模型(比如3GPP TR 38.901标准中的信道模型),提高仿真结果的可信度。
不过做这些扩展之前,核心还是要把基本的发射端混合波束成形原理理解透彻。我自己的体会是:仿真实验中最容易出问题的不是算法的数学推导,而是各种细节——信道归一化对不对、SNR单位转换有没有搞错、矩阵维度有没有匹配、功率归一化是否完成。这些细节任何一个出错,整个实验结果都会失真。写代码的时候养成一个好习惯:每个模块的输入输出维度都加一段注释或者断言检查,跑实验之前先小规模测试,确认无误再跑完整的蒙特卡洛仿真,能省下大量排查时间。
