版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、精选优质文档-倾情为你奉上串行归并与并行归并排序算法一、 串行归并排序算法归并排序是一种很容易进行并行化的算法,因为归并的各个数据区间都是独立的,没有依赖关系。并且归并排序是一种速度比较快的排序,且是一种稳定的排序算法,排序速度与关键词初始排列无关。串行归并排序的算法大体的可以描述为:首先将要排序的表分成两个节点个数基本相等的子表,然后对每个子表进行排序,最后将排好序的两个子表合并成一个子表。在对子表进行排序时可以将子表再分解成两个节点数量基本相同的子表,当子表足够小时,也可以采用其他排序方法对子表进行排序,然后再对排好序的子表进行归并操作,最后将整个表排好序。1、1算法流程图并行归并排序算法
2、的流程图:1、2代码分析#include <iostream>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, i
3、nt begin, int end)if(end-begin+1 > 2) MergeSort(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
4、) otherk+ = arrayi+;while(j <= end) otherk+ = arrayj+;for(k=begin; k<=end; +k) arrayk = otherk;else if(arrayend < arraybegin) Swap(arrayend, arraybegin);void Output(int *array, int n)for(int i=0; i<n; +i)cout<<arrayi<<" "cout<<endl;int main()cout<<"
5、串行归并排序算法"<<endl<<"the numbers are: "Output(array, N);MergeSort(array, 0, N-1);cout<<"the sorted result:"Output(array, N);int i;cin>>i;return 0;1、3运行结果1、4复杂度分析通过算法分析很容易发现串行归并排序算法的时间复杂度地推公式为:这是一个时间复杂度的递推公式,我们需要消去等号右侧的T(n),把T(n)写成n的函数。其实符合一定条件的Recurrence
6、的展开有数学公式可以套,这里我们略去严格的数学证明,只是从直观上看一下这个递推公式的结果。当n=1时可以设,当n>1时可以设,我们取c1和c2中较大的一个设为c,把原来的公式改为:参照主定理公式,可以知道当n>1时,有以下等式成立:同时又有下面的等式成立:则有T(n)满足主定理公式的第二种情况,也即是T(n)的时间复杂度为:二、 并行归并排序算法由串行归并排序算法可知,归并的各个数据区间都是独立的,没有依赖关系。因此归并排序是一种很容易进行并行化的算法。其方案是先将待排序区间划分成若干个相等的小区间,然后并行地对这些小区间进行排序,最后再通过归并的方法将所有排好序的小区间归并成一个
7、有序系列。由于归并时是一层层向上进行的,因此需要将区间划分成个小区间,这样第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 CACHE_LINE_SIZE 64typedef unsigned int UINT;#include&
8、lt;omp.h>#include<windows.h>#include<iostream>#include<cstdlib>#include<ctime>using 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 *p
9、Ret = (void *)(UINT)pAddr+m-1)&(-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 - 比较函数 p
10、aram void *ppNewData - 存放归并后的数据 return 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 <= nEnd
11、2; j+ ) if ( (*func)(ppDatai, ppDataj) < 0 ) ppNewDatak = ppDatai; +k;i+;break; else ppNewDatak = ppDataj; +k; /如果j已经到了尾部if ( j > nEnd2 ) for ( ; i <= nEnd1; i+ ) ppNewDatak = ppDatai; +k; break; if ( i > nEnd1 ) for ( ; j <= nEnd2; j+ ) ppNewDatak = ppDataj; +k; for(i = nStart1; i &l
12、t;= nEnd2; i+)ppDatai = ppNewDatai;return ppData; /* 串行归并排序函数param void *ppData - 待排序数据 param int nBegin - 排序区间的开始位置 param int nEnd - 排序区间的结束位置 param COMPAREFUNC func - 数据大小比较函数 return void - 无 */ void Serial_MergeSort(int *ppData, int nBegin, int nEnd, int(*func)(int*, int*) if ( nEnd - nBegin <
13、 MIN_MERGE_COUNT ) int* temp;if(*ppDatanBegin > *ppDatanEnd)temp = ppDatanBegin;ppDatanBegin = ppDatanEnd;ppDatanEnd = temp;return; int* tempData = new int*nEnd - nBegin + 1;int i;int tmpInt = 0;for(i = 0; i < nEnd - nBegin + 1; i+)tempDatai = &tmpInt;int nMid = (nBegin + nEnd) >> 1;
14、 /除以Serial_MergeSort(ppData, nBegin, nMid, func); Serial_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_MergeS
15、ort(int *ppData, int nLen, int(*func)(int*, int*) int 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 = M
16、AX_MERGE_TURN; nLoopCount = 1 << nTurn; /nLoopCount等于的nTurn次方while ( nLoopCount > nCount ) nLoopCount = nLoopCount >> 1; /除以-nTurn; /判断nTurn是否为奇数if ( (nLoopCount > nCore) && (nTurn > 0x1) && (nTurn & 0x1) = 0x1) ) -nTurn; /把nTurn变成偶数,便于后面不拷贝数据nLoopCount = nLo
17、opCount >> 1; nStep = nLen / nLoopCount; int *p = new intnLoopCount*2 + CACHE_LINE_SIZE; int *pnPos = (int *)GetCacheAlignedAddr(p); /将数据分成nLoopCount个小区间,并行地对每个区间进行串行排序#pragma omp parallel for private(nStart1, nEnd1) num_threads(nCore) for ( i = 0; i < nLoopCount; i+) nStart1 = i * nStep; n
18、End1 = nStart1 + nStep - 1; if ( i = nLoopCount - 1 ) nEnd1 = nLen - 1; Serial_MergeSort(ppData, nStart1, nEnd1, func); pnPosi + i = nStart1; pnPosi + i + 1 = nEnd1; /对排好序的各个相邻区间进行并行归并操作int *pp = new int *nLen + CACHE_LINE_SIZE; int * ppOutData = (int *)GetCacheAlignedAddr(int *)pp); int * ppMergeDa
19、ta = 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 < nLoopCount-1; i += 2 ) int nPos = i * nStep; Serial_Merge(ppMergeData, pnPosnPos, pnPosnPos+1, pnPosnPos+nStep, pnPosnPos+nStep+1,fun
20、c, ppTempOutData); pnPosnPos+1 = pnPosnPos+nStep+1; nLoopCount = nLoopCount >> 1; /除以nStep += nStep; ppSwap = ppMergeData; ppMergeData = ppTempOutData; ppTempOutData = ppSwap; /将数据写回到ppData中,如果nTurn为偶数则下面的判断内的循环不会被执行if ( ppMergeData = ppOutData ) #pragma omp parallel for num_threads(nCore) for
21、 ( i = 0; i < nLen; i+ ) ppDatai = ppOutDatai; delete p; delete pp; return; 测试文件:Test.cpp#include"MergeSort.h"/test MergeSortvoid testFunc(int size)Sleep(1000);/防止srand取同样的值int i;int cost;SYSTEMTIME lpsystimeStr;SYSTEMTIME lpsystimeEnd;int* ppDataForSerial = new int*size;int* ppDataForP
22、arallel = new int*size;int* tempArrForSerial = new intsize;int* tempArrForParallel = new intsize;srand(unsigned int)time(0);for(i = 0; i < size; i+)tempArrForSeriali = rand();tempArrForParalleli = tempArrForSeriali;ppDataForSeriali = tempArrForSerial + i;ppDataForParalleli = tempArrForParallel +
23、i;cout << "测试" << size << "个数字串行归并算法:" << endl;GetLocalTime(&lpsystimeStr); printf("开始时间:%u年%u月%u日星期%u %u:%u:%u:%un",lpsystimeStr.wYear,lpsystimeStr.wMonth,lpsystimeStr.wDay,lpsystimeStr.wDayOfWeek,lpsystimeStr.wHour,lpsystimeStr.wMinute,lpsy
24、stimeStr.wSecond,lpsystimeStr.wMilliseconds); Serial_MergeSort(ppDataForSerial, 0, size - 1, compare);GetLocalTime(&lpsystimeEnd); printf("结束时间:%u年%u月%u日星期%u %u:%u:%u:%un",lpsystimeEnd.wYear,lpsystimeEnd.wMonth,lpsystimeEnd.wDay,lpsystimeEnd.wDayOfWeek,lpsystimeEnd.wHour,lpsystimeEnd.w
25、Minute,lpsystimeEnd.wSecond,lpsystimeEnd.wMilliseconds); cost = lpsystimeEnd.wMilliseconds - lpsystimeStr.wMilliseconds;if(cost <= 0)cost = cost + (lpsystimeEnd.wSecond - lpsystimeStr.wSecond) * 1000;cout << "共耗时:" << cost << "ms。" << endl;cout <<
26、 "串行归并排序后前个数字:"for(i = 0; i < 10; i+)if(0 = i % 6)cout << endl;cout << *ppDataForSeriali << " "cout << endl;cout << endl;cout << "测试" << size << "个数字并行归并算法:" << endl;GetLocalTime(&lpsystimeStr); prin
27、tf("开始时间:%u年%u月%u日星期%u %u:%u:%u:%un",lpsystimeStr.wYear,lpsystimeStr.wMonth,lpsystimeStr.wDay,lpsystimeStr.wDayOfWeek,lpsystimeStr.wHour,lpsystimeStr.wMinute,lpsystimeStr.wSecond,lpsystimeStr.wMilliseconds); Parallel_MergeSort(ppDataForParallel, size, compare);GetLocalTime(&lpsystimeEn
28、d); 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 + (lpsystimeE
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 快递乡镇加盟合同范本
- 产品研发销售合同范本
- 聘请厨师做饭合同范本
- 合伙修厂房合同范本
- 支付借呗合同(标准版)
- 外卖机器转让合同范本
- 线上运营合作合同范本
- 北京麦田房产合同范本
- 涂料防水简易合同范本
- 2026年建筑行业创新报告协议
- 【二年级】2025秋季期中家长会:让每一颗小小的种子【课件】
- 2026年车友会活动合同
- DB33∕T 2476-2022 长期护理保障失能等级评估规范
- 学校病媒生物防制培训
- 七年级上期中家长会《家校携手共前行一路向阳待花开》课件
- 2025年国家公务员《行测》真题及答案
- 路面铣刨工程规范施工方案
- 医疗器械质量管理体系内审员职业发展
- 掼蛋活动方案
- 2025年三元锂电池行业分析报告及未来发展趋势预测
- 蛋糕房员工合同
评论
0/150
提交评论