5G 靠什么在嘈杂信道里不传错?LDPC 与 Polar 这对黄金组合,管着数据信道与控制信道的生死。本文从香农极限讲到工程抉择,并用可复现的 Python 仿真亲手跑通两种编码——还发现了一个只有跑代码才能看见的"4-环教训"。
引子:5G 在嘈杂信道里凭什么"不传错"?
你有没有想过:手机在高速地铁里、在人山人海的演唱会上,为什么打电话、刷视频偶尔卡一下,但消息基本"传不错"?
答案藏在 5G 物理层最硬核的一环——信道编码(Channel Coding)。5G NR 里负责纠错的是一对黄金组合:LDPC 码(数据信道)和Polar 码(控制信道)[1]。
这篇文章把这件"隐形但决定生死"的事讲透:为什么需要信道编码、LDPC 和 Polar 各自凭什么入选 5G、5G 为什么"数据用 LDPC、控制用 Polar"——以及最重要的:用 Python 亲手把这两种编码跑起来。文中所有仿真代码我都本地运行验证过,输出是真实的,可直接复现。
一、为什么需要信道编码:从香农极限说起
1.1 噪声是物理定律,不是 bug
任何物理信道都有噪声:电磁干扰、热噪声、多径衰落。信号一旦发出去,接收端拿到的永远是"污染版"。问题是如何在噪声里恢复原始比特?
香农在 1948 年给出理论回答:只要码率 R 低于信道容量 C,就存在某种编码让误码率任意小——这就是香农极限[2]。
1.2 编码的本质:用冗余换可靠性
信道编码就是在原始数据后加冗余(校验比特),让接收端能发现甚至纠正错误:
原始数据 1011 → 加冗余 → 发送 1011 0110 → 噪声 → 接收 1011 0010 ↓ 译码 恢复 1011 ✓从 4G 到 5G,数据信道编码经历了一次换代:LTE 用Turbo 码,5G NR 换LDPC 码;控制信道引入全新的Polar 码[1]。这次换代背后,是一场持续半个多世纪的"容量可达"竞赛。
二、LDPC 码:从 1962 到 5G 数据信道
2.1 历史三幕
LDPC(Low-Density Parity-Check,低密度奇偶校验)码的故事,像一部被埋没又翻红的电影[3][4]:
年代 | 事件 |
|---|---|
1962 | Gallager 提出 LDPC,但因硬件算力不足被忽略近 30 年 |
1981 | Tanner 引入图表示(Tanner 图) |
1995 | MacKay/Neal 复兴,证明逼近香农极限 |
2018 | 3GPP Rel-15 定稿,LDPC 成为 5G 数据信道编码 |
2.2 原理:稀疏校验矩阵与 Tanner 图
LDPC 定义很朴素:校验矩阵 H 中 1 的密度极低。编码输出 n 比特(含 k 个信息比特),H 是 (n-k)×n 矩阵,满足任意合法码字 c:H·c^T = 0(模 2)[3]。
"低密度"为什么重要?因为稀疏性让迭代译码可行。H 可画成 Tanner 图:左边变量节点(比特),右边校验节点(方程):
每个校验节点对应一个校验方程(若干比特异或为 0)。译码时消息在图上反复传递,这就是置信传播(Belief Propagation, BP)。
2.3 5G NR 的 LDPC:从概念到工程
5G 用的是精心设计的准循环 LDPC(QC-LDPC):先定义一张小的基图(Base Graph),再用循环移位(提升,Lifting 参数 Z)扩展成大矩阵[5][6]。5G 定义了两张基图[7]:
基图 | 规模 (N, M) | 面向场景 |
|---|---|---|
BG1 | (68, 46) | 大传输块、高速率 |
BG2 | (52, 42) | 小块、低速率 |
数据信道块长可达8448 比特,大块长下 LDPC 的高吞吐、强并行、低时延优势发挥得淋漓尽致[1]。
2.4 译码:min-sum 置信传播
LDPC 译码是迭代消息传递。假设接收端每个比特得到对数似然比(LLR):
变量节点:Mvc[i,j] = Lc[i] + Σ_{t≠j} Mcv[i,t] 校验节点:Mcv[i,j] = (∏_{t≠i} sign(Mvc[t,j])) · min_{t≠i} |Mvc[t,j]|min-sum 是标准 BP 的简化近似,牺牲一点性能换实现简单,是硬件主流选择。实战部分用代码完整复现。
三、Polar 码:信道极化的奇迹
3.1 Arikan 2009:第一个"显式"容量可达的码
如果说 LDPC 是"靠系综平均好",Polar 码就是"我构造的每一个码都好"。
2009 年 Erdal Arikan 提出信道极化方法,构造出第一类显式构造、低复杂度、可证明容量可达的编码[8][9]。这是编码理论史上里程碑式的突破。
3.2 信道极化:把"平均水平"变成"两极分化"
对 N 个独立信道副本做递归变换(极化核 F = [[1,0],[1,1]]),合成 N 个"合成比特信道":
总体能力守恒,但分布极化:一半信道更好,一半更差。在"好信道"上传信息,"坏信道"上放已知冻结位——整码性能逼近容量[8]。
3.3 Bhattacharyya 参数:怎么选信息位
用Bhattacharyya 参数 Z(W)度量信道可靠度(Z 越小越可靠)。对二进制擦除信道(BEC),有漂亮的递归[8][10]:
坏信道 W^-:Z(W^-) = 2Z - Z² 好信道 W^+:Z(W^+) = Z²选 Z 最小的 K 个信道传信息位,其余传冻结位。
3.4 编码与 SC 译码
编码:信息位向量 u × 生成矩阵 G_N = F^⊗n(Kronecker 幂)
译码:SC(连续消除),复杂度 O(N log N),逐个判决、前面结果作为后续条件
5G 实际用CA-SCL(CRC 辅助 + 列表译码)进一步提升短码性能[11]
2016 年 3GPP 正式选定 Polar 作为 5G 控制信道编码(PDCCH/PUCCH/PBCH)[11]。
四、为什么 5G 用 LDPC 做数据、Polar 做控制
这是很多人最想知道的"工程题"。答案是块长、时延、硬件实现综合权衡的结果,不是简单的好坏之分[1][7]。
4.1 数据信道:大块长 → LDPC
高吞吐:BP 译码天然可并行
低时延:并行度高,时延可控
逼近容量:大块长下容量逼近能力完全释放
4.2 控制信道:短块 → Polar
块很短(几十到几百比特):Polar 短码场景优势明显
零错误平层:Polar 无错误平层问题
结构简单:SC 译码器结构规整,硬件友好
4.3 一句话对比
维度 | LDPC(数据) | Polar(控制) |
|---|---|---|
3GPP 分工 | 用户数据信道 | 控制信道 |
典型块长 | 大(可达 8448) | 短(几十~几百比特) |
译码 | 迭代 BP(min-sum) | SC / CA-SCL |
优势 | 高吞吐、强并行、低时延 | 短码优、零平层、结构简单 |
容量可达性 | 系综平均论证 | 显式构造证明 |
历史 | 1962 Gallager → 1995 复兴 | 2009 Arikan → 2016 入选 |
五、实战:用 Python 复现两种编码
理论说得再多,不如跑一段代码。以下代码全部本地运行验证(Python + numpy),输出真实,可复现。
5.1 Polar 信道极化仿真
BEC(ε=0.3)、N=16 各比特信道 Bhattacharyya 参数(真实输出):
自然序 Z = [0.997, 0.888, 0.821, 0.333, 0.700, 0.205, 0.131, 0.005, 0.530, 0.099, 0.058, 0.001, 0.032, 0.0003, 0.0001, 0.0000]部分 Z→1(不可靠),部分 Z→0(可靠)——信道极化。选 Z 最小的 K 个信道传信息位:
import numpy as np def z_concat(N, eps): """BEC 下 Bhattacharyya 参数递归:前半坏 W^-(2z-z²),后半好 W^+(z²)。""" z = np.array([eps]) for _ in range(int(np.log2(N))): z = np.concatenate([2*z - z*z, z*z]) return z z = z_concat(16, 0.3) print(np.round(z, 4))工程细节:若编码用 G=F^⊗n(无位反转),可靠度需对 Z 做位反转置换再选信息位——仿真中容易踩的坑。
5.2 Polar SC 译码:块错误率随码长下降
编码 + BEC 擦除 + SC 译码,块错误率随 N 变化(码率 1/2,ε=0.2,真实输出):
码长 N | SC 块错误率 |
|---|---|
8 | 0.0157 |
16 | 0.0213(有限长波动) |
32 | 0.0070 |
64 | 0.0033 |
核心结论:整体趋势 N 越大错误率越低——极化越充分越接近容量。N=16 的小幅回升是有限长极化码的真实特性(极小 N 下 Bhattacharyya 构造并非严格最优),恰恰说明"容量可达"需要足够大的 N。
核心 SC 译码代码(BEC 原生实现,规避浮点 LLR 的 ±∞ 抵消):
def sc_decode_bec(y, n, info_mask, gens): """y: -1=擦除。返回译码 u。""" E = -1 def node(nl, yv, mask, gidx): if nl == 1: if not mask[0]: return np.array([0]) # 冻结位=0 return np.array([0 if yv[0] == E else yv[0]]) # 信息位 half = nl // 2 y1, y2 = yv[:half], yv[half:] f = np.where((y1 == E) | (y2 == E), E, (y1 ^ y2)) # u1·G = x1⊕x2 u1 = node(half, f, mask[:half], gidx-1) u1_enc = (u1 @ gens[gidx-1]) % 2 g = np.where(y2 != E, y2, np.where(y1 != E, (y1 ^ u1_enc), E)) # u2·G u2 = node(half, g, mask[half:], gidx-1) return np.concatenate([u1, u2]) return node(1 << n, np.array(y, dtype=int), info_mask, n)5.3 Hamming(7,4):伴随式译码(LDPC 雏形)
汉明码 (7,4) 是最小的"类 LDPC"码。伴随式译码:算 s = r·H^T,查表定位单错,翻转。
BSC 擦除概率 p | 译码后 BER | 原始误码率 |
|---|---|---|
0.03 | 0.0074 | 0.03 |
0.05 | 0.0185 | 0.05 |
0.08 | 0.0440 | 0.08 |
误码率显著下降,单错全部纠正——"加冗余换可靠性"的直接证据。
def syndrome_decode(r, H): """伴随式译码:s=r·H^T → 查表定位单错 → 翻转。""" table = {tuple(H[:, e] % 2): e for e in range(H.shape[1])} s = (r @ H.T) % 2 if tuple(s) in table: r = r.copy() r[table[tuple(s)]] ^= 1 return r5.4 min-sum vs 和积:汉明码 4-环教训(原创实验)
这是我最想分享的仿真发现。把两种 BP 译码——min-sum与和积(tanh 规则)——用在汉明码上,逐一翻转单比特看能否纠正(真实输出):
翻转bit0: min-sum=OK 和积=OK 翻转bit1: min-sum=OK 和积=OK 翻转bit2: min-sum=OK 和积=OK 翻转bit3: min-sum=FAIL 和积=OK 翻转bit4: min-sum=OK 和积=FAIL 翻转bit5: min-sum=OK 和积=FAIL 翻转bit6: min-sum=OK 和积=FAIL两种"标准"BP 译码器,各有 1 个单错纠不回来!原因:汉明码 Tanner 图存在4-环——两个校验节点与两个变量节点围成环,消息在环里打转,无法传播足够外部信息,陷入局部最优。
这个"失败"是全文最重要的工程结论:这就是为什么真实 LDPC 要避免短环(围长 ≥ 6)。5G 的 QC-LDPC 基图设计时严格规避 4-环[6]。汉明码作为"LDPC 雏形"能用(配合随式译码完美工作),但图结构不适合纯粹迭代译码——一个 60 年前的码,教会了我们 21 世纪的 LDPC 设计原则。
def min_sum_bp(y_llr, H, iters=20): """min-sum 置信传播。H: m×n 校验矩阵。""" m, n = H.shape Lc = np.array(y_llr, dtype=float) Mvc = np.zeros((n, m), dtype=float) for i in range(n): Mvc[i, H[:, i] == 1] = Lc[i] for _ in range(iters): Mcv = np.zeros((n, m), dtype=float) for j in range(m): # 校验节点:min-sum idx = np.where(H[j] == 1)[0] for i in idx: others = [t for t in idx if t != i] sp = 1.0; ma = np.inf for t in others: sp *= np.sign(Mvc[t, j]); ma = min(ma, abs(Mvc[t, j])) Mcv[i, j] = sp * ma if ma != np.inf else 0.0 for i in range(n): # 变量节点 idx = np.where(H[:, i] == 1)[0] for j in idx: others = [t for t in idx if t != j] Mvc[i, j] = Lc[i] + sum(Mcv[i, t] for t in others) return ((Lc + Mcv.sum(axis=1)) < 0).astype(int)六、总结与我的观点
6.1 三条心得
心得一:容量可达 ≠ 工程可用。LDPC 1962 年就发明,却等了 30 年才有硬件能跑;Polar 理论漂亮,落地也要靠 CA-SCL 和精心的速率匹配。理论边界和工程落地之间,隔着"硬件成本、时延、复杂度"这座大山。
心得二:5G 的编码抉择是"分场景优化"。不是 LDPC 全面碾压 Polar,而是"数据大块长用 LDPC 吃吞吐、控制短块用 Polar 吃短码性能"。理解了这个,才算理解 5G 物理层为什么是今天这个样子。
心得三:亲手仿真才叫"真懂"。这次实验最意外的收获是 4-环教训——不跑代码,我永远不会直观理解"为什么 LDPC 要避免短环"。理论告诉你结论,仿真让你"看见"结论。
6.2 展望
面向 6G,信道编码探索仍在继续:更高速率的新构造、与 AI 结合的译码器(神经网络 BP)、面向新信道的编码……但无论怎么演进,LDPC 与 Polar 在 5G 确立的"迭代译码 + 显式构造"两大范式,仍是所有新编码的地基。
建议:先把本文仿真代码跑一遍,改参数看现象,再读 Arikan 2009 原文与 ETSI 138 212 规范——从"会跑"到"懂原理",中间只差"亲手改一改"。
参考资料
[1] Cambridge《An overview of channel coding for 5G NR cellular communications》(二级)2019
[2] ETSI TS 138 212 V15.12.0(5G NR 复用与信道编码规范)(一级)2021-10
[3] Gallager, Low-Density Parity-Check Codes, IRE Trans. IT-8:21-28(一级)1962
[4] 清华大学《Introduction to LDPC Codes》课件(LDPC 历史三幕)(三级)2018
[5] 3GPP Spec Explorer:LDPC(QC-LDPC、基图+提升)(三级)2026-08
[6] nxgconnect:LDPC Coding in 5G NR(BG1/BG2 分工)(三级)2026-01
[7] arXiv 2502.11053《Demystifying 5G Polar and LDPC Codes》(二级)2025-02
[8] Arikan, Channel Polarization, IEEE TIT 55(7):3051-3073(一级)2009
[9] IEEE TechNav:Polar Codes(二级)2026-07
[10] 仿真本地验证:BEC 下 Z 参数递归式(见 polar_ldpc_sim.py)
[11] arXiv 2506.04163(3GPP 2016 选定 Polar 用于控制信道)(二级)2026-05
注:仿真数据来自文章配套脚本
polar_ldpc_sim.py本地运行输出,可复现。