《Comparing Different Decodings for Posit Arithmetic》(一)
好的,下面按照你的指令用中文系统分析这篇论文《Comparing Different Decodings for Posit Arithmetic》:
1. 论文主要内容与研究方向
本论文关注Posit算术(Posit Arithmetic)中不同解码方式对硬件实现效率的影响。
研究方向是:
- 分析传统的“符号-幅值(Sign-Magnitude)”解码方式与一种较新的“两补(Two’s Complement)”解码方式;
- 比较这两种解码方式在Posit加法器、乘法器设计上的硬件资源占用、延迟、功耗和能量效率;
- 通过ASIC综合,定量评估每种解码策略对硬件实现性能的影响。
最终目标是探索更适合硬件优化的Posit解码与运算方法。
2. 研究方法介绍(包含截图)
研究方法主要包括:
- 提出两种解码方式:
- 符号-幅值(Sign-Magnitude)解码(传统方法,类浮点数处理)
- 两补(Two's Complement)解码(新方法,负数直接解码,无需取绝对值)
- 设计Posit加法器与乘法器,分别基于上述两种解码方式。
- 模块级别综合比较:分别对Decoder、Encoder、Adder、Multiplier模块进行独立综合,评估面积、功耗、延迟和能量。
- 完整算术单元综合比较:对整体加法器和乘法器进行综合,并与已有开源实现(PACoGen、Flo-Posit、MArTo)进行对比。
📷 截图(原文对应的部分):
-
Posit解码方式介绍:
-
组件硬件性能比较(Decoder部分):
3. 研究结果分析
主要对比结果总结:
- Decoder模块:使用Two's Complement解码,面积下降约34%,功耗下降约55%,能量下降约73%。
- Encoder模块:面积下降约33%,能量下降约50%。
- 加法器核心(Adder Core):面积下降约9%,能量下降约16%。
- 乘法器核心(Multiplier Core):面积稍有增加(面积+7%,功耗+7%),但延迟降低,能量下降。
完整算术单元对比(以32位Posit〈32,2〉为例):
- 加法器:面积减少22.7%,功耗减少32.9%,延迟减少10.22%,能量减少39.77%。
- 乘法器:面积减少8.17%,功耗减少7.72%,延迟减少21.54%,能量减少27.6%。
被引用并对比的其他项目及开源地址:
- PACoGen(传统解码):PACoGen GitHub地址
- Flo-Posit(传统解码):Flo-Posit GitHub地址
- MArTo(新式解码,PIF格式):MArTo GitLab地址
4. 论文出处及期刊/会议等级
- 出处:收录于CoNGA 2022(Conference on Next Generation Arithmetic)会议论文集,Lecture Notes in Computer Science (LNCS)系列,卷号13253,Springer出版。
- 会议等级查询:
- CoNGA 不是CCF推荐会议。
- LNCS属于Springer B类会议论文集,整体水平中等偏上。
- 会议主题新颖,偏向交叉领域(算术电路、机器学习低精度运算硬件优化)。
5. 论文是否有开源代码
本论文本身没有直接给出开源工程地址。
但是文中提到的对比实现(如Flo-Posit和PACoGen)是开源的,地址见上节。
6. 相关原文出处标注
部分重要分析所对应的原文出处示例如下:
-
提出两种解码方式,见论文第2章:
"At the time of writing this paper, two main different ways of understanding how posit bit strings represent real values have been proposed..."
-
硬件对比实验,见论文第4章:
"To have a better understanding of how the different ways of decoding posit numbers impact on the hardware resource utilization..."
-
总结结论,见论文第5章:
"Synthesis evaluations show that posit units based on classical float-like decoding schemes require generally more hardware resources..."
好的,下面我将更深入、详细地从数学本质、硬件实现、优缺点、适用场景四个方面,全面分析这篇论文中提出的两种Posit解码方式:
🔵 1. 符号-幅值(Sign-Magnitude)解码
数学本质
传统的Posit解码与浮点数IEEE 754风格一致:
-
把Posit的最高位作为符号位。
-
剩余的比特串表示数值的绝对值,按如下公式解释:
[
X = (-1)^s \times (\text{useed})^k \times 2^e \times (1+f)
]
其中:- ( s ):符号位
- ( k ):由regime字段计算出的值
- ( e ):无符号指数
- ( f ):小数部分(fraction)
如果符号位是负的((s=1)),要先对整个数取二进制补码(Two's Complement),然后再解析出(k, e, f)。
硬件实现流程
- 解码(Decoding)阶段:
- 判断符号,如果为负,需要取补码;
- 提取regime(通过leading zero/one count),再提取指数(e)、小数(f);
- 运算(Computation)阶段:
- 以绝对值进行加减乘除;
- 运算结束后,再根据符号位确定最终结果的正负;
- 编码(Encoding)阶段:
- 重新根据(k, e, f)组合;
- 如果是负数,需要再次取补码编码。
优点与缺点
项目 | 内容 |
---|---|
优点 | 兼容IEEE 754浮点数设计思路;容易迁移现有浮点单元;早期工具链和设计成熟。 |
缺点 | 解码和编码需要两次补码(取绝对值 & 写回); 影响解码器延迟和能耗; 不适合极低功耗或面积受限场景。 |
适用场景
- 想快速将浮点单元迁移到Posit;
- 对延迟、功耗要求不极端苛刻的应用;
- 原有EDA、硬件库(如浮点加法器、乘法器)想重用。
🔵 2. 两补(Two's Complement)解码
数学本质
在这种解码方式下:
- 不需要取绝对值;
- 直接把符号隐藏在小数部分(fraction)里,用二补码格式表示正负。
解码公式变为:
[
X = (\text{useed})^{\tilde{k}} \times 2^{\tilde{e}} \times (1 - 3s + f)
]
变化点:
- (\tilde{e}):原指数(e)与符号(s)按位异或(XOR);
- (\tilde{k}):regime符号也随(s)变化;
- 小数(f)通过增加或减少固定偏移(1或-2)表达正负。
注意:
- 正数时,小数范围 ([1, 2));
- 负数时,小数范围 ([-2, -1))。
而且负数的小数部分是高位10开头,正数是高位01开头。
硬件实现流程
- 解码(Decoding)阶段:
- 直接根据符号调整regime和指数,无需补码;
- 小数部分根据符号自动分配到对应的二补码格式;
- 运算(Computation)阶段:
- 直接以有符号数方式运算;
- 无需事先比较大小,无需取补码,无需补偿符号;
- 编码(Encoding)阶段:
- 直接组合各个字段;
- 只需要简单判断正负,无需取补码。
优点与缺点
项目 | 内容 |
---|---|
优点 | 解码和编码无需取补码; 延迟降低,面积功耗大幅下降; 加法器和乘法器的符号处理自然嵌入,不用额外逻辑; 适合低功耗、低延迟场景。 |
缺点 | 算术核(尤其是乘法器)要处理宽得多的有符号数(四个整数位); 实现逻辑更复杂(需要关注负数乘积超出情况,如−2×−2); 对传统EDA工具兼容性稍差。 |
适用场景
- 需要极致优化面积、功耗、延迟的应用(如物联网、边缘AI);
- Deep Learning领域需要大量低位宽乘加(MAC)运算的应用;
- 有定制硬件设计能力的团队。
🔵 总结对比
比较维度 | 符号-幅值解码 | 两补解码 |
---|---|---|
符号处理 | 需补码处理 | 无需补码,符号自然编码 |
解码复杂度 | 高 | 低 |
编码复杂度 | 高 | 低 |
算术核复杂度 | 低(逻辑简单) | 略高(需处理signed multiply/normalize) |
面积功耗 | 大 | 小 |
延迟 | 长 | 短 |
易用性 | 高(兼容浮点) | 较低(需特殊设计) |
适用场景 | 通用浮点加速器改造 | 极限优化AI/IoT硬件 |
很好!这次我将使用严格符合 Posit〈8,1〉 格式(8位宽,总是正好8位)的两个例子,
重新、标准、详细地推导 符号-幅值解码 和 两补解码 的全过程。
🧩 严格版案例设定
例子1(正数):
编码(8位二进制):0 1110 100
对应:
- 符号位:0
- Regime字段:1110(连续3个1,后跟0)
- 剩余位:1(exponent)+ 00(fraction)
例子2(负数):
编码(8位二进制):1 0001 110
对应:
- 符号位:1
- Regime字段:0001(连续3个0,后跟1)
- 剩余位:1(exponent)+ 10(fraction)
✏️ 正确推导:例子1【正数 0 1110 100】
符号-幅值解码(传统方法)
步骤如下:
-
符号位 (s = 0)(正数,无需取补码)
-
Regime字段
1110
- 3个连续1
- (k = l - 1 = 3 - 1 = 2)
-
Exponent字段
- 接下来1位:
1
- exponent = 1
- 接下来1位:
-
Fraction字段
- 剩下2位:
00
- fraction =
0
- 剩下2位:
-
计算公式:
useed (= 2{21} = 2^2 = 4)
[
X = (-1)^0 \times 4^2 \times 2^1 \times (1 + 0)
]
[
X = 1 \times 16 \times 2 \times 1 = 32
]
✅ 结果:32
两补解码(Yonemoto方法)
步骤如下:
-
符号位 (s=0)(正数)
-
Regime字段:
1110
- 3个连续1
- (k = l - 1 = 2)
-
Exponent字段
1
- exponent = 1 XOR 0 = 1
-
Fraction字段
00
→ fraction = 0
-
计算公式:
[
X = 4^2 \times 2^1 \times (1 - 3s + f)
]
[
X = 16 \times 2 \times (1 - 0 + 0) = 32
]
✅ 结果:32
✏️ 正确推导:例子2【负数 1 0001 110】
符号-幅值解码(传统方法)
步骤如下:
-
符号位 (s=1)(负数)
-
取补码(除了符号位,后7位):
0001110
- 取反:
1110001
- 加1:
1110010
-
Regime字段(从补码后)
1110
- 3个连续1
- (k = l-1 = 3-1 = 2)
-
Exponent字段
0
- exponent = 0
-
Fraction字段
10
- fraction =
10
→ 0.5
-
计算公式:
useed (= 4)
[
X = (-1)^1 \times 4^2 \times 2^0 \times (1 + 0.5)
]
[
X = -16 \times 1.5 = -24
]
✅ 结果:−24
两补解码(Yonemoto方法)
步骤如下:
-
符号位 (s=1)(负数)
-
Regime字段
0001
- 3个连续0
- (k = l - 1 = 3 - 1 = 2)
-
Exponent字段
1
- Exponent 1 XOR 符号位1 → 1 ⊕ 1 = 0
-
Fraction字段
10
→ fraction = 0.5
-
计算公式:
[
X = 4^2 \times 2^0 \times (1 - 3\times1 + 0.5)
]
[
X = 16 \times 1 \times (1-3+0.5) = 16 \times (-1.5) = -24
]
✅ 结果:−24
🔥 总结复核
例子 | 符号-幅值解码结果 | 两补解码结果 | 最终正确性 |
---|---|---|---|
0 1110 100 | +32 | +32 | ✅ |
1 0001 110 | -24 | -24 | ✅ |
✔️ 正式推导结束!这次保证是严格8位、标准Posit〈8,1〉格式下的分析。
要不要我接着用这两个例子,继续给你演示一下加法或乘法硬件流程对比?比如计算:
- (32 + (-24))
- (32 \times (-24))
太好了!下面我就继续用上面两个严格合法的 Posit〈8,1〉 编码例子:
0 1110100
→ +321 0001110
→ −24
来演示:
✅ 任务:计算 +32 + (−24)
,即 结果为 +8
我们将分别从符号-幅值解码和两补解码两个角度,推导出该加法运算在硬件中的执行流程差异。
🔵 一、符号-幅值解码路径(传统方式)
💡 总思路:
- 先对每个 Posit 编码进行解码:提取 (k, e, f)
- 对负数先取补码再解码(需要前处理!)
- 变为绝对值运算:做对齐(exponent)、移位、相加
- 得到结果后,再编码(若为负需补码)
步骤:
Step 1: 解码两个数
-
+32:
- (k_1 = 2), (e_1 = 1), (f_1 = 0)
- (val_1 = 4^2 \times 2^1 \times (1+0) = 32)
-
−24:
- 补码后提取 (k_2 = 2), (e_2 = 0), (f_2 = 0.5)
- (val_2 = - (4^2 \times 2^0 \times 1.5) = -24)
Step 2: 统一 exponent
-
(e_1 = 1), (e_2 = 0),所以把 (val_2) 的 significand 右移一位
(val_2_sig = 1.5 → 0.75)
Step 3: 相加
[
val_1 = 32,\quad val_2 = -24 → 32 + (-24) = 8
]
Step 4: 编码为新的 Posit〈8,1〉
-
(8 = 4^1 \times 2^1 \times 1) → (k = 1, e = 1, f = 0)
-
构造编码:
- 符号位:0
- Regime:
110
(2个1 + 终止0,表示k=1) - exponent:
1
- fraction:
00
-
最终编码:
0 110 1 00
(共8位)
✅ 结果编码:01101100
🔴 二、两补解码路径(Yonemoto方法)
💡 总思路:
- 两个Posit直接解码,无需补码
- 所有运算在有符号fixed-point空间进行
- 符号嵌入了小数中:±(1~2) 的区间
- 不需要后期再转换符号,也不需要判断大小再决定谁减谁
步骤:
Step 1: 解码两个数
-
+32:
- (k_1 = 2), (e_1 = 1), (f_1 = 0), (sig_1 = 1)
- 结果 (val_1 = 4^2 \times 2^1 \times (1 + 0) = 32)
-
−24:
- (k_2 = 2), (e_2 = 0), (f_2 = 0.5), (sig_2 = -2 + 0.5 = -1.5)
- 结果 (val_2 = 4^2 \times 2^0 \times (-1.5) = -24)
Step 2: 加法
直接相加:
[
32 + (-24) = 8
]
Step 3: 反向编码 Posit〈8,1〉
- 与上面一样,值为8 = (4^1 \times 2^1 \times 1)
- 构造 Posit 编码:
- 符号:0
- Regime:
110
(k=1) - exponent:
1
- fraction:
00
✅ 编码仍然是:01101100
🔧 硬件路径对比总结
操作阶段 | 符号-幅值(传统) | 两补(Yonemoto) |
---|---|---|
解码前处理 | 需负数取补码(多1次加法+取反) | 不需要 |
对齐处理 | 需比较大小、确定对齐方向 | 不需要,用signed addition直接加 |
符号处理 | 需在结果阶段判断结果正负并做补码写回 | 内嵌于运算中 |
加法器逻辑 | 无符号加法器+比较逻辑 | 有符号加法器(支持负significand) |
编码后处理 | 可能需再次补码写回 | 无需符号变换 |
🔺传统方式更“浮点式”,而两补方式更“整数式”,逻辑路径更短。
✅ 结论
- 对于
+32 + (-24)
,无论哪种解码方式,结果正确性完全一致; - 但从硬件实现角度看,两补解码省去了两次补码和一次大小判断对齐,整体路径更短、面积更小、功耗更低;
- 论文中正是基于这种对比,得出两补方案适合更高能效的设计。
这个问题问得非常关键。你提到的这一步:
Step 2: 统一 exponent
( e_1 = 1 ), ( e_2 = 0 ),所以把 ( \text{val}2 ) 的 significand 右移一位
( \text{val}{2,\text{sig}} = 1.5 \rightarrow 0.75 )
🧠 这一步是做什么的?
这一步是 浮点或Posit加法运算中最核心的步骤之一,称为:
✅ 对齐操作(alignment)
它的作用是:
让两个要相加的数具有相同的指数(exponent),从而可以直接将它们的小数部分(significand)进行相加或相减。
🔍 为什么要做对齐?
浮点数或Posit数采用如下表示方式:
[
X = \text{sign} \times \text{base}^{\text{exponent}} \times \text{significand}
]
如果两个数的 exponent 不同,比如:
- ( X_1 = 2^1 \times 1.0 = 2 )
- ( X_2 = 2^0 \times 1.5 = 1.5 )
你不能直接把 1.0 和 1.5 相加,因为它们属于不同的“尺度”,就像“2元”和“2角”不能直接相加一样。
✅ 怎么做对齐?
把指数小的数“右移”它的小数部分,让它的指数变得和另一个数一样大。
回到你提的情况:
- ( e_1 = 1 ),( \text{sig}_1 = 1.0 )
- ( e_2 = 0 ),( \text{sig}_2 = 1.5 )
我们把 ( \text{sig}_2 ) 右移 1 位(相当于除以2):
[
\text{sig}_2 = 1.5 \rightarrow 0.75 \quad \text{并升 exponent } e_2 \rightarrow 1
]
这样,两个数就都处于 (2^1) 的尺度下:
[
X_1 = 2^1 \times 1.0 = 2 \
X_2 = 2^1 \times 0.75 = 1.5
]
这时候就可以直接把 significand 相加了:
[
1.0 + 0.75 = 1.75,\quad \text{结果就是 } 2^1 \times 1.75 = 3.5
]
🔁 在硬件中,这对应什么操作?
- 比较两个exponent大小
- 选择小的那一个数的 significand
- 使用移位器(shifter)右移它的值
- 然后再将两个 aligned significands 相加
这一步的存在是浮点加法比整数加法复杂的根源之一。
💡 在Posit里也有这一步?
是的,在符号-幅值解码(传统浮点式)Posit加法中仍然需要这个步骤。
但在两补解码(Yonemoto方案)里,因为significand是有符号数(已包含符号),所以你可以直接做加法,不再需要对齐逻辑,这就是它能节省逻辑面积和延迟的关键点之一。