付费下载
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
OpenMP程序设计的两个小技巧1、动态设置并行循环的线程数量在实际情况中,程序可能运行在不同的机器环境里,有些机器是双核,有些机器是4核甚至更多核。并且未来硬件存在升级的可能,CPU核数会变得越来越多。如何根据机器硬件的不同来自动设置合适的线程数量就显得很重要了,否则硬件升级后程序就得进行修改,那将是一件很麻烦的事情。比如刚开始在双核系统中开发的软件,线程数量缺省都设成2,那么当机器升级到4核或8核以后,线程数量就不能满足要求了,除非修改程序。线程数量的设置除了要满足机器硬件升级的可扩展性外,还需要考虑程序的可扩展性,当程序运算量增加或减少后,设置的线程数量仍然能够满足要求。显然这也不能通过设置静态的线程数量来解决。在具体计算需要使用多少线程时,主要需要考虑以下两点:1)当循环次数比较少时,如果分成过多数量的线程来执行,可能会使得总运行时间高于较少线程或一个线程执行的情况。并且会增加能耗。2)如果设置的线程数量远大于CPU核数的话,那么存在着大量的任务切换和调度等开销,也会降低整体效率。那么如何根据循环的次数和CPU核数来动态地设置线程的数量呢?下面以一个例子来说明动态设置线程数量的算法,假设一个需要动态设置线程数的需求为:1、以多个线程运行时的每个线程运行的循环次数不低于4次2、总的运行线程数最大不超过2倍CPU核数下面代码便是一个实现上述需求的动态设置线程数量的例子constintMIN_ITERATOR_NUM=4;intncore=omp_get_num_procs();//获取执行核的数量intmax_tn=n/MIN_ITERATOR_NUM;inttn=max_tn>2*ncore?2*ncore:max_tn;//tn表示要设置的线程数量#pragmaompparallelforif(tn>1)num_threads(tn)for(i=0;i<n;i++){printf("ThreadId=%ld\n",omp_get_thread_num());//Dosomeworkhere}在上面代码中,根据每个线程运行的循环次数不低于4次,先计算出最大可能的线程数max_tn,然后计算需要的线程数量tn,tn的值等于max_tn和2倍CPU核数中的较小值。然后在parallelfor构造中使用if子句来判断tn是否大于1,大于1时使用单个线程,否则使用tn个线程,,这样就使得设置的线程数量满足了需求中的条件。比如在一个双核CPU上,n=64,最终会以2倍CPU核数(4个)线程运行,而不会以max_tn=64/4=16个线程运行。在实际情况中,当然不能每个循环都象上面一样写几行代码来计算一遍,可以将其写成一个独立的功能函数如下:constintg_ncore=omp_get_num_procs();//获取执行核的数量/**计算循环迭代需要的线程数量根据循环迭代次数和CPU核数及一个线程最少需要的循环迭代次数来计算出需要的线程数量,计算出的最大线程数量不超过CPU核数@paramintn-循环迭代次数@paramintmin_n-单个线程需要的最少迭代次数@returnint-线程数量*/intdtn(intn,intmin_n){intmax_tn=n/min_n;inttn=max_tn>g_ncore?g_ncore:max_tn;//tn表示要设置的线程数量if(tn<1){tn=1;}returntn;}这样每次并行化循环时就可以直接使用函数dtn()来获取合适的线程数量,前面的代码可以简写成如下形式:#pragmaompparallelfornum_threads(dtn(n,MIN_ITERATOR_NUM))for(i=0;i<n;i++){printf("ThreadId=%ld\n",omp_get_thread_num());//Dosomeworkhere}当然具体设置多少线程要视情况而定的,一般情况下线程数量刚好等于CPU核数可以取得比较好的性能,因为线程数等于CPU核数时,每个核执行一个任务,没有任务切换开销。2、嵌套循环的并行化在嵌套循环中,如果外层循环迭代次数较少时,如果将来CPU核数增加到一定程度时,创建的线程数将可能小于CPU核数。另外如果内层循环存在负载平衡的情况下,很难调度外层循环使之达到负载平衡。下面以矩阵乘法作为例子来讲述如何将嵌套循环并行化,以满足上述扩展性和负载平衡需求。一个串行的矩阵乘法的函数代码如下:/**矩阵串行乘法函数@paramint*a-指向要相乘的第个矩阵的指针@paramintrow_a-矩阵a的行数@paramintcol_a-矩阵a的列数@paramint*b-指向要相乘的第个矩阵的指针@paramintrow_b-矩阵b的行数@paramintcol_b-矩阵b的列数@paramint*c-计算结果的矩阵的指针@paramintc_size-矩阵c的空间大小(总元素个数)@returnvoid-无*/voidMatrix_Multiply(int*a,introw_a,intcol_a,int*b,introw_b,intcol_b,int*c,intc_size){if(col_a!=row_b||c_size<row_a*col_b){return;}inti,j,k;//#pragmaompforprivate(i,j,k)for(i=0;i<row_a;i++){introw_i=i*col_a;introw_c=i*col_b;for(j=0;j<col_b;j++){c[row_c+j]=0;for(k=0;k<row_b;k++){c[row_c+j]+=a[row_i+k]*b[k*col_b+j];}}}}如果在外层循环前加上OpenMP的for语句时,它就变成了一个并行的矩阵乘法函数,但是这样简单地将其并行化显然无法满足前面所述的扩展性需求。其实可以采用一个简单的方法将最外层循环和第2层循环合并成一个循环,下面便是采用合并循环后的并行实现。voidParallel_Matrix_Multiply(int*a,introw_a,intcol_a,int*b,introw_b,intcol_b,int*c,intc_size){if(col_a!=row_b){return;}inti,j,k;intindex;intborder=row_a*col_b;i=0;j=0;#pragmaompparallelprivate(i,j,k)num_threads(dtn(border,1))for(index=0;index<border;index++){i=index/col_b;j=index%col_b;introw_i=i*col_a;introw_c=i*col_b;c[row_c+j]=0;for(k=0;k<row_b;k++){c[row_c+j]+=a[row_i+k]*b[k*col_b+j];}}}从上面代码可以看出,合并后的循环边界border=row_a*col_b;即等于原来两个循环边界之积,然后在循环中计算出原来的外层循环和第2层循环的迭
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年冷链运输作业指导书
- 健康档案管理制度(7篇)
- 2026年克拉玛依职业技术学院单招职业技能测试题库(含答案详解)
- 2026年内蒙古美术职业学院单招职业技能考试题库含答案详解(黄金题型)
- 2026年内蒙古化工职业学院单招职业技能测试题库带答案详解(综合卷)
- 2026年内蒙古民族幼儿师范高等专科学校单招职业倾向性测试题库带答案详解(基础题)
- 2026年南通职业大学单招职业技能考试题库含答案详解(培优b卷)
- 2026年兰州石化职业技术大学单招职业适应性测试题库含答案详解(满分必刷)
- 2026年内蒙古商贸职业学院单招职业技能测试题库附参考答案详解(模拟题)
- 2026年信阳涉外职业技术学院单招职业适应性考试题库含答案详解(综合卷)
- 血液灌流在维持性血液透析患者中的临床应用专家共识(2025年版)
- 齐成控股集团招聘笔试题库2026
- 菏泽医专综评试题及答案
- 2026年交管12123驾照学法减分题库(考试直接用)
- 传染病影像学课件
- 国企投融资课件
- 人工智能优化血管血流动力学随访管理策略
- 全国项目管理标准体系建设指南(2025版)
- 年龄段护理知识培训内容课件
- 八年级语文下册必背古诗文(字帖描红)
- GE多排螺旋CT培训教材
评论
0/150
提交评论