λmem.ac

II. Arithmetic

Numbers

Radix-Based System

  • 最高有效位(Most Significant Digit, MSD)An1A_{n-1}
  • 最低有效位(Least Significant Digit, LSD)AmA_{-m}

Binary Representations

对于正数而言,原码=反码=补码;而对于负数:

  • 原码(sign-magnitude):符号位为 1,其余位和其相反数的表示相同。
  • 反码(1’s complement code):在其相反数的表示的基础上取反。
  • 补码(2’s complement code):在其相反数的表示的基础上取反并 + 1。

另外,一些场合(比如:IEEE754 标准浮点数的指数部分(阶码))还会用到移码:

  • 移码(biased notation):统一加上一个固定常数并用无符号整数的方法表示。
原码表示和补码表示的差异

原码和补码下表示正数都是不变,且符号位为 00。但是原码表示下的负数仅符号位为 11,其余为是数值绝对值的二进制表示;补码表示下的负数会取反并加一。

ALU

1-bit ALU

AND 和 OR 的功能可以直接使用对应的电路门。

加法功能通过 一位全加器(1-bit full adder) 实现(后面直接用“方括号内加号”的组合来表示全加器):

S=ABCinCout=BCin+ACin+AB\begin{aligned} S &= A \oplus B \oplus C_{\text{in}} \\ C_{\text{out}} &= B \cdot C_{\text{in}} + A \cdot C_{\text{in}} + A \cdot B \end{aligned}

为了实现减法器,多一个 Binvert 输入控制(而不是通过 Operation 控制)是否需要将输入 B 取反并将第一个 CarryIn 设 1,因为减一个数就相当于加上这个数的补码。

这样的 1-bit ALU 已经实现了最基本的 AND、OR、加法、减法四种功能。

Complete ALU

可以直接把 1-bit 连接起来拼成一个 nn 位的 ALU。这样的设计虽然简单,但是速度慢。

真实的 ALU 每个部分都应是用更快的电路实现的,最后通过一个 MUX 实现选择。

  • Zero detection:给输出加一个或非门,即可作为一个判断结果是否为 0 的输出。

Overflow Detection

两个数的和或差可能超过可以被表示的范围,这种情况下就是发生了 溢出(overflow),ALU 可以支持溢出检测。

  • 对于有符号数运算,正数和正数相加得到负数,或者负数和负数相加得到负数,就可以认为发生了溢出。这里正数包括 00
  • 对于无符号数运算,两个数相加的结果小于其中任何一个数,就可以认为发生了溢出。

一般来说,实现上我们需要将结果扩展一位,并和最高位综合进行检测。

一般溢出条件
一般溢出条件

Comparison

两个计算时会发生 overflow 的数也可以进行比较,比如 127-128。这时可以通过符号位得到结果,而不用担心减法产生溢出。

对应指令 slt rd, rs, rt(set on less than)

行为:如果 rs < rt,则设 rd 为 1,否则设 rd 为 0。(rd 除了最低有效位,其他位都为 0)

Faster Adders

  • 所有的组合逻辑都可以通过二级逻辑表示(但是其硬件代价可能极高)。

Carry Lookahead Adder

超前进位加法器(Carry Lookahead Adder, CLA) 通过“超前进位”的方式改进 行波进位加法器(Ripple Carry Adder, RCA) 中后一位必须等待前一位进位结果的问题。关于加法中的进位,可以视为两种条件:

  • 生成(generate):记作 Gi=AiBiG_i=A_i \cdot B_i,即第 ii 位两位相加本身是否会产生进位。
  • 传播(propagate):记作 PiP_i,接到低位的 GjG_j 一起,用来表示进位逐步上传的过程。
4 bit CLA
4 bit CLA

CLA 的底层也可以不是 1 bit Adder,而是另一个 CLA,如两层 4 bit CLA 嵌套就可以实现 16 bit 加法器。

16 bit CLA
16 bit CLA

Carry Select Adder

进位选择加法器(Carry Select Adder, CSA) 通过在加法器中添加一个选择器,在计算时同时计算两种情况,然后根据进位选择结果。

CSA 和 CLA 没有一定优劣,在实际优劣中,我们可以根据对性能快还是面积小的需求选择合适的加法器。

Multiplier

Unsigned Multiplication

Approach 1

按照竖式乘法的算术法则实现。

具体过程:执行以下步骤 64 次:

  1. 判断 Multiplier 寄存器的最低位是否是 1:
  2. 如果是,则将 Multiplicand 寄存器的值加到 Product 寄存器里;
  3. 如果否,进入下一步;
  4. 将 Multiplier 寄存器的值右移一位(这是为了不断拿出每一位,相当于在枚举 Multiplier 的每一位),将 Multiplicand 寄存器的值左移一位(对应于和 Multiplier 的第几位乘得到的位移,具体参考上面的链接内容);
  5. 判断是否做满 64 次,决定是否终止;

Approach 2

只在 Product 的左半部分应用加法,这样 ALU 的大小可以减半。

具体过程:执行以下步骤 64 次:

  1. 判断 Multiplier 寄存器的最低位是否是 1:
  2. 如果是,则将 Multiplicand 寄存器的值加到 Product 寄存器的左半部分里;
  3. 如果否,进入下一步;
  4. 将 Multiplier 寄存器的值右移一位,将 Product 寄存器的值右移一位;
  5. 判断是否做满 64 次,决定是否终止;
Why 129 bits?

在执行循环的第 2 步时,可能会有加法进位的问题,这一问题也同样会出现在下面的 Approach 3。如果认为加法和右移的过程不是同时的,那么 Product 寄存器就需要有额外的 1 位用来存储进位

Approach 3

把 Multiplier 寄存器和 Product 寄存器进行合并,每次只有一个寄存器需要右移。

具体过程:先将 Multiplexer 放到 Product 寄存器的低 64 位,然后执行以下步骤 64 次:

  1. 判断 Product 寄存器的最低位是否是 1:
  2. 如果是,则将 Multiplicand 寄存器的值加到 Product 寄存器的左半部分里;
  3. 如果否,进入下一步;
  4. 将 Product 寄存器的值右移一位;
  5. 判断是否做满 64 次,决定是否终止;

Signed Multiplication

上面的乘法不能用补码,只能先进行绝对值的乘法,再把符号位单独处理并应用到结果上。

使用 Booth’s Algorithm 可以实现基于补码的乘法(仅了解)。

  • 注意 算术右移(arithmetic shift right) 时应保持符号位不变,最高位补符号位。

Parallel Multiplier

我觉得这个图放在这里本身就有问题。

(TBD:我不理解!)

Division

TBD

Unsigned Division

Approach 1

Approach 2

Approach 3

Faster Division

与乘法不同,除法不能通过循环展开来并行。一些其它的加速方法如 SRT Division 仍需要多步。

Floating Arithmetic

IEEE 754 Representation

  • 符号位:一般来说正数就是 0 负数就是 1。
  • 尾数:去除符号位后应被移到 1.xxxxx1.\text{xxxxx} 的形式,所以最高位的 1 可以被省略(称为 hidden 1)。
    • 对于一些不使用 hidden 1 策略的表示方式则移到 0.1xxxxx0.1\text{xxxxx} 的形式,注意不同的方式会影响阶码的值。
  • 指数:用移码表示,单精度浮点数的 偏移(bias)127127,双精度浮点数的偏移为 10231023(刚好是范围的一半)。
(1)sign(1+significand)2exponent-bias(-1)^\text{sign} \cdot (1+\text{significand}) \cdot 2^{\text{exponent-bias}}
0.75-0.75 的单精度、双精度表示

一些特殊值:

  • NaN:Exponent = 111…1, Fraction ≠ 000…0
  • Infinity:Exponent = 111…1, Fraction = 000…0
单精度、双精度表示法的范围和精度

Floating Point Addition

  • Step 1:对齐(alignment),即让两个数的指数相同,不能表示的位(被移出的位)将被舍弃。这里还需要补上前面被省略掉的尾数最高位。
  • Step 2:将对齐后的小数部分进行相加。
  • Step 3:规格化(normalization),将其移位直到符合标准。
  • Step 4:上溢(overflow)下溢(underflow) 检测。
  • Step 5:舍入(rounding),将结果舍入到最接近的值。
  • Step 6:还需要再进行一次规格化,因为 rounding 时可能产生了进位。

Round Modes

  • guard bit:最低有效位
  • round bit:最低有效位右边的第一位
  • sticky bit:只要 round bit 右边出现过非零位,就将 sticky bit 置 1。在加法的右移过程中,可以记录是否有 1 被移出,从而能够实现 “round to nearest even”。

Floating Point Multiplication

  • Step 1:add exponents
  • Step 2:multiply the significands
  • Step 3:normalise
  • Step 4:over/under-flow detection
  • Step 5:rounding
  • Step 6:sign(依据输入数的符号确定结果的符号)

Comments

2
Y
Yuki2 days ago
The √dₖ intuition finally clicked for me here — the "keeps logits calm" framing is so much better than the papers.
K
Kenji5 days ago
Would love a follow-up on positional encodings! Bookmarking this.