从串行算法到并行算法
分解模式:任务分解,数据分解,数据流分解
分解类型 | 设计 |
---|---|
任务 | 计算被分解为一组独立的任务,多个线程可以用任意顺序执行这些任务 将不同的行为分配给不同的线程 |
数据 | 程序需要处理一个大型数据集,并且可以对数据集中的每个元素进行独立计算 令多个线程对不同的数据集执行同样的操作 |
数据流 | 一个线程的输出是第二个线程的输入,需要特别关注消除开始和结束的延迟 |
-
任务分解:
园丁问题,让每个园丁负责不同的工作,共同经营同一块草地
-
数据分解:
生命游戏问题,将棋盘划分为多个区域(多个子棋盘),每一区域分配线程独立进行计算,最后再整合得到新棋盘
园丁问题,让每个园丁负责一小块草地
-
数据流分解:
由第一个任务引起的延迟为第二个任务产生一个暂停,在此之后两个任务才能并行运行。在计算机领域这样的模式经常发生。
生产者消费者模型
任务分解
核心:串行->并行
技巧:将计算密集的代码分解(计算量大或耗时多的代码)
任务并行的3个元素
-
任务和他们定义的方式()
-
任务间的依赖性
-
调度(任务怎样分配到执行单元)
- 静态调度(Static Scheduling)
- 计算开始时完成(提前人为定义好)
- 简单,开销小
- 动态调度(Dynamic Scheduling)
- 任务之间的计算量是可变的或者是不可预测的(例如:输入数据大小不确定)
- 随着计算的执行逐步把任务分配到各线程
- 共享容器(队列)方式(通过线程池管理)
- 静态调度(Static Scheduling)
任务的数据至少与执行单元的数目一样多,越多越好,确保调度时有很大灵活性
与各个任务相关联的计算量必须足够多,以此来抵消与任务管理和处理任何依赖性相关的开销(粒度)
分治策略
-
问题被划分为许多较小的子问题,独立求解每一个子问题,并将所有的子问题解决方案合并为整个问题的解决方案,从而求解整个问题
-
子问题可以直接求解,或者可以再使用相同的分治策略求解,产生一个整体的递归程序结构
几何分解模型
实际上就是数据的并行化
递归数据模式
问题涉及对递归的数据结构的操作(如:列表,树,图)
流水线模式
-
计算机不同粒度层次的流水线
- CPU中的指令流水线
- 向量处理(循环级流水线)
- 算法级流水线
- 信号处理
- 图
- shell程序
数据分解
-
问题中计算密集部分是围绕着一个大型数据结构的管理而组织的
-
相似的操作应用于数据结构的不同部分,这样可以相对的操作数据结构中的不同部分
如何将数据分解成数据块?
核心:结合数据块的形状与数据的交互方法进行设计
-
经验法则:体积与表面积比最大化
- 体积:计算的粒度(计算量)
- 表面积:需要交换数据的边界
a:粒度2*8=16,需要交换数据的边界为8,体积/表面积 = 2
b:粒度4*4=16,需要交换数据的边界为4,体积/表面积 = 4
则b比a更优
-
能否进行数据分解
- 基于数组的计算——>对数据进行划分
- 递归数据结构——>重建为树结构并计算
-
灵活性、效率、简单性讨论