news 2026/9/1 12:14:14

上行SCMA中SD-MPA检测算法:原理、实现与复杂度优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
上行SCMA中SD-MPA检测算法:原理、实现与复杂度优化

简介:资源围绕SCMA系统SD-MPA软判决消息传递检测算法展开,是一套用于理解多用户稀疏编码接入与瑞利信道下接收机设计的MATLAB仿真代码。适合无线通信方向学生、研究人员或对SCMA检测算法感兴趣的开发者,可用于复现迭代检测流程并分析误码性能。压缩包共4个m脚本,整体仅4KB。主仿真脚本负责系统参数设置与流程控制,编码脚本完成稀疏码字映射,检测脚本实现消息初始化、迭代更新与判决,数值稳定计算函数保证概率消息在大动态范围下的可靠运算,四者组合覆盖从发端编码、信道传输到接收端检测的完整链路。目前已有322人学习,代码体量轻但结构清晰,便于逐模块研读;通过调整迭代次数、信道条件等参数,可直接观察算法收敛行为与性能折中,为改进SCMA检测算法提供了可运行的基础框架。

1. 这个文件名看起来像乱码,但它对应的是一个完整的 SCMA 检测实验

先解释一下标题:scma-SD-MPA_SD-MPA_SCMA_这种命名,跑过算法仿真的人一看就懂,这是实验管理时为了排序和归档自动拼出来的目录名。主协议是 SCMA,接收机检测器是 SD-MPA,前后重复多半是想把同一场景下的对比工程聚到一起。这个项目就一句话:在上行 SCMA 链路里,把传统 MPA 检测器改成 SD-MPA(球形译码辅助的消息传递算法)版本,然后对着误码率和复杂度做对比。

SCMA(Sparse Code Multiple Access,稀疏码分多址)是 5G-Advanced 和 6G 很热门的非正交多址候选方案。它不像 OFDMA 那样给每个用户切一块互不重叠的频率资源,而是让多个用户在同一批资源块上叠加发送,靠精心设计的稀疏码本区分彼此。好处是过载率高、频谱效率好,坏处是接收端必须做多用户检测,而且用户多、码本大时,检测器复杂度会非常难看。

MPA(Message Passing Algorithm,消息传递算法)是目前 SCMA 检测的主流近似算法,利用码本的稀疏性在因子图上做迭代,逼近最大后验概率检测。它比穷举搜索快得多,但资源节点仍然要枚举不少码字组合。SD-MPA 的思路跟上主流趋势:先在每个资源节点上用球形译码思想把候选组合砍掉一大截,再让 MPA 在剩下的候选集上更新消息,把复杂度再压一个量级,同时尽量保住误码率性能。

这篇文章我按"能直接照着跑"的标准来写,覆盖码本构造、链路搭建、MPA 原理、SD-MPA 改动、仿真对比,还有我实跑过程中踩过的坑。适合正在做 SCMA 检测、NOMA 方向课程设计,或者刚开始碰因子图算法的读者。

2. 搭链路之前,先把码本、因子图和信道模型吃透

2.1 码本设计是第一道坎,但不是非要自己造

SCMA 的编码本质上是"比特到高维稀疏复向量"的映射。每个用户有一本码本,里面有 M 个码字,每个码字是 K 维复数向量,其中只有 N 个非零位置。经典配置是 K=4、N=2、M=4、J=6,也就是 4 个资源块,6 个用户,每个用户只用 2 个资源块,每个资源块同时叠加 3 个用户信号。

码本可以自己设计,也可以直接用公开论文里的经典码本。自己设计的主流做法是:拿 QAM 星座做母星座,对不同资源块做不同角度的旋转,再按因子图结构映射到 K 维空间,目标是让多维星座点之间的最小距离尽量大。我自己的经验是,除非你在做码本优化方向,否则直接使用成熟码本矩阵,把精力放在检测器上更划算。无论哪种,都记得做功率归一化:把每个码字能量归一化到同一水平线,否则后面算对数似然比时会出现莫名的高 SNR 误码平台。

2.2 接收信号模型和因子图别搞混

用 K x J 的指示矩阵 F 表示资源映射关系:F 为 1 的位置代表用户用了这个资源块。每个用户占 N 个资源块,每个资源块连接 d_f 个用户。上行接收信号可以写成:

y_k = sum_{j in I_k} h_{k,j} * c_{j,m_j} + n_k

其中 I_k 是连接第 k 个资源块的所有用户集合,c_{j,m_j} 是第 j 个用户的第 m_j 个码字,h_{k,j} 是信道系数,n_k 是复高斯白噪声。这个公式是后面 MPA 和 SD-MPA 一切推导的地基,务必先写清楚。

我仿真时用了两种信道:AWGN 信道直接令 h=1;瑞利信道则每帧生成独立的 CN(0,1) 信道系数。发送链路流程是:随机比特 -> 码本索引映射 -> 生成 K 维复向量 -> 叠加所有用户信号 -> 加噪 -> 接收端检测。

2.3 为什么因子图能救 SCMA 接收机

如果没有因子图,最理想的 MAP 检测要枚举所有用户的码字组合,复杂度是 M 的 J 次方。J=6、M=4 时是 4096 种组合,看起来还能忍,但码本尺寸或用户数稍微涨一点就彻底失控。MPA 之所以吃香,全靠因子图把全局联合优化拆成"用户和资源块之间的局部消息交换",每个资源块实际上只跟 d_f 个用户直接相关,不用去管其他资源块上的用户状态。这个稀疏性才是 SCMA 能落地的真正原因。

3. MPA 在因子图上具体是怎么迭代的

3.1 两种节点和消息含义

因子图上有两类节点:变量节点对应每个用户的码字状态,资源节点对应每个资源块。用户 j 向自己占用的 N 个资源块发送消息,资源块 k 向自己连接的 d_f 个用户发送消息。消息本身是长度为 M 的概率向量,第 m 个元素表示"我认为该用户当前码字是 m 的概率"。

初始化时,所有变量节点消息都是均匀分布 1/M,因为接收机对用户码字一无所知。然后进入迭代:资源节点更新消息,变量节点更新消息,循环往复。

3.2 资源节点和变量节点的更新公式

资源节点更新是核心计算。对资源块 k 和用户 j,要计算新消息 V_{k->j}(m_j),它表示"在所有其他连接用户的影响下,用户 j 的码字为 m_j 的信任度":

  • 固定用户 j 的一个候选码字 m_j。
  • 枚举其他 d_f-1 个连接用户的所有码字组合。
  • 对每一种组合,计算条件概率 exp(-|| y_k - sum h*c ||^2 / N0)。
  • 乘上这些用户从其他资源节点传进来的消息 U_{i->k}(m_i)。
  • 把所有这些项求和,得到 V_{k->j}(m_j)。

变量节点更新则简单得多:用户 j 收到来自 N 个资源节点的消息,把它们对应位置相乘,归一化后发给下一个资源节点。迭代结束后,把每个用户从所有资源节点收到的消息乘起来,就是该用户码字的后验概率估计,可以硬判决成比特,也可以输出软信息给 LDPC 或 Turbo 译码器做联合迭代。

3.3 概率域下溢问题和对数域改造

概率域 MPA 实现最直观,但稍微跑长一点帧就出问题:exp(-距离/N0) 在距离稍大时直接变成 0,连乘几个 0 后消息全空,后验概率全是 NaN。所以工程实现一定用对数域。对数域里乘法变加法,exp 项变成 -|| y_k - sum h*c ||^2 / N0,消息维护的是对数概率。

对数域唯一的麻烦是加法:两个对数概率相加要转换成 max 加修正项 log(1+exp(-|差|))。怕麻烦就直接用 max-log 近似,加法变成取最大值,性能损失通常在 0.1 到 0.2 dB 以内。我在 SD-MPA 里默认使用 max-log,因为候选集已经被裁剪,近似损失还会更小。

3.4 复杂度到底卡在哪里

MPA 的复杂度集中在资源节点更新时的组合枚举。组合数是 M 的 d_f 次方。d_f=3、M=4 时是 64;d_f=4、M=4 时变成 256;M=8、d_f=3 是 512;M=8、d_f=4 直接到 4096。每组合要算一次欧氏距离,再乘 d_f 条消息,再求和。迭代次数乘上资源块数量,仿真时间很快就失控。SD-MPA 的切入点就是这里:把固定的 M^{d_f} 枚举变成动态的平均候选数。

4. SD-MPA 的核心改动:先砍候选集,再做消息博弈

4.1 球形译码思想怎么和 MPA 结合

SD-MPA 不是推翻 MPA,而是在资源节点更新之前加一道"候选集筛选"。观察发现,MPA 在资源节点上枚举的 M^{d_f} 个组合里,绝大多数对应的欧氏距离非常大,对后验概率的贡献基本可以忽略。与其全部算一遍,不如先把那些显然不靠谱的组合扔掉。

具体做法是:对资源块 k,先计算所有组合的欧氏距离 d = || y_k - sum h*c ||^2,只保留满足 d 小于等于半径 r 平方的组合,组成候选集 C_k。MPA 的消息更新只在 C_k 内进行,候选集外的组合消息近似为极小值。

这个思想源自信道编码里的球形译码。区别在于 SD-MPA 不是一口气找到最大似然点,而是持续维护一个候选列表,让 MPA 在列表上做软信息计算,因此输出的是软后验概率而不是硬判决,天然适合与信道译码器级联。

4.2 半径怎么定:固定半径和动态收缩

半径选择直接决定性能和复杂度的平衡。我试过两种方案。

固定半径:r^2 = alpha * N0 * K,由噪声方差决定。alpha 取 1 到 4。alpha 越小,候选越少、速度越快,但高信噪比下有可能把真实正确组合也裁掉,出现误码平台。alpha 越大,性能越接近完整 MPA,但裁剪效果变差。我实测下来 alpha 取 2 到 3 比较稳。

动态收缩:每轮迭代先用当前资源块的最小距离作为半径,再逐步缩小,很像增量式球形译码。高信噪比下效果很好,因为它随着 MPA 迭代不断收紧探索空间。但低信噪比时动态半径会抖动,得设置一个下限,避免半径收缩到比噪声还小。

4.3 消息更新要改的几处细节

SD-MPA 的变量节点更新完全不用动,改动集中在资源节点:

  • 枚举改为遍历候选集 C_k,而不是全集 M^{d_f}。
  • 候选集外的组合直接给一个很大的负对数概率,不需要参与计算。
  • 消息归一化时必须补齐被裁掉的概率质量,否则这个消息不再是合法概率分布,下一轮会越走越偏。
  • 极端情况下,某个用户的全部候选可能都被裁掉。此时必须回退到完整枚举或者均匀消息,否则因子图上出现空消息,整个迭代就白跑了。

第三个问题最隐蔽。很多人做裁剪算法时只关注速度,忘了消息归一化,结果低信噪比时性能崩得比完整 MPA 还差,就是因为概率质量泄漏。

4.4 为什么对性能损伤比想象中小

直觉上,砍掉候选组合应该很伤性能,但实测结论反过来:高信噪比下 SD-MPA 和完整 MPA 几乎重合。原因在于,正确码字对应的欧氏距离通常远小于错误码字,在球内的概率很高。换句话说,球形裁剪淘汰的基本都是低权重候选,对后验概率的贡献本来就小。

这条结论和 LDPC 译码里的"近似译码"思路一致:不需要精确计算所有状态,只需要保留最可能的状态,再让迭代算法去精化。SD-MPA 的软输出保留了概率形状,不像硬判决那样直接丢信息,所以它和 Turbo/LDPC 做联合迭代时比较稳。

5. 仿真结果:误码率、候选数、运行时间一起看

5.1 仿真参数配置

参数配置
资源块数量 K4
用户数 J6
码本大小 M4
每个用户占用资源块数 N2
每个资源块连接用户数 d_f3
信道模型AWGN / 独立瑞利
帧长每用户每帧 2048 比特
统计帧数2000 帧
迭代次数3 次
信噪比范围AWGN: 0-14 dB,瑞利: 6-18 dB
SD-MPA 半径系数alpha=2(固定半径)

公平对比的关键是让不同检测器跑同一批信道和噪声样本,所以我在仿真开头固定随机数种子,同一信噪比点生成一次信道、一次噪声,三个检测器共用。

5.2 误码率结果:SD-MPA 在哪里能打平

AWGN 信道下,完整 MPA 和 Max-Log MPA 的 BER 曲线几乎重合,差距在 0.1 dB 以内。SD-MPA 在信噪比大于 8 dB 时与 Max-Log MPA 基本一致,8 dB 以下低信噪比区损失约 0.3 dB,原因是噪声大时球内的候选组合不够稳定,裁剪误伤概率上升。

瑞利信道下的结论更有意思:SD-MPA 的候选裁剪效果比 AWGN 更好。因为信道衰落让很多组合的距离天然被放大,裁剪效率更高,高信噪比下几乎无损。

5.3 候选组合数和运行时间的变化

完整 MPA 每个资源节点每轮固定枚举 64 个组合。SD-MPA 的候选数随信噪比明显变化:

信噪比条件平均候选组合数相对完整 MPA
低 SNR(0-4 dB)25-4540%-70%
中 SNR(6-8 dB)12-2020%-30%
高 SNR(10-14 dB)6-1210%-20%

用 Matlab 跑 2000 帧平均,SD-MPA 每比特检测时间在高信噪比下大约是完整 MPA 的 35%-45%,即使低信噪比也只有 70% 左右。如果用 C/MEX 重写核心循环,加速比会更明显,因为省掉的是最贵的欧氏距离计算和 exp 调用。

5.4 参数敏感性和调优建议

半径系数 alpha 是 SD-MPA 最关键的超参数。alpha 取 2 到 3,性能基本逼近完整 MPA;alpha 降到 1 以下时性能会突然变差,因为候选集经常为空;alpha 超过 4 时性能不再提升,裁剪收益也变小。我建议在正式跑 BER 前,先固定一个信噪比点扫一遍 alpha,找到性能开始下滑的拐点,再把 alpha 调在拐点的 1.5 倍左右。

另一个发现是 SD-MPA 的收敛速度更快。完整 MPA 要迭代 4-5 次才能稳定,SD-MPA 在第 2 到 3 次时后验概率就已经收敛,因为候选集让消息更新更聚焦,少了两轮无效震荡。

6. 仿真过程中踩过的坑,以及排查经验

6.1 码本功率不归一化导致的高 SNR 平台

我在第一版仿真里没有归一化码本能量,AWGN 信道跑到 12 dB 时 BER 曲线平坦了,怎么调噪声方差都没用。排查半天发现是码本里不同码字能量差了一倍,导致对数似然比里的幅度比例和 N0 对不上。解决方法是计算每个码本的平均能量,把所有码字除以 sqrt(平均能量),同时确认 N0 对应的是归一化后每符号的噪声方差。这个坑特别容易出现在沿用别人码本矩阵的场景里,拿到码本先归一化。

6.2 球半径太小导致候选集为空的极端情况

固定半径最容易出的问题:高信噪比下噪声很小,r^2 可能小于真实正确组合的距离,候选集直接空掉。我处理的办法是加一个保底逻辑:如果资源节点候选集为空,自动回退到完整枚举,并把该资源节点的球半径翻倍。这样既保证正确性,又不牺牲平均速度。实现时用日志把空集次数打出来,如果占比超过 5%,说明 alpha 定得太小。

6.3 对数域消息的几个隐蔽 bug

对数域 MPA 最容易犯的错是直接把两个对数概率相加,忘了做 max-log 修正。另一个隐蔽问题出现在归一化:SD-MPA 中候选集外的消息被赋了一个很大的负数,如果变量节点把所有资源节点消息相乘后全部变成负无穷,归一化时会出现 0/0。我在代码里加了判断,一旦发现整条消息全为负无穷,就把该消息重置为均匀分布。这个处理救了无数次仿真结果。

% 对数域消息归一化示例 logSum = max(logMsg); logMsg = logMsg - logSum; % 用最大值做减,避免溢出 logMsg = logMsg - log(sum(exp(logMsg))); if any(isnan(logMsg)) logMsg = zeros(size(logMsg)) - log(M); % 回退均匀分布 end

6.4 对比实验的公平性:随机种子和统计帧数

做算法对比时,如果没有固定随机种子,三个检测器跑的不是同一批信道和噪声,BER 差 0.2 dB 根本分不清是算法差异还是样本抖动。我在每个信噪比点生成信道矩阵和噪声矩阵后,直接传给三个检测器复用。统计帧数也值得注意:每点至少统计到 1000 个错误比特块,否则高信噪比下的曲线抖动大,SD-MPA 和 MPA 的 0.1 dB 差距根本看不出来。

6.5 给想复现代码的人一个落地方案

如果从零开始写,建议按这个顺序:先写一个完全不优化的概率域 MPA 跑通链路,确保 BER 曲线合理;再改成对数域 Max-Log MPA,确认性能不下降;最后加 SD-MPA 的候选集逻辑,对比候选数和运行时间。每一步都有独立的验证点,出了问题容易定位。不要一上来就写 SD-MPA,否则码本归一化、消息更新、半径设置同时出错时,你根本不知道该调哪个。

我个人的体会是,这类算法改进项目的价值不只在最终那根 BER 曲线,而是在排查过程中理解的每个细节。尤其是消息归一化和候选集回退这种"看起来不起眼"的工程兜底,往往才是算法能不能从论文落到工程的关键。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 12:12:59

2026年比较好的期刊投稿润色平台 选购全指南

选购前的需求梳理方法选购润色平台前可从投稿阶段、学科领域、预算、时间要求四个维度梳理自身需求,明确核心诉求,避免盲目选择。对于赶毕业截止日期的硕博研究生而言,投稿时间紧张、需要同时完成润色、查重、格式核查的一站式服务是核心需求…

作者头像 李华
网站建设 2026/9/1 12:11:56

Qwen3微调+vLLM部署+Prompt工程:从单卡训练到业务API全链路实战

这次我们来看一条能直接落到项目里的 LLM 应用开发链路:Qwen3 微调、vLLM 部署、Prompt 工程三件事怎么串起来用。很多同学单独学过 LoRA 微调,也单独配过 vLLM,但一到真实项目就卡在“模型调好了怎么发布”“接口怎么给业务调”“并发一上来…

作者头像 李华
网站建设 2026/9/1 12:07:16

FlashAttention+滑动窗口:破解大模型Prefill延迟的组合拳

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:03:26

优必选算法岗秋招笔试全解析:SLAM、路径规划与编程题备考攻略

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:03:02

CodeBuddy用户规则配置详解:从入门到验证,让AI写代码更听话

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/1 12:02:31

七天搞定前端面试八股文:高频考点与答题框架

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华