




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、串行归并与并行归并排序算法一、 串行归并排序算法归并排序是一种很容易进行并行化的算法,因为归并的各个数据区间都是独立的,没有依赖关系。并且归并排序是一种速度比较快的排序,且是一种稳定的排序算法,排序速度与关键词初始排列无关。串行归并排序的算法大体的可以描述为:首先将要排序的表分成两个节点个数基本相等的子表,然后对每个子表进行排序,最后将排好序的两个子表合并成一个子表。在对子表进行排序时可以将子表再分解成两个节点数量基本相同的子表,当子表足够小时,也可以采用其他排序方法对子表进行排序,然后再对排好序的子表进行归并操作,最后将整个表排好序。1、1算法流程图并行归并排序算法的流程图:1、2代码分析#
2、include using namespace std;#define n 11int arrayn = 4, 67, 456, 23, 1, 78, 26, 222, 34, 432, 12 ; /待排序数组int othern; /辅助空间,用以暂存已经排序的数组元素void swap(int &a, int &b)int tmp = a;a = b;b = tmp;/* array 待排序数组* begin 数组开始的下标* end 数组最后一个元素的下标*/void mergesort(int *array, int begin, int end)if(end-begin+1 2) m
3、ergesort(array, begin, (end+begin)/2);mergesort(array, (end+begin)/2+1, end);int i = begin, j = (end+begin)/2+1, k=begin;while(i=(begin+end)/2 & j=end) if(arrayi arrayj)otherk+ = arrayi+;elseotherk+ = arrayj+;while(i = (begin+end)/2) otherk+ = arrayi+;while(j = end) otherk+ = arrayj+;for(k=begin; k=
4、end; +k) arrayk = otherk;else if(arrayend arraybegin) swap(arrayend, arraybegin);void output(int *array, int n)for(int i=0; in; +i)coutarrayi ;coutendl;int main()cout串行归并排序算法endlthe numbers are: ;output(array, n);mergesort(array, 0, n-1);couti;return 0;1、3运行结果1、4复杂度分析通过算法分析很容易发现串行归并排序算法的时间复杂度地推公式为:这
5、是一个时间复杂度的递推公式,我们需要消去等号右侧的t(n),把t(n)写成n的函数。其实符合一定条件的recurrence的展开有数学公式可以套,这里我们略去严格的数学证明,只是从直观上看一下这个递推公式的结果。当n=1时可以设,当n1时可以设,我们取c1和c2中较大的一个设为c,把原来的公式改为:参照主定理公式,可以知道当n1时,有以下等式成立:同时又有下面的等式成立:则有t(n)满足主定理公式的第二种情况,也即是t(n)的时间复杂度为:二、 并行归并排序算法由串行归并排序算法可知,归并的各个数据区间都是独立的,没有依赖关系。因此归并排序是一种很容易进行并行化的算法。其方案是先将待排序区间划
6、分成若干个相等的小区间,然后并行地对这些小区间进行排序,最后再通过归并的方法将所有排好序的小区间归并成一个有序系列。由于归并时是一层层向上进行的,因此需要将区间划分成个小区间,这样第1轮归并时,可以将个小区间归并成个区间。这样过k轮归并操作后就归并成一个有序的大区间。这也正是并行归并排序的算法思想。2、1算法流程图并行归并排序算法的思想可以通过下面的流程图表示:2、2代码分析功能函数头文件:mergesort.h#define max_merge_turn 24 #define min_parallel_sort_count 3#define min_merge_count 2#define
7、cache_line_size 64typedef unsigned int uint;#include#include#include#include#includeusing namespace std;int compare(int* one, int* two)if(*one *two)return 1;else if(*two *one)return -1;elsereturn 0;void *getcachealignedaddr(void *paddr) int m = cache_line_size; void *pret = (void *)(uint)paddr+m-1)&
8、(-m); return pret;/* 串行归并函数归并好的数据存放在输出参数ppnewdata中param void *ppdata - 待归并的数据 param int nstart1 - 第个区间的开始位置(包括nstart1) param int nend1 - 第个区间的结束位置(包括nend1) param int nstart2 - 第个区间的开始位置(包括nstart2) param int nend2 - 第个区间的结束位置(包括nend2) param comparefunc func - 比较函数 param void *ppnewdata - 存放归并后的数据 ret
9、urn void* - 返回归并后的数据指针(等于ppnewdata) */ int* serial_merge(int *ppdata, int nstart1, int nend1, int nstart2, int nend2, int(*func)(int*, int*) , int *ppnewdata) int i, j, k; i = nstart1; j = nstart2; k = nstart1; for( i = nstart1; i = nend1;) for ( ; j = nend2; j+ ) if ( (*func)(ppdatai, ppdataj) nend
10、2 ) for ( ; i nend1 ) for ( ; j = nend2; j+ ) ppnewdatak = ppdataj; +k; for(i = nstart1; i = nend2; i+)ppdatai = ppnewdatai;return ppdata; /* 串行归并排序函数param void *ppdata - 待排序数据 param int nbegin - 排序区间的开始位置 param int nend - 排序区间的结束位置 param comparefunc func - 数据大小比较函数 return void - 无 */ void serial_me
11、rgesort(int *ppdata, int nbegin, int nend, int(*func)(int*, int*) if ( nend - nbegin *ppdatanend)temp = ppdatanbegin;ppdatanbegin = ppdatanend;ppdatanend = temp;return; int* tempdata = new int*nend - nbegin + 1;int i;int tmpint = 0;for(i = 0; i 1; /除以serial_mergesort(ppdata, nbegin, nmid, func); ser
12、ial_mergesort(ppdata, nmid+1, nend, func); serial_merge(ppdata, nbegin, nmid, nmid+1, nend, func, tempdata); /* 并行归并快速排序函数param void *ppdata - 待排序数据 param int nlen - 待排序数据长度 param comparefunc func - 数据比较回调函数 return void - 无 */ void parallel_mergesort(int *ppdata, int nlen, int(*func)(int*, int*) int
13、 i, k; int nstep; int nloopcount; int ncore; int nstart1, nend1; if ( nlen min_parallel_sort_count ) serial_mergesort(ppdata, 0, nlen - 1, func ); return; ncore = omp_get_num_procs(); int ncount = nlen / min_parallel_sort_count; int nturn = max_merge_turn; nloopcount = 1 ncount ) nloopcount = nloopc
14、ount 1; /除以-nturn; /判断nturn是否为奇数if ( (nloopcount ncore) & (nturn 0x1) & (nturn & 0x1) = 0x1) ) -nturn; /把nturn变成偶数,便于后面不拷贝数据nloopcount = nloopcount 1; nstep = nlen / nloopcount; int *p = new intnloopcount*2 + cache_line_size; int *pnpos = (int *)getcachealignedaddr(p); /将数据分成nloopcount个小区间,并行地对每个区间进
15、行串行排序#pragma omp parallel for private(nstart1, nend1) num_threads(ncore) for ( i = 0; i nloopcount; i+) nstart1 = i * nstep; nend1 = nstart1 + nstep - 1; if ( i = nloopcount - 1 ) nend1 = nlen - 1; serial_mergesort(ppdata, nstart1, nend1, func); pnposi + i = nstart1; pnposi + i + 1 = nend1; /对排好序的各个
16、相邻区间进行并行归并操作int *pp = new int *nlen + cache_line_size; int * ppoutdata = (int *)getcachealignedaddr(int *)pp); int * ppmergedata = ppdata; int * pptempoutdata = ppoutdata; int * ppswap; nstep = 2; for ( k = 0; k nturn; k+ ) #pragma omp parallel for num_threads(ncore) for ( i = 0; i 1; /除以nstep += ns
17、tep; ppswap = ppmergedata; ppmergedata = pptempoutdata; pptempoutdata = ppswap; /将数据写回到ppdata中,如果nturn为偶数则下面的判断内的循环不会被执行if ( ppmergedata = ppoutdata ) #pragma omp parallel for num_threads(ncore) for ( i = 0; i nlen; i+ ) ppdatai = ppoutdatai; delete p; delete pp; return; 测试文件:test.cpp#includemergeso
18、rt.h/test mergesortvoid testfunc(int size)sleep(1000);/防止srand取同样的值int i;int cost;systemtime lpsystimestr;systemtime lpsystimeend;int* ppdataforserial = new int*size;int* ppdataforparallel = new int*size;int* temparrforserial = new intsize;int* temparrforparallel = new intsize;srand(unsigned int)tim
19、e(0);for(i = 0; i size; i+)temparrforseriali = rand();temparrforparalleli = temparrforseriali;ppdataforseriali = temparrforserial + i;ppdataforparalleli = temparrforparallel + i;cout 测试 size 个数字串行归并算法: endl;getlocaltime(&lpsystimestr); printf(开始时间:%u年%u月%u日星期%u %u:%u:%u:%un,lpsystimestr.wyear,lpsyst
20、imestr.wmonth,lpsystimestr.wday,lpsystimestr.wdayofweek,lpsystimestr.whour,lpsystimestr.wminute,lpsystimestr.wsecond,lpsystimestr.wmilliseconds); serial_mergesort(ppdataforserial, 0, size - 1, compare);getlocaltime(&lpsystimeend); printf(结束时间:%u年%u月%u日星期%u %u:%u:%u:%un,lpsystimeend.wyear,lpsystimeen
21、d.wmonth,lpsystimeend.wday,lpsystimeend.wdayofweek,lpsystimeend.whour,lpsystimeend.wminute,lpsystimeend.wsecond,lpsystimeend.wmilliseconds); cost = lpsystimeend.wmilliseconds - lpsystimestr.wmilliseconds;if(cost = 0)cost = cost + (lpsystimeend.wsecond - lpsystimestr.wsecond) * 1000;cout 共耗时: cost ms
22、。 endl;cout 串行归并排序后前个数字:;for(i = 0; i 10; i+)if(0 = i % 6)cout endl;cout *ppdataforseriali ;cout endl;cout endl;cout 测试 size 个数字并行归并算法: endl;getlocaltime(&lpsystimestr); printf(开始时间:%u年%u月%u日星期%u %u:%u:%u:%un,lpsystimestr.wyear,lpsystimestr.wmonth,lpsystimestr.wday,lpsystimestr.wdayofweek,lpsystimes
23、tr.whour,lpsystimestr.wminute,lpsystimestr.wsecond,lpsystimestr.wmilliseconds); parallel_mergesort(ppdataforparallel, size, compare);getlocaltime(&lpsystimeend); printf(结束时间:%u年%u月%u日星期%u %u:%u:%u:%un,lpsystimeend.wyear,lpsystimeend.wmonth,lpsystimeend.wday,lpsystimeend.wdayofweek,lpsystimeend.whour,lpsystimeend.wminute,lpsystimeend.wsecond,lpsystimeend.wmilliseconds); cost = lpsystimeend.wmilliseconds - lpsystimestr.wmilliseconds;if(cost = 0)cost = cost + (lpsystimeend.wsecond - lpsystimestr
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 计算机软件编程基础试题集及答案解析
- 移动医疗健康应用软件授权使用协议
- 物业管理装修协议书
- 产品市场推广策略与操作手册编制
- 设备分期付款销售合同
- 初中生心理健康故事
- 国际物流与运输合同
- 知识产权转让协议签署细节说明
- 物流行业个性化配送优化方案
- 初中生职业规划课程心得
- 照明灯具统计表
- 杭州市居住房屋出租安全管理若干规定
- 2022年江西工业贸易职业技术学院职业适应性测试题库及答案解析
- 住建部《建筑业10项新技术(2017版)》解读培训课件
- 给水排水管道工程质量通病以及防治
- 计算机视觉全套课件
- 中国联通IMS接口规范 第三分册:Sh接口 V1.0
- protel完全教程(原理图部分)
- 迎泽公园文化广场歌词汇集
- 环境化学物的毒性作用及其影响因素
- Q∕GDW 12176-2021 反窃电监测终端技术规范
评论
0/150
提交评论