ImageVerifierCode 换一换
格式:DOCX , 页数:18 ,大小:315.70KB ,
资源ID:3306500      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/3306500.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(并行归并排序.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

并行归并排序.docx

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

3、+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) otherk+ = arrayi+;while(j = end) otherk+ = arrayj+;for(k=be

4、gin; k=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_COUN

7、T 2#define 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; else return 0;void *GetCacheAlignedAddr(void *pAddr) int m = CACHE_LINE_SIZE; void *pRet = (void *)

8、(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 - 比较函数 param void *ppNewDa

9、ta - 存放归并后的数据 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 = nEnd2; j+ ) if ( (*func)(ppDat

10、ai, ppDataj) nEnd2 ) 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 -

11、无 */ void Serial_MergeSort(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(ppDat

12、a, 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_MergeSort(int *ppData, int nLen,

13、 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 = MAX_MERGE_TURN; nLoopCount = 1 n

14、Count ) nLoopCount = nLoopCount 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);

15、/将数据分成nLoopCount个小区间,并行地对每个区间进行串行排序#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; pn

16、Posi + i + 1 = nEnd1; /对排好序的各个相邻区间进行并行归并操作 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) f

17、or ( i = 0; i 1; /除以 nStep += nStep; 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; ret

18、urn; 测试文件:Test.cpp#includeMergeSort.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* tempArrForPar

19、allel = new intsize; srand(unsigned int)time(0); for(i = 0; i size; i+) tempArrForSeriali = rand(); tempArrForParalleli = tempArrForSeriali; ppDataForSeriali = tempArrForSerial + i; ppDataForParalleli = tempArrForParallel + i; cout 测试 size 个数字串行归并算法: endl; GetLocalTime(&lpsystimeStr); printf(开始时间:%u

20、年%u月%u日星期%u %u:%u:%u:%un,lpsystimeStr.wYear,lpsystimeStr.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月

21、%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.wSe

22、cond - lpsystimeStr.wSecond) * 1000; cout 共耗时: cost ms。 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,lpsystime

23、Str.wMonth,lpsystimeStr.wDay,lpsystimeStr.wDayOfWeek,lpsystimeStr.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.wMo

24、nth,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。

25、endl; cout 并行归并排序后前个数字:; for(i = 0; i 10; i+) if(0 = i % 6) cout endl; cout *ppDataForParalleli ; cout endl; cout endl; delete tempArrForSerial; delete tempArrForParallel; delete ppDataForSerial; delete ppDataForParallel;int main() testFunc(500); testFunc(10000); testFunc(50000); testFunc(100000); testFunc(500000); testFunc(800000); testFunc(1000000); return 0; 2、3运行结果2、4与串行归并排序的性能比较 由于并行归并排序算法采用了多线程在多个CPU上运行,其运行的时间复杂度在理论上应该是比串行归并算法的时间小很多,此处不做具体的分析。 不过需要指出的是,如果数据量非常小的话,串行和并行的归并排序算法在时间上的差异十分不明显。并且,由于并行归并排

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1