ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

极化码速率匹配:打孔、缩短与准均匀打孔QUP详解

极化码速率匹配:打孔、缩短与准均匀打孔QUP详解 看到标题里的“打孔”如果是从PCB行业过来的朋友第一反应多半是包地打孔的孔间距怎么算、地过孔怎么摆。但这里要聊的是极化码Polar Code编码技术里的另一个“打孔”在中文文献里也叫删余、凿孔英文写作puncturing。和它经常一起出现的还有缩短shortening、准均匀打孔QUP。做5G物理层或者研究信道编码的人几乎每天都要和这一组概念打交道。这篇文章要解决的就是一件事把极化码为什么需要打孔和缩短、QUP到底在干什么、工程上怎么算参数、译码器怎么初始化、最常见的坑在哪里用一套完整逻辑讲清楚。无论你是刚接触信道编码的学生还是在做协议栈实现、FPGA验证的工程师都能从里面找到可以直接抄走的步骤和排查经验。先建立一个整体认知后面再展开细节。1. 极化码为什么绕不开打孔和缩短1.1 母码长度只能是2的幂极化码和LDPC、Turbo码不一样它要求编码矩阵的尺寸严格是2的幂也就是母码长度N2^n。这个约束来自编码矩阵的递归构造方式生成矩阵用克罗内克幂一层层叠出来信道极化过程也依赖这种二分结构。你没法直接定义一个N48的极化码因为48不是2的幂矩阵结构就断了。但实际通信系统分配的资源是任意整数。比如系统给你48个资源单元而离48最近的2的幂是64那怎么把64个编码比特塞进48个位置里这时候就需要速率匹配。速率匹配本质上是“凑长度”的工程手段N个编码后比特经过处理后变成E个实际传输比特。E比N小就删除一部分E比N大就把一部分比特重复发送。删除这一步要么用打孔要么用缩短。这里有个很容易绕晕的点在有些资料里“速率匹配”泛指打孔、缩短、重复三种手段的总称在另一些资料里速率匹配单指针对HARQ的比特选择。本文按通信系统最常见的用法把打孔、缩短、重复都算作速率匹配的底层操作。你是做协议实现的话只要心里清楚这三个操作最终都是为了把N个比特变成E个比特后面看标准就不容易混乱。1.2 速率匹配在收发链路里的位置一个最简化的Polar编码发射链路是信息比特加CRC后填入信息位其余位置填冻结比特经过Polar编码得到N个编码比特再经过速率匹配得到E个比特然后调制发送。接收端的方向刚好反过来解调得到N个位置里的部分LLR再经过解速率匹配恢复出一个完整的N长LLR序列送进Polar译码器。注意“恢复”这个动作。接收端并没有真的把被删掉的比特从空气里拿回来它只是把对应位置的LLR按照约定填上。打孔的位置填0表示完全未知缩短的位置填一个很大的正数表示确定是0。这个填法如果搞错了整个译码器直接崩溃。所以速率匹配图案必须在收发两端严格同步协议里会把图案生成的规则写成公共算法两边用同一套输入参数得到完全一样的打孔位置和缩短位置。我调试L1原型时最开始的几次“灵异现象”最后查来查去都是图案没对齐发送端和接收端各算各的LLR初始化乱成一锅粥。后来我们直接把这部分定位为“必须共享同一份代码、同一组参数”问题就消失了。速率匹配看起来简单但它在链路里承担的是“收发双方约定窗口”的角色半点马虎不得。1.3 先把术语理顺打孔、删余、QUP都是什么中文文献里关于puncturing的翻译非常不统一有的叫打孔有的叫删余有的叫凿孔其实都是同一个动作把部分编码比特丢掉不发送。而QUP的完整拼写是Quasi-Uniform Puncturing中文一般译为准均匀打孔是一种打孔图案的构造方法。缩短则是另一条路线英文shortening。为了后面讨论清楚我整理了一张术语对照表英文中文常见译法核心含义puncturing打孔、删余、凿孔丢弃部分码字比特接收端对对应位置信息完全未知shortening缩短部分比特固定为已知值不发送接收端知道确定值quasi-uniform puncturing准均匀打孔让打孔位置尽量均匀分布的一种puncturing算法rate matching速率匹配把编码后的N个比特调整成目标长度E个比特的过程frozen bits冻结比特收发双方约定好的固定比特通常为0所以标题里的“打孔、删余”是一回事两个词不能当成两种技术“QUP”和“准均匀打孔”也是一回事它是打孔这个大类里的一个具体算法。整篇文章真正要讲的核心是两类删比特方式打孔和缩短以及打孔里最常用的一个均匀化算法QUP。顺带说一句如果你搜索“打孔”的时候蹦出来一堆PCB包地打孔、孔间距怎么来的讨论不用奇怪那是地过孔的问题解决的是回流路径和电磁辐射和信道编码里的打孔只是同名。判断是哪个领域看上下文里有没有LLR、编码比特这些词就行了。本文后面所有“打孔”都默认是信道编码语境下的puncturing。2. 打孔删余的实现原理和性能代价2.1 发送端删比特接收端填零LLR打孔的过程很直白。假设编码后得到序列x0, x1, ..., x_{N-1}现在要发送E个比特EN于是从N个比特里选择PN-E个位置把这些位置丢掉不传。被丢掉的这些位置组成的集合叫打孔集合通常用一个长度N的布尔掩码表示。发送端做的事情就是按照掩码把对应比特从发送队列里摘掉。接收端的情况要稍微转个弯。它虽然没收到这些被打孔比特的信号但译码器要求的输入长度是N不是E所以它必须为这P个位置“伪造”一个LLR。伪造的规则是填0。LLR0的含义是“P(0)P(1)0.5”也就是完全不知道这个比特是0还是1。这在信息论里等价于一个二进制删除信道信道容量为0。代码里常见的写法是for idx in punctured_positions: llr[idx] 0.0这一步做完译码器仍然按照N2^n的母码结构去译码只是其中P个位置是靠0 LLR“猜”的。这里就埋下了一个关键问题如果打孔位置恰好落在信息位上译码器等于没有任何观测就去猜一个信息比特错误率会显著上升。所以打孔后的信息位选择必须重新做这是打孔技术最核心的约束。2.2 打孔位置为什么牵一发动全身打孔不是随便删几个比特就行。极化码之所以叫“极化”是因为经过编码矩阵的递归混合后N个子信道的可靠度发生了分化一部分接近无噪声一部分接近纯噪声。信息比特应当放在可靠度高的子信道上冻结比特放在可靠度低的子信道上。打孔相当于把某些子信道变成容量为0的删除信道这会改变整个子信道可靠度的分布。最理想的做法是计算所有N个子信道的可靠度然后从可靠度最低的位置开始打孔打满P个为止。这样的性能最好因为被打掉的位置本来也不太可能放信息。但这里有个现实困难可靠度排序依赖信道参数和信噪比通常用高斯近似、密度演进或者巴氏参数来算计算量大而且不同信道条件下排序可能变化。协议实现不可能让每次传输都现场算一遍可靠度。所以工程界才希望有一种“不看信道参数也能直接生成图案”的方法。打孔图案的生成如果能只依赖N和P不依赖信道类型和信噪比发送端和接收端就能用一套简单的递推公式同步图案这是QUP出现的直接动机。理解了这个背景再看后面QUP的算法你会觉得它的每一步都很自然。2.3 随机打孔、连续打孔与均匀打孔的差别打孔图案的分布方式对性能影响很大我见过三种典型做法。第一种是随机打孔每次从N个位置里随机挑P个。实现最简单但性能抖动大。这批码字可能打孔位置均匀下一批又连成一片误码率时好时坏。在校验CRC时随机打孔可能会带来额外的帧间方差不好定位问题。第二种是连续打孔直接从开头或者结尾连续删掉P个比特。实现更简单适合某些特定码长但问题也很明显连续一段子信道全部没有观测在SC译码时这段未知区域的路径度量会快速恶化甚至导致路径选错形成误码平台。你可以想象一个队伍每隔几个人请一个人暂时离队队伍还能保持队形如果从同一位置把一队人全部拉走这个缺口就很难补了。第三种就是均匀打孔让打孔位置在整个码字上尽量铺开避免连续未知段。这种思路下译码器面对的是散布在序列里的一些“零信息点”而不是一大片黑洞路径度量更容易维持稳定。准均匀打孔QUP要做的就是把“尽量铺开”变成一个确定性的、可重复生成的算法让收发两端不需要随机数发生器也不需要可靠度排序就能得到同一个均匀图案。3. 缩短Shortening到底在做什么3.1 缩短的本质是“已知比特免传”缩短和打孔表面上看都是“少发一部分比特”但接收端的认知完全不同。打孔是“我不知道这个比特LLR置0”缩短是“我知道这个比特一定是0LLR置一个很大的正数”。看似只是初始化差了一个符号实际对译码的影响差别非常大。缩短位置因为接收端知道确定值这个位置的LLR相当于“确定置信度无穷大”对译码器来说是额外的已知信息不仅没有损失在某些情况下还能帮助其他比特正确译码。但缩短有个前提被缩短的位置必须约定为冻结位也就是收发双方都知道它固定为0。你不可能把一个信息比特缩短掉因为接收端会把那个位置当作确定的0去译码而发送端实际放的是信息比特两边直接矛盾。所以缩短的技术难点不在“删掉比特”而在“如何选择哪些位置可以被约定为已知冻结位”。从这个角度看缩短其实是“先把一部分子信道改成容量为1的已知信道再从剩下的信道里选信息位”。它操作的是信道分配不只是比特删除。这也解释了为什么缩短对性能的拖累比打孔小打孔引入的是删余信道容量为0缩短引入的是已知信道容量为1。一个是在拉低平均值一个是主动让别人顶上来。3.2 缩短和信息位选择必须联动如果你第一次实现缩短最容易犯的错误就是先算好母码的信息位集合再随便挑几个位置缩短。一旦缩短位置落在信息位上接收端就会把信息位当成已知0去译码错误率会非常离谱。正确的顺序必须反过来先确定缩短集合Sset把Sset对应的位置从信息位候选中排除对剩余的N-S个子信道重新计算可靠度从剩余位置里挑K个可靠度最高的位置放信息位。这个过程在代码里看起来只是把信息位选择表的输入参数换了一下但逻辑上非常关键。为什么必须重新计算可靠度因为把一个位置从编码输出里固定为已知值会改变相关子信道的等效噪声原本可靠度的排序在缩短后已经不再成立。只有把缩短位置排除后再算一遍才能保证选出来的K个信息位真正可靠。工程上为了省事可以离线把不同N、不同E、不同缩短集合对应的信息位表全部算好烧进ROM运行时查表。我们做FPGA验证时就是这么干的效果非常好。运行时只需要根据当前传输的E从ROM里读对应的信息位掩码和缩短掩码主控逻辑瞬间完成不用现场做排序和计算。3.3 什么场景用缩短什么场景用打孔打孔和缩短的适用场景有明显区别。简单说缩短适合删掉比特数比较少的场景也就是E很接近N、目标码率偏高的情况打孔适合删掉比特数比较多的场景也就是E明显小于N、目标码率偏低的情况。原因在于缩短位置必须是冻结位如果缩短数量太多会挤占信息位候选集合可用信道数量变少信息位选择的余地变小性能反而受损。打孔则更灵活删多删少都能通过调整图案来适配。可以做个直观对比维度打孔缩短接收端对被删位置认知完全未知LLR0已知固定值LLR大正数等效信道删除信道容量0已知信道容量1对性能影响较大较小信息位选择要求避开打孔位置缩短位置必须是冻结位必须排除适用场景删的比特多、低码率删的比特少、更高码率在5G NR协议里Polar码的速率匹配就是打孔和缩短混合使用根据E和N的关系决定哪些比特走缩短、哪些比特走打孔具体阈值以标准38.212为准。做算法预研的人可以先按“缩短优先、打孔兜底”的思路搭一套系统再去对照标准细化这样能快速理解两种手段各自的边界。4. 准均匀打孔QUP算法拆解4.1 QUP想解决的痛点是“可靠度依赖”前面反复提到理想打孔要按子信道可靠度排序来选位置但可靠度计算依赖信道参数工程上不方便。QUP的核心目标就是用一种“几何化”的方法只输入N和P就输出一份分布均匀的打孔位置集合。它不关心当前信道是AWGN还是瑞利衰落不关心信噪比是多少只要N和P确定图案就确定。这种特性非常适合协议实现因为图案可以在协议发布时就固定下来收发两端共用一份表或一段代码。QUP里的“准均匀”三个字很关键。它不是严格的等差分布而是让打孔位置从统计上看尽量均匀允许局部有些微小误差。之所以叫“准”就是因为N和P往往不是整除关系没法做到绝对等间隔只能做到“尽量均匀”。这种稍微抖动一点的位置对译码器来说已经足够比随机打孔稳定得多也几乎追平了按可靠度打孔的性能。4.2 一种可执行的准均匀打孔实现模糊的“尽量均匀”落到代码里可以有很多种写法。我平时仿真用的一个版本是这样把0到N-1这段位置分成P份每份取中间点如果中间点已经被人占了就顺延一位。这个逻辑非常好实现def quasi_uniform_puncturing(N: int, P: int): holes set() for i in range(P): pos (i * N N // 2) // P # 取第i段的近似中点 while pos in holes: pos (pos 1) % N # 撞车就顺延一位 holes.add(pos) return sorted(holes) # 示例母码长度N16打孔P6 print(quasi_uniform_puncturing(16, 6))运行这个例子得到的打孔位置会在0到15之间均匀铺开不会出现全部集中在开头或者全部集中在结尾的情况。每一步的逻辑都不复杂先按等差数列的方式把位置摊开再用顺延机制解决碰撞。这个版本是我在纯软件仿真和定点仿真里都觉得比较顺手的一种写法如果你做学术复现应以标准QUP论文里的递推伪代码为准两者的动机和结果非常接近但工程代码追求的是“可读、可断点、可测”不需要完全复制论文行数。需要提醒的是QUP在打孔数量P偏大时也就是E明显小于N时效果比较好当P小到接近N的时候步进快变成1打孔图案几乎铺满所有位置就显得很冗余这时候不如直接用缩短。工程上一般是“能缩短就缩短必须打孔才用QUP”。4.3 QUP和缩短的配合以及性能体会我强烈建议把QUP和缩短当作一套组合拳而不是对立方案。具体做法是根据目标E先判断需要删掉多少比特再决定删的方式。如果删得少用缩短把位置固定成已知0如果删得多用QUP把位置均匀打掉。极端情况下还能混合一部分位置缩短、一部分位置打孔。接收端初始化时对缩短位置填大正数对打孔位置填0两类位置互不影响。我在一个AWGN模型里对比过随机打孔、连续打孔和QUPN128K64打孔P32。随机打孔和连续打孔的误码平台大概在0.1左右就压不下去QUP可以把误码率继续往下压到0.01以下。差距的主要来源就是QUP把未知LLR位置打散了SC译码器的路径度量不会在连续未知段上突然崩掉。这只是简单模型下的体会不代表所有码长和信道下的数值结论但方向很说明问题打孔图案的均匀性对极化码译码的稳定运行非常关键。5. 工程实操参数计算、译码器适配和避坑手册5.1 参数计算示例N64E48约定几个符号K是信息位个数含CRCN是母码长度E是速率匹配后的传输长度。假设一个具体配置N64K32E48。因为EN需要删掉N-E16个比特。此时到底用打孔还是缩短要由协议或算法决策逻辑决定如果走打孔路径那么打孔数P16用QUP生成16个打孔位置信息位从剩余48个候选位置里按可靠度重新排序选32个。接收端这边的处理逻辑是正常接收48个位置的LLR打孔的16个位置填0拼成完整的64长LLR序列再送进Polar译码器。注意译码器的输入长度永远等于母码长度N不是E。很多新手在这里犯迷糊既然只传了48个比特为什么译码器还要处理64个因为Polar码的译码结构是建立在2的幂母码上的你必须把缺失位置的信息补上哪怕补的是“完全不知道”的0也要保持母码结构完整。如果你走缩短路径S16就把16个缩短位置固定为0接收端把这16个位置的LLR填成大正数信息位从另外48个位置里选。两条路径在初始化之后的译码流程完全一致差别只在这批LLR到底填0还是填大正数。所以速率匹配模块的设计质量直接决定译码器输入端是“信息完好的母码”还是“一团浆糊”。5.2 信息位选择顺序错了是最大的坑我要单独给信息位选择这个环节写一节因为它是我见过踩坑最多的地方。很多教程给了一个现成的“母码信息位表”然后让读者无论E怎么变都用同一张表。这在小规模、E刚好等于2的幂时没问题但只要E不是2的幂就一定会踩坑。正确的顺序必须是先确定打孔/缩短图案再选信息位。也就是“图案先行选位在后”。原因很简单打孔/缩短改变了子信道的等效质量原来排序好的信息位可能落到了被打掉的位置上。打孔场景下那些位置LLR0译码器等于在没有任何观测的情况下猜信息比特缩短场景下那些位置被强行当作已知0如果里面真有信息比特译码器直接输错。工程上我见过三种对应策略。第一种是在协议里固定好打孔/缩短图案离线算好信息位表查表即可。第二种是每次传输前根据E动态算这种方式灵活但开销高适合算法验证。第三种是妥协方案信息位表不随E变化只选择绝对可靠的位置当信息位一次性预留出足够冗余。系统级实现一般不推荐第三种它会浪费信道容量。我们最终采用的是第一种提前把所有N、E组合的表离线算好、固化到储存器里运行时只查表既快又稳。5.3 LLR初始化的三个细节LLR初始化这步看起来只是一行赋值实际上有三个细节值得反复检查。第一打孔位置必须填0不能随便填一个小数。如果你在代码里把打孔位置写成0.01接收端等于偏向某个值译码器会跟着产生系统性偏差。第二缩短位置不要真的填float(inf)在定点化硬件里无穷大会溢出工程上填一个大数比如1e6表示“置信度足够大”即可。第三LLR的符号必须和调制映射约定保持严格一致。比如约定0映射为1、1映射为-1那么已知为0的缩短位置LLR必须是正数写反了性能会直接崩。一个比较稳的软件仿真初始化写法是llr np.zeros(N) llr[received_positions] demod_llr # 正常位置放解调后的LLR llr[punctured_positions] 0.0 # 打孔位置完全未知 llr[shortened_positions] 1e9 # 缩短位置已知为0填大正数我建议新手先跑一个N8的最小用例把三类位置的LLR打印出来肉眼检查一遍再往上扩展。很多看似神秘的编译码性能问题最后都出在这三行赋值上。5.4 常见问题速查表我在不同项目里反复见过同一批问题整理成速查表能帮你少走不少弯路现象可能原因处理建议译码输出完全乱码打孔/缩短图案收发不一致检查两侧是否用同一套N、E输入生成图案误码平台居高不下打孔位置覆盖了信息位改为“先定图案再选信息位”用了缩短反而更差缩短位置被当成了信息位缩短位置必须从信息位候选中剔除LLR填了INF导致异常定点平台不支持无穷大用大数饱和替代如1e6性能忽好忽坏随机打孔导致帧间方差大换QUP或固定图案N64、E32正常E56崩溃没有按E重新选择缩短/打孔靠近N用缩短远离N用打孔这张表基本涵盖了我在调试Polar码速率匹配时遇到的大部分问题。其中“性能忽好忽坏”最隐蔽因为码率没变但随机打孔每一帧的图案都在变产生的随机性差异让测试结果非常不稳定。改成QUP固定图案之后帧与帧之间行为一致问题定位就简单多了。5.5 此“打孔”非彼“打孔”最后再回应一下开头提到的PCB包地打孔。数字电路设计里包地打孔的孔间距一般按经验法则沿着包地铜皮每隔λ/20以内打一个地过孔目的是给返回电流提供一个低阻抗路径控制电磁辐射。而极化码里的打孔关心的是被打孔位置在码字序列里的分布它决定的是译码器输入端的LLR格局。一个在铜皮上做文章一个在编码比特上做文章只是中文都叫“打孔”。如果你是想找极化码资料结果被“打孔”这个词引到了PCB文章建议搜索的时候换成“puncturing”或者“删余”更精准。如果你本来是做高速数字设计的工程师意外进了这个坑那你要去找的是地过孔噪声仿真而不是在这里看LLR初始化。两个领域共享一个动词算是行业里一件挺有意思的小事。一点真实的调试感受写在最后个人经验。我在实际项目里受益最大的一个习惯是把速率匹配和信息位选择当成一个整体去设计。很多系统失败不是因为编译码器写得差而是因为打孔图案、信息位选择、LLR初始化这三件事被拆开单独优化结果互相打架。另一个实用技巧是所有打孔/缩短图案都提前离线算好存表运行时查表而不是现场计算这样既快又稳。如果你正在自己搭Polar码仿真建议先从N16或N32的小规模用例跑通这条链路再逐步加大码长会比直接上复杂配置更顺畅。
返回列表