我目前正在撰写关于 turbo 解码器的多线程软件实现的计算机科学论文。基本问题如下:
- 令 (y1, ..., yn) 为通过通道接收的噪声比特序列。两个 SISO 解码器并行工作(每个解码器接收序列的第一位和 {1,2} 中的奇偶校验位 y1j, j) - 目标是计算 LLR(对数似然比,它提供有关概率的信息当前位是 0 或 1),然后将其馈送到另一个 SISO 解码器以进行下一次迭代。假设接收到的位被分成更短的数据帧。(SISO 表示软输入、软输出,因为每个解码器都会得到输入中比特概率的估计并输出自己的估计)
LLR 的每次计算都需要大量串行化的 ACS 操作,具体取决于每帧中的位数(以及编码器用于为初始序列制作奇偶校验位的位数)。这种计算可以与这些嵌套的循环相加(对于两个并行工作的 SISO 解码器中的每一个):
for i=1 to N_FRAMES:
for j=1 to N_ELS_FRAMES:
for k=1 to 4:
for l=1 to N_STATES:
do_ops()
请注意,上述循环实际上并未出现在算法中,但它确实与每次迭代所做的操作非常匹配。通常,N_STATES 约为 8 或 16(这取决于每个编码器用于计算输入序列上的奇偶校验位的位数),并且 do_ops() 需要求和、最大值和向量归一化。
起初,我尝试使用 Jython 进行实现,但结果非常令人沮丧:上面嵌套循环中的操作需要 - 使用多线程版本 - 大约 20 分钟(!),并且位数适中(~2 百万)。
另一方面,使用该算法的单线程版本,Java 实现需要约 1 秒和约 4 mil 位。
为什么会有如此巨大的差异?