首页 > 其他分享 >OpenMP优化调研系列文章(3)

OpenMP优化调研系列文章(3)

时间:2023-07-07 17:32:07浏览次数:51  
标签:int omp pragma OpenMP 优化 parallel 调研

作者介绍

谢依晖

湖南大学硕士研究生在读,

本科毕业于湖南大学计算机科学与技术专业

OpenMP优化调研系列文章(3)_#pragma

本文调研了4篇与OpenMP优化相关的文献,对优化点分析如下:

面向Open64的OpenMP程序优化[1]

跨越过程边界的并行区重构

Open64有着过程间分析优化部件,因此可以知道哪些函数使用了被调函数,从而可以通过在使用被调函数处放置合适的编译指导语句来完成并行区重构。

这样做的好处是:

  1. 进一步扩大并行块的大小;
  2. 将并行块提升到调用函数中,便于进一步对调用函数中的并行块合并。

以下给出例子:

`

program main
   call sub_procedure
 endsubroutine sub_procedure
 !$omp parallel
   P
 !$omp end parallel
 end
 `优化后:
`program main
 !$omp parallel
   call sub_procedure
 !$omp end parallel
 endsubroutine sub_procedure
   P
 end
 `

OpenMP并行编程模型与性能优化方法的研究及应用[2]

Cache命中率优化

  • 数组合并:定义两个数组val[N]和key[N],在顺序访问val[i]和key[i]时可能会导致Cache冲突失效,若改为struct merge{key, val}就可以通过提高空间局部性减少Cache失效次数。
  • 循环交换:C按行存储而Fortran按列存储,应根据存储的顺序来访问。
  • 提取关键数据:提取关键数据可以减少重复存取的数据,例如在排序中用关键字和指针代替整个记录排序,这样就能让Cache无需存放无关数据而提高命中率。
  • 分块:对于极大大小的数组,要在Cache中一次容纳整个数组是有困难的,但可以将数组分为多块,可有效降低Cache失效率。

循环调度优化

在OpenMP中可对并行循环指定调度方案,以将每个迭代分配给多个工作线程执行。其一般形式如下:

#pragma omp for schedule(schedule_name, chunk_size) for(i = 0; i < N; i++) 

OpenMP编译与优化技术研究[3]

论文中给出了一种使用启发式规则来估计各种额外开销和调度参数的关系,得到一个线性不等式组,可以通过求解该不等式组得到较优的调度参数。

变量属性的优化

在OpenMP语句中每一次对变量的声明都对应一次新的地址分配。给出以下例子:

#pragma omp parallel {   #pragma omp for private(a)   {...}   #pragma omp for private(a)   {...} } 

在如上代码中,编译器会为每个循环分配一个单独的私有变量,而优化后的代码如下所示:

#pragma omp parallel private(a) {   #pragma omp for   {...}   #pragma omp for   {...} } 

How to Get Good Performance by Using OpenMP[4]

去除依赖

对于某些循环语句,存在依赖而导致无法使用OpenMP优化,但是这其中的某些依赖可以通过修改代码去除依赖而使用OpenMP运行代码。

下列循环存在反依赖:

for(int i = 0; i < n; i++) {   x = (b[i] + c[i]) / 2;   a[i] = a[i + 1] + x; } 

除去循环之间的依赖后:

#pragma omp parallel for shared(a, a_copy) for(int i = 0; i < n; i++) {   a_copy[i] = a[i + 1]; } #pragma omp parallel for shared(a, a_copy) private(x) for(int i = 0; i < n; i++) {   x = (b[i] + c[i]) / 2;   a[i] = a_copy[i] + x; } 

下列循环存在流依赖:

for(int i = 1; i < n; i++) {   b[i] = b[i] + a[i - 1];   a[i] = a[i] + c[i]; } 

在loop skewing之后:

b[1] = b[1] + a[0] #pragma omp parallel for shared(a, b, c) for(int i = 1; i < n - 1; i++) {   a[i] = a[i] + c[i];   b[i + 1] = b[i + 1] + a[i]; } a[n - 1] = a[n - 1] + c[n - 1]; 

负载不均衡

下段代码使用流水线形式处理,以块的形式读取数据,然后处理每个块并在下一个块之前将结果写入磁盘,造成极差的负载均衡。

for(i = 0; i < N; i++) {   readfromfile(i, ...);   for(int j = 0; j < processingnum; j++) {     processdata(); //lots of work   }   writetofile(i); } 

接下来这段代码使用动态调度来重叠I/O和处理数据,将上述流水线代码并行化。

`#pragma omp parallel
 {
   /* preload data to be used in first iteration of the i-loop /
   #pragma omp single
     {ReadFromFile(O,...);}
   for (i=0; i<N; i++) {
     / preload data for next iteration of the i-loop /
   #pragma omp single nowait
     {ReadFromFile(i+1...);}
   #pragma omp for schedule(dynamic)
     for (j=0; j<ProcessingNum; j++)
       ProcessChunkOfData(); / here is the work /
   / there is a barrier at the end of this loop /
   #pragma omp single nowait
     {writeResultsToFile(i);}
   } / threads immediately move on to next iteration of i-loop /
 } / one parallel region encloses all the work */`

解决伪共享问题

int a[Nthreads][cache_line_size]; #pragma omp parallel for shared(Nthreads, a) schedule(static,1) for (int i = 0; i < Nthreads; i++)  a[i] += i;

一般情况下,int型变量占四个字节,A[0]和A[1]的地址只差四个字节,小于一个Cache行,它们有着极大的可能在同一Cache行内,从而导致同时更新不同处理器的相同Cache行中的单个元素会导致整个Cache行无效。

对于False sharing问题,一般可以通过填充数组来优化。

int a[Nthreads][cache_line_size]; #pragma omp parallel for shared(Nthreads, a) schedule(static,1) for (int i = 0; i < Nthreads; i++)  a[i][0] += i;

我们还对文献中的部分优化使用LLVM Flang编译器和classic-flang编译器进行了测试,测试结果请参考https://gitee.com/src-openeuler/flang/pulls/22/files。

References

  1. 刘京,郑启龙,李彭勇,郭连伟.面向Open64的OpenMP程序优化[J].计算机系统应用,2016,25(01):154-159.
  2. 游佐勇. OpenMP并行编程模型与性能优化方法的研究及应用[D].成都理工大学,2011.
  3. 陈永健. OpenMP编译与优化技术研究[D].清华大学,2004.
  4. http://akira.ruc.dk/~keld/teaching/IPDC_f10/Slides/pdf4x/4_Performance.4x.pdf

OpenMP优化调研系列文章(3)_open64_02

标签:int,omp,pragma,OpenMP,优化,parallel,调研
From: https://blog.51cto.com/u_15127420/6654901

相关文章

  • 如何实现pso优化神经网络pytorch的具体操作步骤
    PSO优化神经网络(PyTorch)实现流程介绍本文将介绍如何使用粒子群优化(ParticleSwarmOptimization,PSO)算法来优化神经网络模型,并使用PyTorch框架来实现。PSO算法是一种基于群体智能的优化算法,通过模拟鸟群觅食行为,来搜索最优解。在神经网络中,我们可以将待优化的参数作为粒子,利用......
  • BZOJ 3073: [Pa2011]Journeys 线段树优化最短路
    3073:[Pa2011]JourneysTimeLimit: 20Sec  MemoryLimit: 512MBSubmit: 243  Solved: 80[Submit][Status][Discuss]DescriptionSeter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条......
  • BZOJ 1915: [Usaco2010 Open]奶牛的跳格子游戏 单调队列优化dp
    1915:[Usaco2010Open]奶牛的跳格子游戏TimeLimit: 4Sec  MemoryLimit: 64MBSubmit: 281  Solved: 110[Submit][Status][Discuss]Description奶牛们正在回味童年,玩一个类似跳格子的游戏,在这个游戏里,奶牛们在草地上画了一行N个格子,(3<=N<=250,000),编号为1..N......
  • mysql常用操作&配置优化
    一、基础操作1、增创建用户:createuser'zhangsan'@'10.10.10.10'identifiedby'密码'; #示例用户授权:grantallon*.*to'zhangsan'@'%';     #示例创建并授权用户:grantallon*.*to'lisi'@'%'identifi......
  • MySQL查询语句优化方法
    1、应尽量避免在where子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。2、对查询进行优化,应尽量避免全表扫描,首先应考虑在where及orderby涉及的列上建立索引。3、应尽量避免在where子句中对字段进行null值判断,否则将导致引擎放弃使用索引而进行全表扫......
  • 如何优化Flutter的性能?
    Flutter的性能优化是一个持续的过程,需要我们不断地学习和实践。优化的目标不仅是提高应用的运行速度,还包括提高应用的响应速度,减少应用的内存使用,以及提高应用的能效。希望我们深入的探索这些实用的技巧和最佳实践可以帮助在使用Flutter构建应用时,提高应用的性能。不可否认Fl......
  • 存储引擎,SQL优化
    --存储引擎和sql优化--MySQL5.5默认的存储引擎是MyISAM5.6开始是InnoDB--InnoDB事务行级锁外键--MyISAMx表级锁x--MyISAM适合对事务不做要求的业务系统,可以容忍少部分数据的丢失(其优势是访问快,以select,insert为主的应用基本上可以使用)--......
  • Linux服务器之间进行文件目录映射/挂载-优化
    转自:https://www.cnblogs.com/tanshaoxiaoji/p/linux_nfs.html稍有优化需要实现的功能为:将192.168.10.10服务器下的/home/要映射的目录/,映射为192.168.10.90服务器下的/home/被映射的目录/。1、分别在192.168.10.10、192.168.10.90服务器上安装nfs、rpcbind;yuminst......
  • 31.性能优化
    首页加载很慢的原因:1.由于vendor.js和app.css较大,VUE等主流的单页面框架都是js渲染htmlbody的,所以必须等到vendor.js和app.css加载完成后完整的界面才会显示。2.单页面首次会把所有界面和接口都加载出来,会有多次的请求和响应,数据不能马上加载,二者相加所以会有长时间的白屏。......
  • java中http请求-okhttp使用连接池优化
    愿历尽千帆,归来仍是少年原因:避免频繁频繁的开关连接。1.Maven添加依赖<dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>3.10.0</version></dependency>2.OkHttpConfiguration配置类......