并行算法:原理、问题与解决方案
1. 并行FFT算法
在经过代数变换后,向量 $y$ 的分量可以写成如下形式:
$y_{\tilde{l}N_2+\tilde{L}} = \sum_{l=0}^{N_1 - 1} e^{\frac{2\pi i\tilde{l}l}{N_1}} e^{\frac{2\pi i l\tilde{L}}{N_1N_2}} \sum_{L=0}^{N_2 - 1} e^{\frac{2\pi i L\tilde{L}}{N_2}} x_{LN_1 + l}$
基于此表达式实现并行程序并不困难,具体步骤如下:
1.
计算内部和
:利用变量 $l$ 的并行性,计算 $l = 0, \cdots, N_1 - 1$ 时的内部和 $\sum_{L=0}^{N_2 - 1} e^{\frac{2\pi i L\tilde{L}}{N_2}} x_{LN_1 + l}$。
2.
乘法运算
:将得到的值乘以 $e^{\frac{2\pi i l\tilde{L}}{N_1N_2}}$。
3.
再次FFT
:对变量 $L$ 进行并行FFT,$L = 0, \cdots, N_2 - 1$,最终得到 $y_{\tilde{l}N_2+\tilde{L}}$ 构成的向量 $y = F[x]$。
该算法的渐近复杂度分析如下:
- 第一次傅里叶变换,对于每个 $\tilde{l} = 0, \cdots, N_1 - 1$,需要 $\Theta(N_2 \log_2 N_2)$ 次算术运算。
- 接着是 $N_2$ 次并行乘法。
- 第二次DFT,对于每个 $\tilde{L} = 0, \cdots, N_2 - 1$,需要 $\Theta(N_1 \log_2 N_1)$ 次运算。
在具有 $p = \max(N_1, N_2)$ 个处理器的系统上,该FFT版本的执行时间为:
$T(N) = \Theta(N_2 \log_2 N_2) + \Theta(1) + \Theta(N_1 \log_2 N_1) = \Theta(\max(N_1, N_2) \log_2 N)$
成本 $C(N)$ 为 $(\max(N_1, N_2))^2 \log_2 N$,当 $N_1 = N_2 = \sqrt{N}$ 时,与顺序FFT版本的成本相同,而加速比 $S(N)$ 为 $\sqrt{N}$。
2. 算法执行时间计算问题
以下是几个关于算法执行时间计算的问题及解答:
|问题编号|算法|输入数据大小 $N$|处理器数量 $p$|执行时间 $T_p(N)$|
| ---- | ---- | ---- | ---- | ---- |
|13.1 - (1)|算法A|32|4|$80\tau$|
|13.1 - (2)|算法A|32|16|$20\tau$|
|13.2 - (1)|算法B|32|4|$2^{30}\tau$|
|13.2 - (2)|算法B|32|16|$2^{28}\tau$|
算法A的顺序版本执行时间为 $T_1(N) = 2N \log_2(N) \tau$,算法B的顺序版本执行时间为 $T_1(N) = 2^N\tau$。在假设算法可最大程度并行化的情况下,即 $T_p(N) = \frac{T_1(N)}{p}$,可计算出上述结果。
3. 基于Amdahl定律的速度计算
Amdahl定律用于计算并行程序的最大加速比,以下是几个相关问题及解答:
-
问题13.3
:当程序中顺序计算的份额 $f = \frac{1}{10}$ 时,在具有 $p$ 个处理器的计算系统上,程序的最大加速比 $(\text{S}
p)
{\max} = \frac{10p}{p + 10}$。
-
问题13.4
:当顺序计算份额 $f = \frac{1}{100}$ 时,程序的最大加速比 $S_{\infty} = 100$。
-
问题13.5
:已知并行算法A在具有 $p$ 个处理器的系统上的加速比为 $S_p$,则在具有 $p’$ 个处理器的系统上的加速比 $S_{p’} = \frac{S_p p’(p - 1)}{p(p’ - 1) + (p - p’)S_p}$。
4. 算法A的最大加速比计算
考虑一个由两个块 $A_1$ 和 $A_2$ 组成的计算算法A,$A_2$ 只能在 $A_1$ 完成后开始执行。设 $A_1$ 和 $A_2$ 中顺序计算的份额分别为 $f_1$ 和 $f_2$,且 $A_2$ 在顺序模式下的执行时间是 $A_1$ 的 $\eta$ 倍。
设 $A_1$ 在顺序模式下的执行时间为 $\tau$,则 $A_2$ 的执行时间为 $\eta\tau$,整个算法A的顺序执行时间 $T_1 = \tau + \eta\tau = (1 + \eta)\tau$。
在并行模式下,$A_1$ 中 $(1 - f_1)$ 的计算时间和 $A_2$ 中 $(1 - f_2)$ 的计算时间将由 $p$ 个计算节点分担,因此算法A的执行时间可估计为:
$T_p \geq f_1\tau + \frac{(1 - f_1)\tau}{p} + f_2\eta\tau + \frac{(1 - f_2)\eta\tau}{p} = (f_1 + \eta f_2)\tau + \frac{1 + \eta - (f_1 + \eta f_2)}{p}\tau$
算法A的最大可实现加速比为:
$(\text{S}
p)
{\max} = \frac{(1 + \eta)\tau}{(f_1 + \eta f_2)\tau + \frac{(1 + \eta - (f_1 + \eta f_2))\tau}{p}} = \frac{1}{f + \frac{1 - f}{p}}$
其中 $f = \frac{f_1 + \eta f_2}{1 + \eta}$,表示该算法中顺序操作的平均份额。
5. Brent引理的证明
为了证明Brent引理,引入算法A的“操作 - 操作数”有向图。由于在并行计算机上解决计算问题需要时间 $T_{\infty}$,该有向图的层数为 $d = \frac{T_{\infty}}{\tau}$,其中 $\tau$ 是一次操作的执行时间。设第 $i$ 层的节点数为 $n_i$,$1 \leq i \leq d$。
算法 $A’$ 使用的处理器数量比A少,为 $p$。在第 $i$ 层,每个处理器最多处理 $\lceil\frac{n_i}{p}\rceil$ 个操作。
通过对“操作 - 操作数”有向图的 $d$ 层操作时间求和,可得到算法 $A’$ 执行时间的估计:
$T(p) \leq \sum_{i = 1}^{d} \lceil\frac{n_i}{p}\rceil \tau$
利用“天花板”函数的性质 $\lceil\frac{k}{m}\rceil \leq \frac{k + m - 1}{m}$,将不等式转化为:
$T(p) \leq \sum_{i = 1}^{d} \frac{n_i + p - 1}{p} \tau = \frac{1}{p} \sum_{i = 1}^{d} n_i\tau + \frac{p - 1}{p} \sum_{i = 1}^{d} \tau$
算法A在单处理器系统上的执行时间为 $\sum_{i = 1}^{d} n_i\tau = T_1$,最终得到算法 $A’$ 在具有 $p$ 个处理器的PRAM上的执行时间估计:
$T(p) \leq T_{\infty} + \frac{T_1 - T_{\infty}}{p}$
6. parPrefix算法的证明
半群是一个对 $(A, \otimes)$,其中 $A$ 是一个集合,$\otimes$ 是一个半群运算。为了证明算法parPrefix可用于计算半群元素上任何二元结合运算的部分结果,对算法进行如下修改:将第15行改为 $prefixList[j] := temp - 2^{i - 1} \otimes temp[j]$,其中 $\otimes$ 可以是任何二元运算。
设 $(i)prefixList[j]$ 是在第8行的第 $i$ 次循环迭代后数组 $prefixList$ 元素的值。使用数学归纳法证明辅助命题:
$(i)prefixList[j] = \prod_{m = \sigma(i, j)}^{j} list[m]$,对于所有 $j = 1, \cdots, N$,其中 $\sigma(i, j) = \max(j + 1 - 2^i, 1)$。
- 基础步骤 :当 $i = 1$ 时,执行第一次迭代后,$(1)prefixList[j]$ 的值为:
- 当 $j = 2, 3, \cdots, N$ 时,$(1)prefixList[j] = list[j - 1] \otimes list[j]$。
- 当 $j = 1$ 时,$(1)prefixList[j] = list[1]$。
这可以重写为 $(1)prefixList[j] = \prod_{m = \sigma(1, j)}^{j} list[m]$,其中 $\sigma(1, j) = \max(j - 1, 1)$,证明了 $P(1)$ 的有效性。
- 归纳步骤 :假设对于 $i = k$,算法parPrefix的操作结果为 $(k)prefixList[j] = \prod_{m = \sigma(k, j)}^{j} list[m]$。证明 $P(k + 1)$ 的有效性,即对于所有不超过 $N$ 的自然索引 $j$,$(k + 1)prefixList[j] = \prod_{m = \sigma(k + 1, j)}^{j} list[m]$。
从算法分析可知:
- 当 $2^k < j \leq N$ 时,$(k + 1)prefixList[j] = (k)prefixList[j - 2^k] \otimes (k)prefixList[j]$。
- 当 $1 \leq j \leq 2^k$ 时,$(k + 1)prefixList[j] = (k)prefixList[j]$。
利用上一步中数组 $prefixList$ 元素的表达式,可得 $(k + 1)prefixList[j] = \prod_{m = \sigma(k, j - 2^k)}^{j - 2^k} list[m] \otimes \prod_{m = \sigma(k, j)}^{j} list[m]$。
由于 $\sigma(k, j - 2^k) = \max(j + 1 - 2^{k + 1}, 1) = \sigma(k + 1, j)$,所以 $(k + 1)prefixList[j] = \prod_{m = \sigma(k + 1, j)}^{j} list[m]$,对于所有 $j = 1, \cdots, N$。
因此,命题 $P(i)$ 对于所有 $i = 1, 2, \cdots, \lceil\log_2 N\rceil$ 都为真。在第 $i = \lceil\log_2 N\rceil$ 次迭代时,$\sigma(\lceil\log_2 N\rceil, j) = 1$,最终元素的值为 $prefixList[j] = \prod_{m = 1}^{j} list[m]$。
这证明了算法parPrefix的正确性,因为 $\otimes$ 可以是任何二元结合运算。
7. 元素求和并行算法示例
以数组 $20, 12, 18, 16, 24, 10, 22, 14$ 为例,展示元素求和并行算法的操作过程:
|迭代次数 $i$|数组元素值|
| ---- | ---- |
|原始数据|$20, 12, 18, 16, 24, 10, 22, 14$|
|$i = 1$|$20, 32, 18, 34, 24, 34, 22, 36$|
|$i = 2$|$20, 32, 18, 66, 24, 34, 22, 70$|
|$i = 3$|$20, 32, 18, 66, 24, 34, 22, 136$|
每次迭代中改变的元素用粗体和下划线突出显示。算法执行完毕后,从第 $N = 8$ 个单元格读取答案,最终结果为 $136$。
8. 连续背包问题的提示
连续背包问题考虑 $N$ 个物体 $a_1, \cdots, a_N$ 和一个容量为 $V$ 的背包。每个物体 $a_i$ 有正体积 $v_i$ 和成本 $c_i$,要求将物体(可能是部分)放入背包,满足两个条件:
1. 它们的总体积不超过 $V$。
2. 它们的总成本最大。
形式上,问题归结为在条件 $\sum_{i = 1}^{N} f_iv_i \leq V$ 和 $0 \leq f_i \leq 1$ 下,最大化 $\sum_{i = 1}^{N} f_ic_i$,其中 $f_i$ 是物体 $a_i$ 放入背包的份额。
解决该问题的提示是:将物体按特定成本 $\tilde{c}_i = \frac{c_i}{v_i}$ 非升序排列,并对数组 $\tilde{c}$ 应用并行前缀计算算法。
9. 实数幂运算算法分析
- 顺序算法复杂度 :顺序算法将实数 $x$ 提升到 $N$ 次幂,基于以下关系:
- 当 $N > 0$ 且为偶数时,$x^N = (x^{\lfloor N/2 \rfloor})^2$。
- 当 $N > 0$ 且为奇数时,$x^N = x(x^{\lfloor N/2 \rfloor})^2$。
- 当 $N = 0$ 时,$x^N = 1$。
该算法的渐近复杂度满足递归关系 $T(N) = T(\frac{N}{2}) + f(N)$,其中非齐次函数 $f(N)$ 为:
- 当 $N$ 为偶数时,$f(N) = 1$。
- 当 $N$ 为奇数时,$f(N) = 2$。
由于 $f(N) = \Theta(1)$,根据基本递归关系定理,$T(N) = \Theta(\log_2 N)$。
-
并行算法
:Kung提出的计算 $x^N$ 的并行算法步骤如下:
1. 计算 $\omega_k$ 和 $\tilde{\omega} k$,对于 $k = 0, 1, \cdots, N - 1$,其中 $\omega_k$ 是方程 $z^N = 1$ 的第 $k$ 个复根,$\tilde{\omega}_k = \frac{\omega_k}{N}$。
2. 计算 $y_k = x - \omega_k$,对于 $k = 0, 1, \cdots, N - 1$。
3. 计算 $z_k = \frac{\tilde{\omega}_k}{y_k}$,对于 $k = 0, 1, \cdots, N - 1$。
4. 计算和 $Z = \sum {k = 0}^{N - 1} z_k$。
5. 反转 $Z$ 的值:$\tilde{Z} = \frac{1}{Z}$。
6. 最终答案:$x^N = \tilde{Z} + 1$。
该算法的执行时间估计:第一步不依赖于 $x$ 的值,可以在算法开始前准备好包含 $\omega_k$ 值的数组。设两个复数求和的操作时间为 $T_a$,两个复数除法的操作时间为 $T_d$,则在具有 $N$ 个处理器的多处理器计算系统上,上述步骤2 - 6的执行时间为:
$T(N) = T_a + T_d + O(\log_2 N)T_a + T_d + T_a = 2T_d + O(\log_2 N)T_a$
10. 离散傅里叶变换相关问题
- 计算DFT :
- 当 $x = (0, 1, 0, 1)$ 时,$F[x] = (2, 0, -2, 0)$。
- 当 $x = (1, 0, 1, 0)$ 时,$F[x] = (2, 0, 2, 0)$。
- DFT性质证明 :
- 缩放性质 :对于连续傅里叶变换,$F[s(at)] = \frac{1}{|a|} S(\frac{f}{a})$,对于所有 $a \in \mathbb{R} \setminus {0}$。
- 时域平移性质 :$F[s(t - t_0)] = S(f)e^{2\pi i f t_0}$,对于所有 $t_0 \in \mathbb{R}$。
- Parseval定理证明 :
- 连续情况 :证明 $\int_{-\infty}^{\infty} |s(t)|^2 dt = \int_{-\infty}^{\infty} |S(f)|^2 df$。
- 离散情况 :设 $y$ 是长度为 $N$ 的向量 $x$ 的DFT,证明 $\sum_{k = 0}^{N - 1} |x_k|^2 = \frac{1}{N} \sum_{k = 0}^{N - 1} |y_k|^2$。
11. 其他问题
- shuffle过程 :“shuffle”过程会交换元素 $x[i]$ 和 $x[j]$ 的位置,当且仅当变量 $i$ 和 $j$ 的二进制表示是可逆的。
- 对于数组 $0, 1, 2, 3, 4, 5, 6, 7$,“shuffle”后数组变为 $0, 4, 2, 6, 1, 5, 3, 7$。
- 对于数组 $0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15$,“shuffle”后数组变为 $0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15$。
- 正弦和余弦变换 :
- 正弦变换 :向量 $x$ 的长度为 $N$ 且 $x_0 = 0$ 的正弦变换定义为 $(F_{\sin}[x]) n = \sum {k = 0}^{N - 1} x_k \sin(\frac{\pi kn}{N})$,可将其简化为标准DFT。
- 余弦变换 :向量 $x$ 的长度为 $N + 1$ 的余弦变换定义为 $(F_{\cos}[x]) n = \frac{1}{2} (x_0 + (-1)^n x_N) + \sum {k = 1}^{N - 1} x_k \cos(\frac{\pi kn}{N})$,也可简化为标准DFT。
12. 快速傅里叶变换并行算法示例
以数组 $0, 1, 2, 3, 4, 5, 6, 7$ 为例,展示快速傅里叶变换并行算法的操作过程:
1. 将输入数组表示为矩阵 $M$,选择 $N_1 = 4$,$N_2 = 2$,则 $M = \begin{bmatrix}0 & 1 & 2 & 3 \ 4 & 5 & 6 & 7\end{bmatrix}$。
2. 对矩阵 $M$ 的列应用顺序FFT,得到 $M = \begin{bmatrix}4 & 6 & 8 & 10 \ -4 & -4 & -4 & -4\end{bmatrix}$。
3. 将矩阵 $M$ 的每个元素乘以 $e^{\frac{2\pi i}{N_1N_2} (l\tilde{L})}$,其中 $l$ 是列号,$0 \leq l \leq N_1 - 1$,$\tilde{L}$ 是行号,$0 \leq \tilde{L} \leq N_2 - 1$,得到 $M = \begin{bmatrix}4 & 6 & 8 & 10 \ -4 & -2\sqrt{2}(1 + i) & -4i & -2\sqrt{2}(-1 + i)\end{bmatrix}$。
4. 对矩阵 $M$ 的行应用顺序FFT,得到 $M = \begin{bmatrix}28 & -4 - 4i & -4 & -4 + 4i \ -4 - 4(\sqrt{2} + 1)i & -4 - 4(\sqrt{2} - 1)i & -4 + 4(\sqrt{2} - 1)i & -4 + 4(\sqrt{2} + 1)i\end{bmatrix}$。
最终,按列写出矩阵 $M$ 的元素,得到原始数组的FFT分量:
$y_0 = 28$,$y_1 = -4 - 4(\sqrt{2} + 1)i$,$y_2 = -4 - 4i$,$y_3 = -4 - 4(\sqrt{2} - 1)i$,$y_4 = -4$,$y_5 = -4 + 4(\sqrt{2} - 1)i$,$y_6 = -4 + 4i$,$y_7 = -4 + 4(\sqrt{2} + 1)i$。
综上所述,本文介绍了多种并行算法及其相关问题的解决方案,包括FFT算法、幂运算算法、背包问题等,通过理论分析和示例展示了这些算法的实现和性能。这些算法在不同的计算场景中具有重要的应用价值,能够提高计算效率和处理大规模数据的能力。
并行算法:原理、问题与解决方案
13. 并行算法在排序问题中的应用
在排序问题中,并行算法也有广泛的应用,下面将介绍几种排序算法的并行版本及相关分析。
13.1 顺序Shell排序的比较次数证明
顺序版本的Shell排序基于增量 $h_s$,其中 $h_{s + 1} = 3h_s + 1$,$h_0 = 1$,$0 \leq s < \lfloor\log_3(2N + 1)\rfloor - 1$。为了估计比较次数,我们分两种情况考虑:
-
当 $h_s > \sqrt{N}$ 时
:在每次使用增量 $h_s$ 运行算法时,内部循环的每次迭代执行 $O(\frac{N^2}{h_s^2})$ 次比较,算法运行次数为 $h_s$,所以该阶段的总比较次数为 $O(\frac{N^2}{h_s})$。
-
当 $h_s \leq \sqrt{N}$ 时
:考虑经过两次使用增量 $h_{s + 1}$ 和 $h_{s + 2}$ 的插入排序后的数组。根据 $h -$ 和 $k -$ 排序定理,对于所有能被 $h_{s + 1}$ 或 $h_{s + 2}$ 整除的 $i$,有 $a[j - i] \leq a[j]$。由于 $h_{s + 1}$ 和 $h_{s + 2}$ 互质,根据数论知识,所有不小于 $(h_{s + 1} - 1)(h_{s + 2} - 1) = 27h_s^2 + 9h_s$ 的自然数都可以表示为 $c_1h_{s + 1} + c_2h_{s + 2}$ 的形式。因此,在这个排序阶段,数组中的逆序对由距离不超过 $O(\frac{27h_s^2 + 9h_s}{h_s}) = O(h_s)$ 的元素形成,所以该阶段数组元素的比较次数估计为 $O(h_sN)$。
综合以上两种情况,所有算法运行后的最坏情况下的比较次数 $W(N)$ 为:
$W(N) = \sum_{s = 0}^{s^
} O(h_sN) + \sum_{s = s^
+ 1}^{\lfloor\log_3(2N + 1)\rfloor - 1} O(\frac{N^2}{h_s}) = O(N\sum_{s = 0}^{s^
} h_s) + O(N^2\sum_{s = s^
+ 1}^{\lfloor\log_3(2N + 1)\rfloor - 1} h_s^{-1})$
使用 $h_s = \frac{3^{s + 1} - 1}{2}$ 的显式表达式,可得:
$\sum_{s = 0}^{s^
} h_s \leq \frac{1}{2}\sum_{s = 0}^{s^
} 3^{s + 1} = \frac{1}{2}\frac{3^{s^
+ 2} - 1}{2} = O(N^{1/2})$
$\sum_{s = s^
+ 1}^{\lfloor\log_3(2N + 1)\rfloor - 1} h_s^{-1} \leq 2\sum_{s = s^
+ 1}^{\lfloor\log_3(2N + 1)\rfloor - 1} \frac{1}{3^{s + 2}} = \frac{2}{9}\frac{3^{-s^
- 3} - 3^{-\lfloor\log_3(2N + 1)\rfloor - 1}}{2} = O(N^{-1/2})$
最终得到顺序Shell排序的比较次数 $W(N) = O(N^{3/2})$。
13.2 并行Shell排序的执行时间估计
并行版本的Shell排序基于增量 $h_s$,使用 $p = \Theta(N)$ 个处理器。在第 $s$ 个排序阶段,增量为 $h_s$,$h_s$ 个处理器独立地对大小为 $\lfloor\frac{N}{h_s}\rfloor$ 或 $\lceil\frac{N}{h_s}\rceil$ 的 $h_s$ 个子数组进行排序。根据练习 12.48 的结果,每个子数组包含 $\Theta(\frac{N}{h_s})$ 个逆序对,所以第 $s$ 个排序阶段需要时间 $\Theta(\frac{N}{h_s})$。
对所有阶段求和,得到该算法最坏情况下的执行时间估计:
$W(N) = \sum_{s = 0}^{\lfloor\log_3(2N + 1)\rfloor - 1} \Theta(\frac{N}{h_s}) = N\Theta(\sum_{s = 0}^{\lfloor\log_3(2N + 1)\rfloor - 1} \frac{1}{h_s})$
当使用Pratt建议的增量序列 $h_s = 2^i3^j$(其中 $2^i3^j < N$,$0 \leq i \leq i_{max}$,$0 \leq j \leq j_{max}$)时,可利用几何级数公式估计 $\sum_{s = 0}^{\lfloor\log_3(2N + 1)\rfloor - 1} \frac{1}{h_s}$:
$\sum_{s = 0}^{\lfloor\log_3(2N + 1)\rfloor - 1} \frac{1}{h_s} = \sum_{i = 0}^{i_{max}} \sum_{j = 0}^{j_{max}} \frac{1}{2^i3^j} = \sum_{i = 0}^{i_{max}} \frac{1}{2^i} \sum_{j = 0}^{j_{max}} \frac{1}{3^j} = 3(1 - \frac{1}{2^{i_{max} + 1}})(1 - \frac{1}{3^{j_{max} + 1}})$
由于 $1 < h_{s_{max}} < N$,即 $1 < 2^{i_{max}} < N$ 和 $1 < 3^{j_{max}} < N$,所以 $\sum_{s = 0}^{\lfloor\log_3(2N + 1)\rfloor - 1} \frac{1}{h_s} = \Theta(1)$,因此基于Pratt增量序列的并行Shell排序的最坏情况执行时间为 $W(N) = \Theta(N)$。
14. 并行算法在搜索问题中的应用
在搜索问题中,并行算法也能发挥重要作用,下面介绍几种搜索算法的并行版本及相关改进。
14.1 并行搜索算法的改进
当数组 $list[1..N]$ 中的元素可以重复时,需要对并行搜索算法进行改进,以返回所寻找元素的第一次出现的编号。
-
并行顺序搜索(parSequentialSearch)
:在CREW和CRCW模型下,需要对算法进行修改,使其在找到第一个匹配元素后停止搜索。具体实现可以在每个处理器找到匹配元素后,通过共享内存或信号机制通知其他处理器停止搜索。
-
并行二分搜索(parBinarySearch)
:同样在CREW和CRCW模型下,需要调整算法逻辑。例如,在CRCW模型中,可以让多个处理器同时进行二分搜索,但在找到第一个匹配元素后,更新全局标记,其他处理器根据标记停止搜索。
14.2 在有序数组中搜索目标元素
在有序数组中搜索目标元素的问题,可以在CREW机器上使用 $O(N^{\epsilon})$ 个处理器($\epsilon > 0$)在 $O(1)$ 时间内解决。具体思路是将数组分成多个块,每个处理器负责一个块的搜索。由于数组有序,可以通过并行计算快速定位目标元素可能存在的块,然后在该块内进行精确搜索。
15. 并行算法在其他问题中的应用
除了排序和搜索问题,并行算法在其他问题中也有应用,下面介绍几个具体问题的并行算法。
15.1 寻找最大值问题
- 在具有 $N^2$ 个处理器的CRCW机器上 :可以设计一个算法在 $O(1)$ 时间内找到 $N$ 个数中的最大值。具体做法是让每个处理器比较两个数,并将较大的数保留。经过一轮比较后,剩下的数再进行比较,直到找到最大值。
- 在具有 $N$ 个处理器的CRCW机器上 :算法的执行时间为 $O(\log_2\log_2 N)$。可以采用分治策略,将 $N$ 个数分成多个小组,每个处理器负责一个小组的最大值计算,然后将小组的最大值再进行比较,逐步缩小范围,直到找到全局最大值。
15.2 确定不超过第 $k$ 大元素的集合
可以设计一个并行算法来确定数组 $list[1..N]$ 中不超过第 $k$ 大元素的集合,算法执行时间为 $\Theta(N^{1 - \epsilon})$,其中 $\epsilon = \frac{\log_2 p}{\log_2 N}$,$p$ 是可用计算节点的数量。具体步骤如下:
1. 随机选择一个元素作为基准元素。
2. 并行地将数组元素与基准元素比较,将小于等于基准元素的元素放在一边,大于基准元素的元素放在另一边。
3. 根据两边元素的数量,判断第 $k$ 大元素在哪一边,然后递归地在相应的子数组中继续寻找。
16. 离散正弦和余弦变换的并行算法
离散正弦和余弦变换在信号处理等领域有重要应用,下面介绍它们的并行算法。
16.1 离散正弦变换
向量 $x$ 的长度为 $N$ 且 $x_0 = 0$ 的正弦变换定义为 $(F_{\sin}[x]) n = \sum {k = 0}^{N - 1} x_k \sin(\frac{\pi kn}{N})$。可以将其简化为标准DFT,具体做法是构造一个长度为 $2N$ 的向量 $\tilde{x}$,其分量满足 $\tilde{x}[k] = x[k]$ ($0 \leq k \leq N - 1$),$\tilde{x}[k] = -x[2N - k]$ ($N + 1 \leq k \leq 2N - 1$),$\tilde{x}[N] = 0$。对 $\tilde{x}$ 应用离散傅里叶变换,得到的结果与正弦变换有一定关系。
并行算法的实现步骤如下:
1. 并行地构造向量 $\tilde{x}$。
2. 对 $\tilde{x}$ 应用并行DFT算法。
3. 根据DFT结果计算正弦变换的结果。
16.2 离散余弦变换
向量 $x$ 的长度为 $N + 1$ 的余弦变换定义为 $(F_{\cos}[x]) n = \frac{1}{2} (x_0 + (-1)^n x_N) + \sum {k = 1}^{N - 1} x_k \cos(\frac{\pi kn}{N})$。同样可以将其简化为标准DFT。
并行算法的实现步骤如下:
1. 并行地对向量 $x$ 进行预处理,计算 $\frac{1}{2} (x_0 + (-1)^n x_N)$ 部分。
2. 构造一个合适的向量,使其DFT与余弦变换相关。
3. 对构造的向量应用并行DFT算法。
4. 根据DFT结果计算余弦变换的结果。
17. 二维离散傅里叶变换的并行算法
二维离散傅里叶变换用于处理二维数组,其定义为 $(F[x]) {n_1,n_2} = \sum {k_1 = 0}^{N_1 - 1} \sum_{k_2 = 0}^{N_2 - 1} \omega_1^{k_1n_1} \omega_2^{k_2n_2} x_{k_1,k_2}$,其中 $\omega_1 = e^{\frac{2\pi i}{N_1}}$,$\omega_2 = e^{\frac{2\pi i}{N_2}}$。
并行算法的实现步骤如下:
1. 对数组 $x[0..(N_1 - 1), 0..(N_2 - 1)]$ 的每一行应用一维离散傅里叶变换。
2. 对经过行变换后的数组的每一列应用一维离散傅里叶变换。
通过以上步骤,可以得到二维离散傅里叶变换的结果。这种方法利用了二维离散傅里叶变换可以分解为两次一维离散傅里叶变换的性质,通过并行计算提高了计算效率。
18. 总结
并行算法在各个计算领域都有广泛的应用,如排序、搜索、离散傅里叶变换等。通过合理设计并行算法,可以显著提高计算效率,处理大规模数据。不同的并行算法适用于不同的计算场景和问题,需要根据具体情况选择合适的算法。
例如,在处理大规模数据的排序问题时,并行Shell排序可以利用多个处理器的优势,在较短的时间内完成排序任务;在搜索问题中,并行搜索算法可以通过并行计算快速定位目标元素。同时,离散傅里叶变换的并行算法在信号处理等领域也能提高处理速度。
在实际应用中,还需要考虑算法的复杂度、处理器数量、通信开销等因素,以优化算法的性能。未来,随着计算机硬件技术的不断发展,并行算法将在更多领域得到应用和发展,为解决复杂的计算问题提供更有效的手段。
下面是一些关键算法的流程总结:
|算法名称|流程说明|
| ---- | ---- |
|并行FFT算法|1. 计算内部和;2. 乘法运算;3. 再次FFT|
|Kung并行幂运算算法|1. 计算 $\omega_k$ 和 $\tilde{\omega}_k$;2. 计算 $y_k$;3. 计算 $z_k$;4. 求和 $Z$;5. 反转 $Z$;6. 得到最终答案|
|并行二维离散傅里叶变换算法|1. 对行应用一维DFT;2. 对列应用一维DFT|
graph TD;
A[输入数据] --> B[并行FFT算法];
B --> C[Kung并行幂运算算法];
C --> D[并行二维离散傅里叶变换算法];
D --> E[输出结果];
这个流程图展示了几个关键并行算法的执行顺序,从输入数据开始,依次经过并行FFT算法、Kung并行幂运算算法和并行二维离散傅里叶变换算法,最终输出结果。通过这些并行算法的组合,可以高效地处理复杂的计算任务。
超级会员免费看
10万+

被折叠的 条评论
为什么被折叠?



