一些对OpenMP进行优化的方法

作者介绍
谢依晖
湖南大学硕士研究生在读,
本科毕业于湖南大学计算机科学与技术专业
abstract
本文调研了一些对openmp进行优化的方法:
h. ma, r. zhao, x. gao and y. zhang针对openmp程序中的barrier提出几种新功能的支持和性能的优化[1];
在sc20的booth talks上,johannes doerfert分享了在llvm上对openmp做的一些优化[2]。
barrier optimization for openmp program[1]
删除冗余的barrier
通过并行数据流分析,两个循环之间无数据依赖,所以s1的barrier是冗余的;parallel结束的时候有一个隐式的barrier,所以s2的barrier也是冗余的。
!$omp parallel!$omp dodo i = 1, 100  a(i) = d(i)end do    !barrier s1!$omp end do!$omp dodo i = 1, 100  b(i) = c(i)end do    !barrier s2!$omp end do!$omp end parallel  
优化时,可以在该语句块加上显式的nowait(!$omp end do nowait)。
实现doacross并行
当并行化循环的时候,如果循环依赖距离是一个常数,如下代码:
do i = 2, 100  do j = 2, 100    a(i, j) = a(i - 1, j) + a(i, j-1)  end doend do  
对外层循环i进行数据依赖检查,可以得到a[i][j]和a[i-1][j]之间的依赖距离为1。因此循环可以以doacross并行的方式运行。openmp只实现了doall并行,没有与doacross对应的语句。
实现时,定义共享数组“_mylocks [ threadid ]”来存储每个线程的事件,定义私有变量_counter0指示当前线程正在等待的事件。数组“_mylocks”中的元素总数是线程数,每个元素表示相应线程的当前状态。实现的代码如下:
int _mylocks[256]; // thread's synchronized array#pragma omp parallel{  int _counter0 = l;  int _my_id = omp_get_thread_num();  int _my_nprocs = omp_get_num_threads();  _mylocks[my_id] = 0;  for (j_tile = 0; j_tile  0) {      do {        #pragma omp flush(_mylock)      } while (_mylock[myid - l] < _counter0);      #pragma omp flush(a, _mylock)      _counter0 +=1;    }    #pragma omp for nowait    for (i = l; i < n; i++) {      for (j = j_tile; j < j_tile + m; j++){        a[i][j] = a[i - 1][j] + a[i][j - 1];      }    }    _mylock[myid] += 1;    #pragma omp flush(a, _mylock)  }}  
region barrier
当线程遇到region barrier时会继续执行。但是直到其他所有线程都进入这个区域之后,它才能运行出该区域。这样的好处是允许线程继续运行而不空转,可以实现cpu的负载均衡。
region barrier的实现代码如下:
unsigned _counter = 0;#pragma omp parallel{  {first parallel region}  #pragma omp atomic  _counter++;  {barrier region}  #pragma omp flush(counter)  while(counter % omp_get_num_threads())  {    #pragma omp flush(counter)  }  #pragma omp flush  {third parallel region}}  
当使用region barrier时,需要保证并行域r1和r3与并行域r2无依赖关系。
openmp sc20 booth talk series : openmp compiler optimizations in llvm [2]
openmp运行时调用重复数据的消除
double *a = malloc(size * omp_get_thread_limit());double *b = malloc(size * omp_get_thread_limit());#pragma omp paralleldo_work(&a[omp_get_thread_num() * size]);#pragma omp paralleldo_work(&b[omp_get_thread_num() * size]);  
示例代码中重复调用了omp_get_thread_limit()和omp_get_thread_num()函数,可以将重复调用合并至一次调用。该功能已在llvm实现,可通过如下编译选项进行优化:
$ clang deduplicate.c -g -o2 -fopenmp -rpass=openmp-opt  
tracking openmp internal control variables
void foo() {  #pragma omp parallel  bar();}void bar() {  if (omp_in_parallel()) {    ...  } else {    ...  }}  
以上代码,如果omp_in_parallel()的返回值可以判断为真,那么这个if结构就可以被删除。


如何选择LED显示屏从而减轻或消除摩尔纹
对数转换器电路原理图
Dialog并购Silego 交易金额达3亿美元
电路为何需要端接?介绍几种端接方式的区别及优缺点
毕马威报告:全球自动驾驶发展分析报告
一些对OpenMP进行优化的方法
深入了解不同负载均衡类型的优缺点
中科视拓上市了吗_中科视拓会借壳么
在Vitis中创建基于ARM的BareMetal程序设计
C语言atoi函数详解
TransEnterix获得了FDA对小型医疗仪器的认可
众泰T700刚出不久,又将推七座版车型-众泰T700L,轴距超哈弗H9!
基于FPGA的数字视频信号处理器设计
在工业互联网领域,智慧医疗仍在起步阶段
智慧配电房电力监控系统
全新Cypress 电源管理IC助力汽车电子控制单元应对苛刻电气条件
极限SOA办公平台开发计划发布(下)
PCB金手指设计的常见问题和解决方案
关于要实现电动汽车大规模推广的关键因素探析
1650显卡性能_1650显卡能吃鸡吗