ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SCMA系统中SD-MPA检测器:球译码剪枝降低多用户检测复杂度

SCMA系统中SD-MPA检测器:球译码剪枝降低多用户检测复杂度 简介面向无线通信与5G多址接入研究者这份MATLAB仿真资源聚焦稀疏码多址接入SCMA系统与软判决消息传递SD-MPA检测算法能够在瑞利衰落信道下完成多用户信号生成、稀疏编码、迭代检测与误码性能统计适合正在学习SCMA原理、需要可运行参考实现的通信专业学生或工程人员。压缩包共4个m文件仅4KB代码精简涵盖编码、检测、主仿真脚本与数值稳定函数编码模块将各用户数据映射为稀疏码字SD-MPA检测器采用概率消息循环迭代示例设置为6次分离多用户信号log-sum-exp函数用于避免概率计算中的数值溢出仿真主脚本则统一配置信道参数并输出结果。已有322人学习下载通过调节迭代次数或信道条件可以直观考察检测性能与复杂度的折中加深对非正交多址接入系统的理解。整体适合作为课程设计或科研入门的轻量级参考实现。1. 项目背景与思路拆解1.1 SCMA是什么为什么检测环节是硬骨头我入手这个的时候其实是想把非正交多址接入里最典型的一套收发链路跑通。SCMASparse Code Multiple Access稀疏码多址接入核心思路不复杂每个用户不是把调制符号直接压到子载波上而是先查一张高维码本把比特映射成稀疏复数码字多个用户在相同的时频资源上叠加依靠码本的稀疏结构在接收端区分开。它比传统正交多址好在过载能力强资源利用率高一度是 5G 空口候选方案里的热门选手。不过代价也明显接收端检测不再是各用户独立解调而是一个多用户联合检测问题。假设 J 个资源块上叠加了 K 个用户每个用户码本大小是 M朴素遍历所有向量组合的计算量是 M 的幂次这个幂就是因子图上资源节点的度数一般 3~4。如果 M4、度数3那一个资源块就要比选 4 的 3 次方也就是 64 种组合看着不算大但码本一扩、度数一涨指数爆炸立刻显现。所以业内普遍用消息传递算法MPA做近似最大后验检测利用稀疏因子图把联合检测拆成节点间消息迭代能压下来很多。但 MPA 本身的复杂度还是随着码本大小 M 和度数 df 指数涨想在低功耗、高吞吐场景里落地依然吃力。我这个项目干脆把球译码Sphere DecodingSD的思路塞到 MPA 里去做了一个 SD-MPA 检测器。通俗讲就是在 MPA 搜索码字组合的时候不再把所有候选都算一遍而是先圈一个“半径”只搜半径以内的候选超半径的直接剪掉。这样在实际信道条件下相当一部分不可能成为最优解的码字组合根本不会进入消息更新流程复杂度自然就下来了。标题里两个词其实已经把这套方案的核心写清楚了一个 SCMA 系统一个 SD-MPA 检测算法。下面我把从原理到仿真实现再到踩坑的经验完整展开给正在做 SCMA 多用户检测或者接触 MPA 类算法的人一个可直接参考的模板。1.2 系统模型和方案选型先交代项目里的标准配置。典型上行 SCMA 系统用户数 K6资源块数 J4每个资源块上叠加 df3 个用户过载率是 K/J150%。发端每个用户有一个 M4 的码本每个码字是一个长度为 J 的复向量但只有 df 个非零位置。稀疏性由因子图矩阵 F 决定F 的第 j 行第 k 列如果是 1说明用户 k 在资源块 j 上有非零发送。我用的因子图是规则稀疏矩阵每个用户占 3 个资源块每个资源块也承载 3 个用户这是 SCMA 最常用的设计之一。接收信号可以写成y_j sum_{k in xi_j} h_{k,j} x_{k,j} n_j其中 xi_j 是资源块 j 上活跃用户的集合h_{k,j} 是用户 k 到资源块 j 的信道系数x_{k,j} 是用户 k 码字在资源块 j 上的分量n_j 是高斯白噪声。检测目标就是从接收向量 y 和信道估计 H 中恢复所有用户的发送符号。选 SD-MPA 而不是传统 MPA核心动力是复杂度。传统 MPA 做迭代消息更新时每个资源节点需要穷举所有 dx 个用户码字组合每个组合都要算一次指数函数和乘积项复杂度是 O(M^df)。SD-MPA 的思路是把这 M^df 个候选看作一个离散搜索树利用已搜索部分路径的累积距离来剪枝。初始搜索半径给一个和噪声方差相关的值搜索过程中一旦发现部分距离已经超过半径就不再往这个分支继续展开。实测下来在典型信噪比区间SD-MPA 能剪掉 50% 以上的候选组合复杂度明显下降性能损失控制在零点几个 dB 以内属于典型的“用一点性能换一截复杂度”。这里要说明一点SD-MPA 和传统的球译码不完全一样。传统球译码在实数域复数域搜的是连续星座点而 SD-MPA 面对的是离散码本空间且要结合因子图上的迭代消息传递。所以它更像是一种带剪枝的序列搜索 MPA不是简单套球译码。我的实现里保留了 MPA 的消息传递框架只是在每个资源节点做穷举组合这一环换成了基于半径约束的部分搜索这样和原 MPA 的系统对接最省事迭代框架不用大改。2. 核心原理与关键算法解析2.1 SCMA编码与码本设计基础SCMA 发端最关键的部件就是码本。码本怎么设计直接影响检测性能和复杂度。最常见的设计方法是多维星座旋转加稀疏扩频先把 QPSK 或 QAM 符号经过一个多维旋转矩阵让各维之间产生相关性再把旋转后的星座点映射到稀疏矩阵的固定位置上。这样做的好处是不同用户落在同一资源块上的码字尽可能正交减轻多用户干扰。码本设计有一条经验规则每个资源块上的 df 个用户码字在任意两个不同码字组合下叠加后的距离谱要尽量均匀。距离谱均匀则检测的错误底限低MPA/SD-MPA 都能稳住。实际项目里不必从零设计码本直接用文献里的标准 SCMA 码本比如 4 点码本就行。但要注意归一化每个码字的平均能量得归一化到 1否则信噪比定义会乱。我一开始没归一化结果 BER 曲线整体右偏排查了好久才发现是能量偏大导致等效信噪比虚高。系统过载率是 SCMA 的核心指标过载率越高资源利用率越好但检测难度越大。J4、K6 的配置过载 150%在检测算法对比里算是一个不错的选择。若 K8、J4过载 200%SD-MPA 的优势会更明显因为传统 MPA 的 M^df 复杂度指数上涨更快而剪枝空间也更大。不过高过载时有一件事需要盯紧因子矩阵的行相关性。若两个用户在所有资源块上的稀疏模式完全相同接收端就完全无法区分他们这是设计时的大忌。2.2 SD-MPA中的球译码剪枝逻辑SD-MPA 的整个流程可以拆成四步。第一步初始化每个资源节点的消息通常设为均匀分布。第二步对每个资源节点 j收集与它相连的用户节点发来的先验消息这些消息给出了每个用户各码字的概率。第三步核心剪枝遍历用户码字组合时不是把所有 M^df 个组合都取出来算因子值而是一层一层地构建组合。我实现时把 df 个用户的码字索引排成一个搜索树每个分支代表一个用户的候选码字。搜索时维护一个累计距离 d_cum每往下一层就根据信道系数和接收值计算这一层新增的部分欧氏距离增量。如果 d_cum 加上一个乐观下界估计后仍然大于当前半径就直接回溯剪枝。所谓乐观下界是假设剩余层全部取最小增量用这个下限来判断是否值得继续。剪枝条件写得严格复杂度就低但性能也会损失所以半径的选择非常关键。第四步把所有通过剪枝保留下来的分支对应的因子值算出来按 MPA 的规则更新资源节点到用户节点的消息接着用户节点更新外信息送回资源节点如此迭代若干次最后计算每个用户各码字的后验概率输出硬判决。这里有一个容易被忽视的细节SD-MPA 虽然剪掉了大量分支但对保留下来的分支必须和标准 MPA 完全一样计算因子值不能为了省事用近似值。否则迭代几轮后消息误差会累积性能下降比想象的快。2.3 复杂度对比与性能指标我用 6 用户 4 资源的配置做过一轮对比三种方案分别是传统 MPA、SD-MPA初始半径系数 α2.5、以及理论上的最大似然ML检测ML 在这个规模下还能遍历但 K 再大就完全跑不动。结果很直观方案每资源块等效搜索组合数相对MPA复杂度BER10^-2所需SNR传统 MPA641.0x约 10.2 dBSD-MPA约 27-380.42x-0.59x约 10.4 dB最大似然409664x约 10.0 dBSD-MPA 的复杂度并非固定随 SNR 变化很明显。低 SNR 时噪声大半径下界宽剪不掉多少分支高 SNR 时最优路径和次优路径距离拉得开剪枝效率很高复杂度甚至可以降到 MPA 的 1/3 以下。这个特性在实际系统里其实很讨喜因为大部分时间信道条件属于中等偏上复杂度自然就降下来了。BER 方面SD-MPA 相比传统 MPA 在 BER10^-2 处大概损失 0.2 dB 左右算是可以接受。如果调小半径性能损失会增加复杂度更低调大半径则复杂度升高性能逼近 MPA。这本质上是一个滑动折中可以通过 α 系数在线调节。这也是我最终选 SD-MPA 的原因在性能损失可控的前提下多了一个可调的复杂度旋钮这在工程实现中非常实用。3. 实操过程与核心环节实现3.1 仿真搭建环境与参数设置我用的是 MATLAB通信系统仿真用它还是最顺手矩阵运算和伯努利随机数生成都很方便。代码拆成几个模块码本生成、发端映射、信道生成、SD-MPA 检测器、BER 统计。每个模块单独调试最后再联调。仿真参数列举如下参数取值说明用户数 K6活跃用户数资源块数 J4OFDM 资源单元数因子图度数 df3每个资源块叠加 3 个用户码本大小 M4每个用户码本中码字个数调制方式QPSK对应每码字 2 bit信道模型瑞利平坦衰落每个资源块独立信道系数迭代次数5MPA 迭代轮数初始半径系数 α2.5半径 α * 噪声方差初始半径的设置是重头戏。理论上最优半径应该包含真实发送码字组合的高概率区域我采用 R^2 α * J * σ^2其中 σ^2 是噪声方差α 取 2.5。这个取值法来自概率论里的卡方分布直觉J 维噪声能量大部分集中在均值附近乘以一个 2~3 的系数可以让真实解大概率落在球内。α 太大剪枝失效太小会出现球内无候选导致检测失败。我在代码里加了保护机制若某个资源块搜索为空就自动把半径扩大 1.5 倍重新搜索这个兜底非常重要。3.2 SD-MPA核心实现步骤核心检测器我写成函数sd_mpa_detector(y, H, codebook, F, M, max_iter, alpha)。内部逻辑分三层外层迭代、中层资源节点搜索、内层剪枝。外层迭代的伪代码如下使用 Python 风格描述逻辑和 MATLAB 一致for it in range(max_iter): for j in range(J): # 获取与资源块j相连的用户索引 xi_j users_on_j get_users_on_resource(F, j) # 收集这些用户传递过来的消息 msgs get_user_to_resource_msgs(users_on_j) # 球约束搜索所有可能的码字组合 candidates sphere_search(y[j], H[users_on_j, j], codebook[users_on_j], msgs, radius, max_keep64) # 根据保留下来的候选计算资源节点到用户节点的消息 update_resource_to_user_msgs(j, users_on_j, candidates) # 更新用户节点消息 for k in range(K): update_user_to_resource_msgs(k)重点在sphere_search。它的输入是当前资源块接收值、各用户信道系数、当前码字先验消息。搜索时维护一个长度为 dfs 的索引数组idx递归展开第 d 层def sphere_search(y_part, h_part, cw_part, prior_msgs, R2): best [] def dfs(depth, current_idx, accum_dist): if depth df: # 叶子节点完整候选组合计算联合因子 factor compute_factor(y_part, h_part, cw_part, current_idx) prob factor * prod(prior_msgs[d][current_idx[d]] for d in range(df)) best.append((prob, current_idx.copy())) return # 对当前层用户的所有码字按部分距离增量排序优先搜小增量 for m in order_candidates_by_increment(y_part, h_part, cw_part, depth): inc compute_increment(y_part, h_part, cw_part, depth, m) if accum_dist inc R2: dfs(depth 1, current_idx [m], accum_dist inc) # 若增量已经超过剩余距离后续排序更大可以提前剪枝 dfs(0, [], 0.0) return best这个实现的关键点有两个。第一每层当前用户的候选码字要按部分增量从小到大排序。排序越合理越早找到好的完整路径半径就能更新得更紧剪枝效率越高。第二compute_increment里只算当前层新增的欧氏距离不要重复计算前面层的距离。我最初版本把累计距离算成了平方和再加结果距离增长过快大量分支被误剪BER 直接崩了。后来改成逐层增量累加才恢复正常。3.3 实测结果与调参心得跑完整个仿真我对比了不同 SNR 下的 BER 和平均搜索节点数。BER 曲线上面说过了和 MPA 几乎重合。这里重点说搜索节点数1 dB 时平均每个资源块搜索 45 个组合10 dB 时降到 28 个15 dB 时只有 22 个。也就是说高信噪比下SD-MPA 能省掉一半以上的组合搜索而高信噪比恰好是系统追求高质量传输的场景这个特性非常理想。调参过程中感受最深的有两点。一是半径系数的敏感性。α 取 2.0 时BER 在低信噪比区明显变差因为球内漏掉真实解的概率变大中高信噪比区反而还好。α 取 4.0 时复杂度回到 MPA 的 80% 以上剪枝意义就不大了。我最后用了动态半径第一轮迭代用 α3.0 保证不漏检后续迭代根据已经找到的最优路径距离把半径收紧到该距离的 1.2 倍。这样兼顾了低信噪比的稳健性和高信噪比的剪枝效率。二是迭代次数。SD-MPA 因为剪枝丢了一部分弱分支消息收敛比传统 MPA 稍慢。迭代 3 次时性能差了 0.5 dB5 次基本稳定7 次以上几乎没提升。实际跑 5 次是性能和复杂度的甜点。这个和传统 MPA 的结论一致但 SD-MPA 每次迭代搜索量降低所以总耗时还是比 MPA 低不少。4. 常见问题与排查技巧4.1 检测性能恶化的排查清单这个问题我调试时踩过很多次拆成几个方向逐一检查。先查码本归一化。码本每个码字的平均能量没有归一化到 1等效信噪比会被拉高或拉低BER 曲线整段平移。用一个简单函数检查mean(abs(codebook(:)).^2)应该等于 1。再查半径兜底。SD-MPA 搜索时如果球内一个候选都没有必须触发半径扩大机制。我最初没加这个保护低信噪比下频繁出现空搜索检测器只能随机猜测符号BER 奇差。加了“检测到空则扩大 1.5 倍半径重搜”的机制后问题立刻消失。还要查消息更新方向。MPA 的消息是有向的从资源节点到用户节点和从用户节点到资源节点不能搞混。很多入门实现会在这里写反导致迭代越跑越差。调试时做一个简单测试把所有信道幅度设成相等且无噪声检测器应该能完美恢复发送符号如果这个测试不通过问题一定在消息更新逻辑上。最后查数值稳定性。概率在连续乘法后会下溢特别是码本点数多、迭代轮数多时。我直接把所有消息更新放到对数域实现用 log-sum-exp 做加法彻底解决下溢问题。对数域实现初期稍微繁琐但省掉后续大量坑值得。4.2 复杂度下降不明显的处理有读者会问我SD-MPA 剪了半天复杂度怎么和直接 MPA 差不多这通常是因为剪枝条件太宽松。我排查时先打印半径收敛曲线如果半径几乎没有随搜索过程收缩说明初始半径太大或排序策略失效。对策之一是做候选排序。前面代码里所有候选码字按增量从小到大排序这个排序作用巨大。如果直接按码本索引顺序搜索好的路径可能最后才找到半径一直很大剪不掉分支。排序开销很小但剪枝效率提升立竿见影。对策之二是调整用户搜索顺序。不是所有用户对资源节点的贡献都一样优先从信道增益大的用户开始搜索可以更快地收紧半径。具体做法是先计算每个用户的 |h|^2按从大到小排列搜索层。这个改进在信道差异明显的场景比如用户离基站近远不同时效果特别明显。对策之三是动态半径更新。不能把半径设死每找到一个完整候选组合就尝试用它的累计距离更新半径。这个操作几乎是免费的但能带来持续的剪枝增强。实际仿真中加了这个策略后平均搜索节点数又降了 15% 左右。4.3 场景扩展与叠加优化的思考SD-MPA 不是孤立只能用在 SCMA 上。凡是因子图上做离散联合搜索的算法都可以尝试引入球约束。比如 LDPC 译码里的最小和算法或者稀疏码分多址SCMA 的近亲中的检测这个思路都能迁移。我在项目里还尝试过一个变体把 SD-MPA 的剪枝结果直接用来降低 MPA 迭代中参与消息计算的候选集合规模相当于在每条边上维护一个动态候选列表进一步减少计算量。正向延伸的方向是联合半径优化和自适应迭代。可以根据解码后的 CRC 校验结果来提前终止迭代或者动态调整半径系数在高可靠场景和低时延场景之间切换。尤其是车联网、低功耗广覆盖这类场景系统对时延和功耗敏感SD-MPA 这种“复杂度可随时调节”的特性比传统固定复杂度的 MPA 有优势得多。这个项目做到最后我最大的一点体会是很多高性能算法不敢落地不是因为性能不好而是复杂度不可控。SD-MPA 之所以值得做是因为它提供了一种机制的复杂度弹性。你不需要在系统设计初期就把所有资源预留满而是可以依据信道状态和业务负载在线调节搜索半径让检测器始终运行在“够用就好”的状态。这种思维比单纯追求某个检测算法跑分更有工程价值。本文还有配套的精品资源点击获取
返回列表