并行算法:如何利用并行处理提高算法的执行效率

并行算法:如何利用并行处理提高算法的执行效率

算法的目的就是为了提高代码执行的效率,当算法无法继续优化的情况下,该如何进一步提高执行效率?如何借助并行计算的处理思想对算法进行改造?

并行排序

给大小为8GB的数据进行排序,且我们的内存可以一次性容纳这么多数据,对于排序来讲,最常用的就是时间复杂度为O(nlogn)的三种排序算法:归并排序、快速排序、堆排序,从算法层面无法继续优化了,而利用并行的处理思想,可以很轻松的将这个8GB数据排序问题的执行效率提高很多倍。

1 对归并排序并行化处理

可以将这8GB数据划分成16个小的数据集合,每个集合包含500MB的数据,用16个线程,并行的对这16个500MB的数据进行排序,这16个小集合分别排序完成之后,再将这16个有序集合合并

2 对快速排序并行化处理

通过扫描一遍数据找到数据所处范围区间,把这个区间从小到大划分成16个小区间,将8GB的数据划分到对应区间中,针对这16个小区间的数据,启动16个线程,并行的排序,等到16个线程都执行结束之后,得到的数据就是有序数据

两者用的都是分治的思想,对数据进行分片,然后并行处理,区别在于第一种思路是先随意对数据分片,排序之后再合并,第二种是先对数据按照大小划分区间,然后再排序,排完序不用再处理了

如果要排序的数据规模是1TB,问题是数据的读取效率,排序过程中,频繁的磁盘数据读取和写入,如何减少磁盘的IO操作,减少磁盘数据读取和写入的总量,变成优化的重点

并行查找

如果给动态数据结构构件索引,在数据不断加入的过程中,散列表的装载因子越来越大,需要动态扩容,如果我们给一个2GB大小的散列表进行扩容,扩展到原来的1.5倍,即3GB,内存的利用率只有60%,我们可以将数据随机分割成K份,每份中的数据只有原来的 1 k \frac{1}{k} ,针对这K个小数据集合分别构建散列表,当某个小散列表的装载因子过大的时候,只用单独对这个小散列表进行扩容,其他散列表不需要扩容,多个小散列表的处理方法比大散列表高效,当我们要查找某个数据的时候,只需要通过K个线程并行的在这K个散列表中查找数据,性能大大提高,添加数据的时候,可以将这个新数据放入装载因子最小的那个散列表中,有助于减少散列冲突

并行字符串匹配

在文本中查找某个关键词可以通过字符串匹配算法来实现,在一个不是很长的文本中查找关键词的时候,KMP、BM、RK、BF都很高效,但是处理超级大文本,如何加快匹配速度?

把大文本分割成K个小文本, 假设K=16,启动16个线程,并行的在这16个小文本中查找关键词,这样性能就提高了16倍,还有原本包含在这大文本中的关键词,被一分为二,分割成两个小文本中,导致尽管大文本中包含这个关键词,但在这16个小文本查找不到,需要进行特殊处理,如果关键词长度为M,在每个小文本的结尾和开始各取M个字符串,前一个小文本的末尾M个字符和后一个小文本开头的M个字符组成一个长度为2M的字符串,再拿关键词,在这个2M的字符串中重新查找

并行搜索

广度优先搜索是一种逐层搜索的搜索策略,基于当前这一层顶点,启动多个线程,并行搜索下一层的顶点,原来广度优先搜索的代码是通过一个队列来记录已经遍历到的但是没有扩展的顶点,现在需要两个队列来完成扩展顶点的工作

这两个队列分别是队列A,和队列B,多线程并行处理队列A中的顶点,并将扩展得到的顶点存储在队列B中,等队列A中顶点都扩展都完成之后,队列A清空,再并行扩展队列B中的顶点,将扩展出来的顶点存储在队列A中,循环使用,实现并行广度优先搜索算法

总结引申

如果我们有N个任务,希望能并行执行任务,但是各个任务有一定的依赖关系,如何根据依赖关系找出可以并行执行的任务?

用一个有向图来存储任务之间的依赖关系,然后用拓扑排序的思想来执行任务,每次都找入度为0 的,放在队列里,启动线程池开始执行,队列里的任务并行执行完毕,再次调用拓扑排序找到入度为0的任务放入队列,直到所有任务跑完

发布了75 篇原创文章 · 获赞 9 · 访问量 9164

猜你喜欢

转载自blog.csdn.net/ywangjiyl/article/details/104893040