Division by Invariant Integers using Multiplication

news2025/2/25 9:10:35

在处理器中,整数除法的成本通常是整数乘法的几倍:

  • 流水线式的组合乘法器通常在不到10个周期内完成操作;
  • 而对于整数除法则没有硬件支持,或者使用的迭代除法器比乘法器慢几倍。

表 1.1 比较了一些处理器上乘法和除法的时间。这张表展示了乘法和除法时间差距的增长趋势。
在这里插入图片描述因此, Division by Invariant Integers using Multiplication 中提出了使用整数乘法进行任意非零整数常数和运行时不变量之间除法的算法。

文档 4. Instruction tables 中记录了更广泛的处理指令性能,其中 Intel IceLake 处理器的乘除法指令延迟和吞吐倒数如下表所示:
在这里插入图片描述
可以看出,在现代 CPU 处理器上除法开销大的情况并未发生改变。NVIDIA 和 AMD GPU 均不支持整数除法指令,CUDA C++ Programming Guide 5.4.1. Arithmetic Instructions 中指出整数除法和取模运算可能会编译出多达20条指令,建议开发者在某些情况下使用位运算来替代。很多深度学习框架和加速库中均采用论文所提出的算法来加速常量除法运算。

2 Mathematical notations

x x x 是一个实数。那么

  • ⌊ x ⌋ \lfloor x\rfloor x 表示不超过 x x x 的最大整数,
  • ⌈ x ⌉ \lceil x \rceil x 表示不小于 x x x 的最小整数。

T R U N C ( x ) \mathrm{TRUNC}(x) TRUNC(x) 表示 x x x 的整数部分,向零取整。形式上,

  • 如果 x ≥ 0 x \ge 0 x0,则 T R U N C ( x ) = ⌊ x ⌋ \mathrm{TRUNC}(x) = \lfloor x\rfloor TRUNC(x)=x
  • 如果 x ≤ 0 x \le 0 x0,则 T R U N C ( x ) = ⌈ x ⌉ \mathrm{TRUNC}(x) = \lceil x \rceil TRUNC(x)=x

x x x 的绝对值是 ∣ x ∣ |x| x。对于 x > 0 x > 0 x>0 x x x 以 2 为(实数)底的对数为 log ⁡ 2 x \log_2 x log2x

乘法写为 x ∗ y x ∗ y xy

如果 x x x y y y n n n 是整数且 n ≠ 0 n \neq 0 n=0,则 x ≡ y ( m o d   n ) x \equiv y (\mathrm{mod}\, n) xy(modn) 意味着 x − y x − y xy n n n 的倍数。

在语言定义中常见两种余数运算符。有时余数带有被除数的符号,有时带有除数的符号。我们使用 Ada 符号。
n r e m d = n − d ∗ T R U N C ( n / d ) ( sign of dividend ) , n m o d d = n − d ∗ ⌊ n / d ⌋ ( sign of divisor ) . \begin{aligned} n \enspace\mathrm{rem}\enspace d &= n − d ∗ \mathrm{TRUNC}(n/d) \quad &(\text{sign of dividend}),\\ n \enspace mod \enspace d &= n − d ∗ \lfloor n/d \rfloor &(\text{sign of divisor}). \end{aligned} nremdnmodd=ndTRUNC(n/d)=ndn/d(sign of dividend),(sign of divisor).

Fortran 90 中的名称是 MOD 和 MODULO。在 C 语言中,对余数的定义取决于具体的实现(许多 C 实现将有符号商向零舍入并使用 r e m \mathrm{rem} rem 余数)。还有其他一些建议的定义[6, 7]。

如果 n n n 是一个 udwordsdword,那么 H I G H ( n ) \mathrm{HIGH}(n) HIGH(n) L O W ( n ) \mathrm{LOW}(n) LOW(n) 分别表示 n n n 的最高有效半部和最低有效半部:

  • L O W ( n ) \mathrm{LOW}(n) LOW(n) 是一个 udword
  • 如果 n n nudword H I G H ( n ) \mathrm{HIGH}(n) HIGH(n) 是一个 udword ;如果 n n nsdword H I G H ( n ) \mathrm{HIGH}(n) HIGH(n)sword

在这两种情况下, n = 2 N ∗ H I G H ( n ) + L O W ( n ) n = 2^N ∗ \mathrm{HIGH}(n) + \mathrm{LOW}(n) n=2NHIGH(n)+LOW(n)

3 Assumed instructions

建议的代码假设在 N 位机器上执行表 3.1 中的操作。某些原语,如加载常量和操作数,在符号中是隐含的,并且不包含在操作计数中。
在这里插入图片描述

第8节中的算法要求能够对两个双字进行加减运算,得到一个双字结果;这通常会扩展为2-4条指令。

处理常数除数的算法需要在编译时对 udword 进行算术运算。

处理运行时不变除数的算法需要取一个正整数以2为底的对数(有时向上取整,有时向下取整),并需要将一个 udword 除以一个 uword。如果这些算法只针对常数除数,那么这些操作只需要在编译时进行。如果该架构有一个前导零计数(LDZ)指令,那么可以从以下方式中找到这些对数
⌈ log ⁡ 2 x ⌉ = N − L D Z ( x − 1 ) , ⌊ log ⁡ 2 x ⌋ = N − 1 − L D Z ( x ) ( 1 ≤ x ≤ 2 N − 1 ) . \begin{aligned} \lceil \log_2 x \rceil &= N − \mathrm{LDZ}(x − 1), \\ \lfloor \log_2 x \rfloor &= N − 1 − \mathrm{LDZ}(x)\qquad (1 ≤ x ≤ 2N − 1). \end{aligned} log2xlog2x=NLDZ(x1),=N1LDZ(x)(1x2N1).

某些算法可能会产生诸如 S R L ( x , 0 ) \mathrm{SRL}(x, 0) SRL(x,0) − ( x − y ) −(x − y) (xy) 等表达式;优化器应该进行显而易见的简化。一些描述显示了 2 N 2^N 2N 的加法或减法,这实际上是一个无操作(no-op)。

如果一个架构缺少算术右移,则可以根据下面的等式来计算它:

S R A ( x , ℓ ) = S R L ( x + 2 N − 1 , ℓ ) − 2 N − 1 − ℓ whenever  0 ≤ n < 2 N \mathrm{SRA}(x, \ell) = \mathrm{SRL}(x + 2^{N −1}, \ell) − 2^{N −1−\ell} \quad \text{whenever } 0 \le n < 2^N SRA(x,)=SRL(x+2N1,)2N1whenever 0n<2N

如果一个架构只有 M U L S H \mathrm{MULSH} MULSH M U L U H \mathrm{MULUH} MULUH 中的一个,那么另一个可以通过以下方式计算得出:

M U L U H ( x , y ) = M U L S H ( x , y ) + A N D ( x , X S I G N ( y ) ) + A N D ( y , X S I G N ( x ) ) \mathrm{MULUH}(x, y) = \mathrm{MULSH}(x, y) + \mathrm{AND}(x, \mathrm{XSIGN}(y))+ \mathrm{AND}(y, \mathrm{XSIGN}(x)) MULUH(x,y)=MULSH(x,y)+AND(x,XSIGN(y))+AND(y,XSIGN(x))
对于任意 N 位模式的 x x x y y y(在 M U L U H \mathrm{MULUH} MULUH 中被解释为 uword,在 M U L S H \mathrm{MULSH} MULSH 中被解释为 sword)。

4 Unsigned division

假设我们想要编译一个无符号除法 q = ⌊ n / d ⌋ q = \lfloor n/d\rfloor q=n/d,其中 0 < d < 2 N 0 < d < 2^N 0<d<2N 是一个常数或运行时不变量, 0 ≤ n < 2 N 0 \le n < 2^N 0n<2N 是变量。
让我们尝试找到 1 / d 1/d 1/d 的一个有理近似 m / 2 N + ℓ m/2^{N +\ell} m/2N+,使得

⌊ n d ⌋ = ⌊ m ∗ n 2 N + ℓ ⌋ whenever  0 ≤ n < 2 N \lfloor \frac{n}{d}\rfloor = \lfloor \frac{m*n}{2^{N +\ell}}\rfloor \quad \text{whenever } 0 \le n < 2^N dn=2N+mnwhenever 0n<2N

n = d n = d n=d 代入上式中显示我们需要 2 N + ℓ ≤ m ∗ d 2^{N +\ell} \le m * d 2N+md。设置 n = q ∗ d − 1 n = q * d - 1 n=qd1 显示 2 N + ℓ ∗ q > m ∗ ( q ∗ d − 1 ) 2^{N +\ell} * q > m * (q * d - 1) 2N+q>m(qd1)。乘以 d d d 得出 ( m ∗ d − 2 N + ℓ ) ∗ ( q ∗ d − 1 ) < 2 N + ℓ (m * d - 2^{N +\ell}) * (q * d - 1) < 2^{N +\ell} (md2N+)(qd1)<2N+。 如果 m ∗ d − 2 N + ℓ ≤ 2 m * d - 2^{N +\ell} \le 2 md2N+2,则对于所有小于 2 N 2^N 2N q ∗ d − 1 q * d - 1 qd1 的值,这个不等式都成立。下面的定理 4.2 声明这些条件是充分的,因为当 n < 2 N n < 2^N n<2N 时,最大相对误差( 2 N 2^N 2N分之一)太小,不足以影响商。

定理 4.2 假设 m m m d d d ℓ \ell 是非负整数,使得 d ≠ 0 d \neq 0 d=0
2 N + ℓ ≤ m ∗ d ≤ 2 N + ℓ + 2 ℓ (4.3) 2^{N+\ell} \le m * d \le 2^{N+\ell} + 2^\ell \qquad\text{(4.3)} 2N+md2N++2(4.3)

那么对于每一个整数 n n n 0 ≤ n < 2 N 0 \le n < 2^N 0n<2N ⌊ n d ⌋ = ⌊ m ∗ n / 2 N + ℓ ⌋ \lfloor \frac{n}{d}\rfloor = \lfloor m*n / 2^{N +\ell}\rfloor dn=mn/2N+

证明: 定义 k = m ∗ d − 2 N + ℓ k = m * d - 2^{N +\ell} k=md2N+。那么根据假设有 0 ≤ k ≤ 2 ℓ 0 \le k \le 2^\ell 0k2。给定 0 ≤ n < 2 N 0 \le n < 2^N 0n<2N n n n,写作 n = q ∗ d + r n = q * d + r n=qd+r,其中 q = ⌊ n / d ⌋ q = \lfloor n/d \rfloor q=n/d 0 ≤ r ≤ d − 1 0 \le r \le d - 1 0rd1。我们必须证明 q = ⌊ m ∗ n / 2 N + ℓ ⌋ q = \lfloor m * n/ 2^{N +\ell}\rfloor q=mn/2N+。通过计算得出

m ∗ n 2 N + ℓ − q = m ∗ d d ∗ n 2 N + ℓ − q = k + 2 N + ℓ d ∗ n 2 N + ℓ − q = k ∗ n d ∗ 2 N + ℓ + n d − n − r d = k 2 ℓ ∗ n 2 N ∗ 1 d + r d \begin{aligned} \frac{m ∗ n}{2^{N +\ell}} - q &= \frac{m * d}{d}*\frac{n}{2^{N +\ell}}- q \\ &= \frac{k + 2^{N +\ell}}{d}*\frac{n}{2^{N +\ell}}- q \\ &= \frac{k ∗ n}{d*2^{N +\ell}} + \frac{n}{d} - \frac{n-r}{d}\\ &= \frac{k}{2^\ell}*\frac{n}{2^N}*\frac{1}{d} + \frac{r}{d} \end{aligned} 2N+mnq=dmd2N+nq=dk+2N+2N+nq=d2N+kn+dndnr=2k2Nnd1+dr

因为 0 ≤ k ≤ 2 ℓ 0 \le k \le 2^\ell 0k2 0 ≤ n < 2 N 0 \le n < 2^N 0n<2N 0 ≤ r ≤ d − 1 0 \le r \le d - 1 0rd1
0 2 ℓ ∗ 0 2 N ∗ 1 d + 0 d ≤ k 2 ℓ ∗ n 2 N ∗ 1 d + r d ≤ 2 ℓ 2 ℓ ∗ 2 N − 1 2 N ∗ 1 d + d − 1 d 0 ≤ k 2 ℓ ∗ n 2 N ∗ 1 d + r d ≤ 2 N − 1 2 N ∗ 1 d + d − 1 d 0 ≤ k 2 ℓ ∗ n 2 N ∗ 1 d + r d ≤ 1 − 1 2 N ∗ d 0 ≤ k 2 ℓ ∗ n 2 N ∗ 1 d + r d < 1 \begin{aligned} \frac{0}{2^\ell}*\frac{0}{2^N}*\frac{1}{d} + \frac{0}{d} \le &\frac{k}{2^\ell}*\frac{n}{2^N}*\frac{1}{d} + \frac{r}{d}\le \frac{2^\ell}{2^\ell}*\frac{2^N -1}{2^N}*\frac{1}{d} + \frac{d - 1}{d}\\ 0 \le &\frac{k}{2^\ell}*\frac{n}{2^N}*\frac{1}{d} + \frac{r}{d}\le \frac{2^N -1}{2^N}*\frac{1}{d} + \frac{d - 1}{d}\\ 0 \le &\frac{k}{2^\ell}*\frac{n}{2^N}*\frac{1}{d} + \frac{r}{d}\le 1 − \frac{1}{ 2^N ∗ d} \\ 0 \le &\frac{k}{2^\ell}*\frac{n}{2^N}*\frac{1}{d} + \frac{r}{d} < 1 \end{aligned} 202N0d1+d00002k2Nnd1+dr222N2N1d1+dd12k2Nnd1+dr2N2N1d1+dd12k2Nnd1+dr12Nd12k2Nnd1+dr<1
这个差值是非负的,并且不超过 1。

如果不等式(4.3)成立,定理 4.2 允许用 m ∗ n / 2 N + ℓ m * n/ 2^{N +\ell} mn/2N+ 的乘法来替代除以 d d d。一般来说,我们要求 2 ℓ ≥ d − 1 2^{\ell} \ge d-1 2d1 以确保在区间 [ 2 N + ℓ , 2 N + ℓ + 2 ℓ ] [2^{N +\ell}, 2^{N +\ell} + 2^\ell] [2N+,2N++2] 中存在 d d d 的适当倍数。为了与有符号除法的算法(第5节和第6节)兼容,选择 m ∗ d > 2 N + ℓ m * d > 2^{N +\ell} md>2N+,尽管定理 4.2 允许相等。由于 m m m 几乎可以大到 2 N + 1 2^{N +1} 2N+1,我们不直接乘以 m m m,而是分别乘以 2 N 2^N 2N m − 2 N m - 2^N m2N。这引出了图 4.1 中的代码。在计算仅依赖于除数的常数之后,每个商的成本为1次乘法、2次加法/减法以及2次移位。
在这里插入图片描述

图 4.1 的解释:

  • 如果 d = 1 d = 1 d=1,那么 ℓ = 0 \ell = 0 =0,所以 m ′ = 1 m' = 1 m=1 s h 1 = s h 2 = 0 sh_1 = sh_2 = 0 sh1=sh2=0。代码计算 t 1 = ⌊ 1 ∗ n / 2 N ⌋ = 0 t_1 = \lfloor 1 ∗ n/2^N \rfloor = 0 t1=1n/2N=0 q = n q = n q=n
  • d > 1 d > 1 d>1,则 ℓ ≥ 1 \ell≥1 1,故 s h 1 = 1 sh_1 = 1 sh1=1 s h 2 = ℓ − 1 sh_2 =\ell −1 sh2=1。由于 m ′ ≤ 2 N ∗ ( 2 ℓ − d ) d + 1 ≤ 2 N ∗ ( d − 1 ) d + 1 < 2 N m' \le \frac{2^N ∗ (2^\ell − d)}{d} + 1 \le \frac{2^N ∗ (d − 1)}{d} + 1 < 2^N md2N(2d)+1d2N(d1)+1<2N m ′ m' m 的值可以置于一个 uword 中。由于 0 ≤ t 1 ≤ n 0 \le t_1 \le n 0t1n q q q 的公式简化为
    q = S R L ( t 1 + S R L ( n − t 1 , 1 ) , ℓ − 1 ) = ⌊ t 1 + ⌊ ( n − t 1 ) 2 ⌋ 2 ℓ − 1 ⌋ = ⌊ ⌊ 2 ∗ t 1 2 + ( n − t 1 ) 2 ⌋ 2 ℓ − 1 ⌋ (4.5) = ⌊ ⌊ ( t 1 + n ) / 2 ⌋ 2 ℓ − 1 ⌋ = ⌊ t 1 + n 2 ℓ ⌋ \begin{aligned} q &= \mathrm{SRL}(t_1 + \mathrm{SRL}(n − t_1, 1), \ell− 1)\\ &=\lfloor \frac{t_1 + \lfloor \frac{(n − t_1)}{2} \rfloor}{2^{\ell− 1}}\rfloor\\ &=\lfloor \frac{\lfloor \frac{2*t_1}{2} + \frac{(n − t_1)}{2} \rfloor}{2^{\ell− 1}}\rfloor \qquad\text{(4.5)}\\ &=\lfloor \frac{\lfloor(t_1 + n)/2\rfloor}{2^{\ell− 1}} \rfloor\\ &=\lfloor \frac{t_1 + n}{2^{\ell}} \rfloor \end{aligned} q=SRL(t1+SRL(nt1,1),1)=21t1+2(nt1)=2122t1+2(nt1)(4.5)=21⌊(t1+n)/2=2t1+n

t 1 + n = ⌊ m ′ ∗ n / 2 N ⌋ + n = ⌊ ( m ′ + 2 N ) ∗ n / 2 N ⌋ t_1 + n = \lfloor m' ∗ n/2^N \rfloor + n = \lfloor (m' + 2^N)∗ n/2^N \rfloor t1+n=mn/2N+n=⌊(m+2N)n/2N。设 m = m ′ + 2 N = ⌊ 2 N + ℓ / d ⌋ + 1 m = m' + 2^N = \lfloor 2^{N+\ell}/d\rfloor + 1 m=m+2N=2N+/d+1。由于 2 N + ℓ < m ∗ d ≤ 2 N + ℓ + 2 ℓ 2^{N +\ell} < m ∗ d ≤ 2^{N +\ell} + 2^\ell 2N+<md2N++2,且 d ≤ 2 ℓ d \le 2^{\ell} d2
2 N + ℓ / d − 1 ≤ m − 1 ≤ 2 N + ℓ / d 2 N + ℓ − d ≤ m ∗ d − d ≤ 2 N + ℓ 2 N + ℓ ≤ m ∗ d ≤ 2 N + ℓ + d 2 N + ℓ ≤ m ∗ d ≤ 2 N + ℓ + 2 ℓ \begin{aligned} 2^{N+\ell}/d -1 &\le m - 1 \le 2^{N+\ell}/d\\ 2^{N+\ell} -d &\le m*d - d \le 2^{N+\ell}\\ 2^{N+\ell} &\le m*d \le 2^{N+\ell} + d\\ 2^{N+\ell} &\le m*d \le 2^{N+\ell} + 2^{\ell} \end{aligned} 2N+/d12N+d2N+2N+m12N+/dmdd2N+md2N++dmd2N++2
因此满足定理 4.2 的假设。

注意: 从概念上讲, q q q S R L ( n + t 1 , ℓ ) \mathrm{SRL}(n + t_1, \ell) SRL(n+t1,),就像在 (4.5) 中一样。不要这样计算 q q q,因为 n + t 1 n+t_1 n+t1 可能会溢出 N N N 位,且移位计数可能会越界。

改进: 如果 d d d 是常数且为2的幂,则用移位替换除法。

改进: 如果 d d d 是常数且 m = m ′ + 2 N m = m' + 2^N m=m+2N 是偶数,则将 m / 2 ℓ m/2^\ell m/2 约简到最低项。原始乘数约简后在 N N N 位内。在极少数情况下(例如,在 32 位机器上 d = 641 d = 641 d=641,在 64 位机器上 d = 274177 d = 274177 d=274177),最终的移位为零。

改进。 如果 d d d 是常数且为偶数,则对某个 e > 0 e > 0 e>0 重写 ⌊ n d ⌋ = ⌊ ⌊ n / 2 e ⌋ d / 2 e ⌋ \lfloor \frac{n}{d}\rfloor=\lfloor \frac{\lfloor n/2^e\rfloor}{d/2^e}\rfloor dn=d/2en/2e。然后可以使用 S R L \mathrm{SRL} SRL 计算 ⌊ n / 2 e ⌋ \lfloor n/2^e\rfloor n/2e。由于 n / 2 e < 2 N − e n/2^e < 2^{N−e} n/2e<2Ne,乘数所需的精度比之前少。

这些思想体现在图 4.2 中,它生成了 n / d n/d n/d 的代码,其中 n n n 是无符号的, d d d 是常数。
在这里插入图片描述

以下三个示例阐述了图 4.2 中的情况。所有示例都采用无符号 32 位算术。

示例 q = ⌊ n / 10 ⌋ q = \lfloor n/10 \rfloor q=n/10CHOOSE MULTIPLIER 找到 m l o w = ( 2 36 − 6 ) / 10 m_\mathrm{low} = (2^{36} − 6)/10 mlow=(2366)/10 m h i g h = ( 2 36 + 14 ) / 10 m_\mathrm{high} = (2^{36} + 14)/10 mhigh=(236+14)/10。 经过一轮除以2的操作后,它返回 ( m , 3 , 4 ) (m, 3, 4) (m,3,4),其中 m = ( 2 34 + 1 ) / 5 m = (2^{34} + 1)/5 m=(234+1)/5。推荐的代码 q = S R L ( M U L U H ( ( 2 34 + 1 ) / 5 , n ) , 3 ) q = \mathrm{SRL}(\mathrm{MULUH}((2^{34} + 1)/5, n), 3) q=SRL(MULUH((234+1)/5,n),3) 消除了预先的0位移。见表 11.1。
在这里插入图片描述
示例 q = ⌊ n / 7 ⌋ q = \lfloor n/7 \rfloor q=n/7。这里 m = ( 2 35 + 3 ) / 7 > 2 32 m = (2^{35} + 3)/7 > 2^{32} m=(235+3)/7>232。本示例使用图 4.1 中较长的序列。

示例 q = ⌊ n / 14 ⌋ q = \lfloor n/14\rfloor q=n/14CHOOSE MULTIPLIER 首先返回当 d = 7 d = 7 d=7 时相同的乘数。 推荐的代码使用2和7的独立除法:

q = S R L ( M U L U H ( ( 2 34 + 5 ) / 7 , S R L ( n , 1 ) ) , 2 ) . q = \mathrm{SRL}(\mathrm{MULUH}((2^{34} + 5)/7, \mathrm{SRL}(n, 1)), 2). q=SRL(MULUH((234+5)/7,SRL(n,1)),2).

本算法和后续算法共享的程序 CHOOSE MULTIPLIER 如图 6.2 所示。

在这里插入图片描述

因为 N + s h p o s t ≤ ℓ + p r e c N + sh_{post} ≤ \ell + prec N+shpost+prec,所以 N + s h p o s t − p r e c ≤ ℓ N + sh_{post}-prec ≤ \ell N+shpostprec
2 N + s h p o s t ∗ ( 1 + 2 − p r e c ) ≤ 2 N + s h p o s t + 2 ℓ 2^{N +sh_{post}} ∗ (1 + 2^{−prec}) \le 2^{N +sh_{post}} + 2^\ell 2N+shpost(1+2prec)2N+shpost+2
又因为 0 ≤ s h p o s t ≤ ℓ 0 \le sh_{post} ≤ \ell 0shpost,所以
2 N + s h p o s t ∗ ( 1 + 2 − p r e c ) ≤ 2 N + ℓ + 2 ℓ 2^{N +sh_{post}} ∗ (1 + 2^{−prec}) \le 2^{N +\ell} + 2^\ell 2N+shpost(1+2prec)2N++2
不等式(4.3)的上界成立。

因为 2 ℓ − 1 < d 2^{\ell−1} < d 21<d d ≤ 2 p r e c d \le 2^{prec} d2prec, 所以 ℓ − 1 < p r e c \ell-1 < prec 1<prec,所以 2 − p r e c < 2 1 − ℓ 2^{−prec}< 2^{1−\ell} 2prec<21
m < 2 N + s h p o s t ∗ ( 1 + 2 1 − ℓ ) / d m < 2^{N +sh_{post}} ∗ (1 + 2^{1−\ell})/d m<2N+shpost(1+21)/d
因为 2 ℓ − 1 < d ≤ 2 ℓ 2^{\ell−1} < d \le 2^\ell 21<d2 2 1 − ℓ ≤ 1 2^{1−\ell} \le 1 211,所以 1 + 2 1 − ℓ ≤ 2 1 + 2^{1−\ell} \le 2 1+212。可得
2 N + s h p o s t ∗ ( 1 + 2 1 − ℓ ) / d ≤ 2 N + s h p o s t ∗ 2 / d 2^{N +sh_{post}} ∗ (1 + 2^{1−\ell})/d \le 2^{N +sh_{post}} ∗ 2/d 2N+shpost(1+21)/d2N+shpost2/d
又因为 d ≤ 2 ℓ d \le 2^{\ell} d2,所以
2 N + s h p o s t + 1 / d ≤ 2 N + s h p o s t − ℓ + 1 2^{N +sh_{post}+1}/d \le 2^{N +sh_{post}−\ell+1} 2N+shpost+1/d2N+shpost+1
因此, 2 N + s h p o s t ∗ ( 1 + 2 1 − ℓ ) / d ≤ 2 N + s h p o s t − ℓ + 1 2^{N +sh_{post}} ∗ (1 + 2^{1−\ell})/d \le 2^{N +sh_{post}−\ell+1} 2N+shpost(1+21)/d2N+shpost+1

注意:略去5到9节中商向零取整的有符号除法、商向负无穷大取整的有符号除法、udword 除以运行时不变的 uword,以及先验已知余数为零的除法。

10 Implementation in GCC

作者在可自由使用的 GCC 编译器[21]中实现了常数除数的算法,扩展了其与机器和语言无关的内部代码生成。 并且还对一些机器描述符或 md 文件进行了轻微的机器依赖的修改,以获得最优的代码。GCC 支持的所有语言和几乎所有处理器都将受益。 相关更改计划包含在 GCC 2.6中。

为了生成 N 位数除法的代码,CHOOSE MULTIPLIER 函数需要执行 ( 2 N 2N 2N) 位算术运算。这使得该程序比图 6.2中显示的更复杂。

根据操作的位大小选择最佳指令是一个棘手的问题,作者花了相当长的时间:

  • 对于某些架构,选择具有最小可用精度的乘法指令很重要。
  • 在其他架构上,可以通过一系列加法、减法和移位更快地执行乘法。

作者还没有实现任何针对运行时不变除数的算法。只有少数架构(AMD 29050、英特尔 x86、摩托罗拉 68k 和88110,以及在某种程度上的 IBM POWER)具有足够的硬件支持来使这种实现可行,即可以用于整数对数计算的指令,以及 ( 2 N 2N 2N) 位/ N N N 位除法指令。即使有硬件支持,也必须小心,确保转换真正改进了代码;例如,可能需要执行很多次循环才能确保较快的循环体超过循环头中乘数的计算成本。

11 Results

图 11.1 提供了一个编译时间常数除法器的例子,它在所有最新的处理器实现上都获得了显著的加速。该程序将二进制数转换为十进制字符串。它为每个输出数字计算一个商和一个余数。
在这里插入图片描述

表 11.1 展示了为 Alpha、MIPS、POWER 和 SPARC 生成的汇编代码。这里没有显式的除法。尽管最初是单独计算的,但商和余数计算已合并(通过 GCC 的公共子表达式消除过程)。

unsigned int 数据类型在所有四种架构上均为32位,但 Alpha 是一种64位架构。Alpha 的代码比其他的长,因为它使用
4 ∗ [ ( 2 16 + 1 ) ∗ ( 2 8 + 1 ) ∗ ( 4 ∗ [ 4 ∗ ( 4 ∗ x − x ) + x ] − x ) ] + x 4 * [(2^{16} + 1) * (2^8 + 1) * (4 * [4 * (4 * x - x) + x] - x)] + x 4[(216+1)(28+1)(4[4(4xx)+x]x)]+x
( 2 34 + 1 ) / 5 (2^{34} + 1)/5 (234+1)/5 乘以 x x x,而不是更慢的、需要 23 个周期的mulq。这说明这些算法所需的乘法有时可以通过一系列的移位、加法和减法快速计算[5],因为小常数除数的乘数在二进制模式上有规律。

表 11.2 比较了有除法消除算法和没有除法消除算法的基转换例程在一些处理器实现上的时间。转换的数字是一个完整的32位数,足以隐藏测量中的程序调用开销。
在这里插入图片描述

作者还运行了 SPEC’92 的整数基准测试。对于大多数程序来说,改进微不足道;观察到的最佳改进仅为3%左右。一些涉及哈希的基准测试显示出高达约30%的提升。作者预计在一些数论代码上会有显著的提升。

参考资料:

  • Division by Invariant Integers using Multiplication
  • Improved division by invariant integers
  • C++干货系列——从编译期常量谈到constexpr(二)
  • Integer Division by Constants: Optimal Bounds
  • lemire/fast_division
  • Thorius/fast_division
  • Why doesn’t gcc or clang on ARM use “Division by Invariant Integers using Multiplication” trick?
  • Perform integer division using multiplication [duplicate]
  • paddle/phi/kernels/funcs/fast_divmod.h
  • paddle/phi/kernels/primitive/datamover_primitives.h
  • onnxruntime/core/providers/cuda/shared_inc/fast_divmod.h
  • intel/xetla/include/common/utils/fastmath.hpp
  • How to find magic multipliers for divisions by constant on a GPU?
  • [原创]加减乘除反汇编笔记与MagicNumber探究记录
  • Java 源码 - java.lang.Integer
  • 除以二
  • C/C++除数为整数常量(但不是2的幂次)时,优化得div指令都没了是什么原理?
  • 编译技术-除常数优化
  • 即,令,当,这些数学用语在英文论文中如何表示?
  • 英语分数的表达,特别是分母比较大的怎么表达 比如: 2/37 2/115 3/1112
  • What has a better performance: multiplication or division?
  • 4. Instruction tables
  • 『扩展欧几里得算法 Extended Euclid』
  • 擴展歐基里德算法 (Extended Euclidean algorithm)
  • The integer division algorithm of Intel’s x86 processors
  • x86汇编_MUL/IMUL乘法指令_笔记52
  • integer division and modulo
  • Quick ALU Performance multiply/division investigation
  • Most efficient way of dividing by power of two
  • Fast integer division and modulo with a const runtime divisor
  • Floating Point and Integer Arithmetic Benchmark
  • Achieved IOPs
  • Integer division problem
  • 5.4.1. Arithmetic Instructions

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1528949.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c++多长时间会被Python或者其他语言取代?

c多长时间会被Python或者其他语言取代&#xff1f; 如果不考虑市场因素&#xff0c;C#今天就可以取代C。 自.NET跨平台至今&#xff0c;C能做的工作&#xff0c;C#都能做了&#xff0c;且性能差别不大。 在C最有优势的嵌入式UI方面&#xff0c;C#可以拿出Avalonia替代QT。用 …

存储器的层次结构和局部性原理

前言 大家好我是jiantaoyab&#xff0c;这是我所总结作为学习的笔记第19篇&#xff0c;在这里分享给大家&#xff0c;这篇文章讲存储器的一部分内容。 存储器的层次结构 SRAM 静态随机存取存储器的芯片&#xff0c;SRAM 之所以被称为“静态”存储器&#xff0c;是因为只要处…

MYSQL概念和编译安装

目录 一、数据库概述 1.1数据 1.2表 1.3数据库 总结&#xff1a; 2.数据库管理系统&#xff08;DBMS&#xff09; 3.DBMS工作模式 4.数据库系统原理 二、数据库发展史 三、主流数据库 四、关系型数据库和非关系型数据库 1.关系型数据库 2.非关系数据库 MYSQL数据…

输出菱形(*)--c语言

//输出菱形 #include<stdio.h>int main(){//上int line0;scanf("%d",&line);int i0;for(i0;i<line;i){int j0;//输出空格for(j0;j<line-1-i;j){printf(" ");}//输出*号for(j0;j<2*i1;j){printf("*");}printf("\n")…

Redisson 分布式锁原理分析

Redisson 分布式锁原理分析 示例程序 示例程序&#xff1a; public class RedissonTest {public static void main(String[] args) {Config config new Config();config.useSingleServer().setPassword("123456").setAddress("redis://127.0.0.1:6379"…

【开发环境】Ubuntu 18.04 搭建 QT编译环境详细步骤 【亲测有效】

目录 1 查看Ubuntu系统中Qt版本 2 下载Ubuntu系统Qt版本安装包 3 Qt安装 3.1 Qt 安装步骤 3.2 安装qt发现Ubuntu空间不足&#xff0c;怎么去扩容呢&#xff1f; 3.2.1 硬盘操作步骤&#xff08;需要关闭虚拟机进行操作&#xff09; 3.2.2 Ubuntu命令操作&#xff1a;安装…

基于单片机的模糊PID炉温控制系统设计

摘 要 电热炉是在工业热处理的生产中广泛使用的一种设备&#xff0c;电热炉的温度控制系统存在时变性&#xff0c;非线性&#xff0c;滞后性等特征&#xff0c;难以用常规PID的控制器对系统达到很好的控制效果。当控温精度的要求高时&#xff0c;使用传统的控制理论方法难以达…

蓝桥杯刷题|03普及-真题

[蓝桥杯 2017 省 B] k 倍区间 题目描述 给定一个长度为 N 的数列&#xff0c;​,,⋯&#xff0c;如果其中一段连续的子序列 ​,,⋯ (i≤j) 之和是 K 的倍数&#xff0c;我们就称这个区间 [i,j] 是 K 倍区间。 你能求出数列中总共有多少个 K 倍区间吗&#xff1f; 输入格式 …

微服务高级篇(一):微服务保护+Sentinel

文章目录 一、初识Sentinel1.1 雪崩问题及解决方案1.2 微服务保护技术对比1.3 Sentinel介绍与安装1.4 微服务整合Sentinel 二、Sentinel的流量控制三、Sentinel的隔离与降级四、Sentinel的授权规则五、规则持久化5.1 规则管理模式【原始模式、pull模式、push模式】5.2 实现push…

第二十六节 Java 重写(Override)与重载(Overload)

重写 (Override) 重写是子类对父类的允许访问的方法的实现过程进行重新编写&#xff01;返回值和形参都不能改变。即外壳不变&#xff0c;核心重写&#xff01; 重写的好处在于子类可以根据需要&#xff0c;定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。…

面试算法-48-二叉树的锯齿形层序遍历

题目 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff0c;层与层之间交替进行&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,…

从Excel到山海鲸:我的数据可视化升级之旅

作为一名新用户&#xff0c;我最近有幸体验了山海鲸可视化软件&#xff0c;近期山海鲸可视化产品开放了可视化编辑全部功能&#xff0c;并支持本地化部署功能&#xff0c;在使用过程中它不仅打开了我对数据可视化全新世界的大门&#xff0c;而且在实际操作中为我带来了不少惊喜…

【C语言】数据在内存中的存储(包含大小端字节序问题)~

一、前言 我们在刚开始学习C语言的时候&#xff0c;就接触到了很多数据的不同类型。我们也知道&#xff0c;数据是存储在一块内存空间的&#xff0c;且我们只知道数据的类型决定着&#xff0c;该数据在内存中所占内存空间的大小&#xff0c;且超过一个字节的数据在内存中存储的…

【NLP笔记】Transformer

文章目录 基本架构EmbeddingEncoderself-attentionMulti-Attention残差连接LayerNorm DecoderMask&Cross Attention线性层&softmax损失函数 论文链接&#xff1a; Attention Is All You Need 参考文章&#xff1a; 【NLP】《Attention Is All You Need》的阅读笔记 一…

安科瑞智慧安全用电云平台【无人化数据监控 远程控制 运维管理】

背景 在住宅火灾中&#xff0c;电气引发的居高不下&#xff0c;已查明原因的火灾中有52%系电气原因引起&#xff0c;尤其是各类家用电器、电动车、电气线路等引发的火灾越来越突出&#xff0c;仅电动自行车引发的较大火灾就有7起。这些事故暴露出电器产品生产质量、流通销售&a…

引领展览新风尚:一站式搭建VR在线展馆,开启数字化展示新纪元

随着VR技术的不断成熟和普及&#xff0c;VR在线展馆已成为企业和用户展示展品的新颖方式。这种技术不仅能够提供沉浸式的观展体验&#xff0c;还能帮助企业和个人快速搭建属于自己的虚拟展馆。元居虚拟空间布展平台为用户提供了快速搭建VR在线展馆的便捷服务。 一、VR在线展馆的…

vue3+vite项目打包遇到的问题

一、项目打包出现空白页 vite.config.js中&#xff0c;添加base: ./ import { defineConfig } from vite import vue from vitejs/plugin-vueexport default defineConfig({base: ./, })router/index.js&#xff0c;将路由模式改成hash模式 import { createRouter, createWe…

4G/5G视频记录仪_联发科MTK6765平台智能记录仪方案

视频记录仪主板采用了联发科MT6765芯片&#xff0c;该芯片采用12nm FinFET制程工艺&#xff0c;8*Cortex-A53架构&#xff0c;搭载安卓11.0/13.0系统&#xff0c;主频最高达2.3GHz&#xff0c;待机功耗可低至5ma&#xff0c;并具有快速数据传输能力。配备了2.4英寸高清触摸显示…

YOLOv5独家改进:block改进 | RepViTBlock和C3进行结合实现二次创新 | CVPR2024清华RepViT

💡💡💡本文独家改进:CVPR2024 清华提出RepViT:轻量级新主干!从ViT角度重新审视移动CNN,RepViTBlock和C3进行结合实现二次创新 改进结构图如下: 收录 YOLOv5原创自研 https://blog.csdn.net/m0_63774211/category_12511931.html 💡💡💡全网独家首发创…

2024:存量时代,内容平台如何“发新芽”?

今年年初&#xff0c;腾讯董事会主席马化腾表示&#xff0c;微信这棵老树如何发新芽&#xff0c;是一个很大的问题。 在互联网存量时代&#xff0c;如何提升效率焕发新活力&#xff0c;已经成为内容平台共同的命题。本质上看&#xff0c;这需要平台把握“三重法则”&#xff1…