openmp #pragma omp task总结

目录

0.注意事项

1.基本原理

2.使用方法

3.关键命令

3.1 计算斐波那契数列

3.2unbounded loops

3.3 #pragma omp taskloop

4.总结


0.注意事项

本文所有的测试采用x86的处理器,

所有的测试代码位置为:https://github.com/Beichen-Wang/HPCTest/tree/master/OpenMPTest

1.基本原理

#pragma omp task的基本原理如下图所示,一个是线程池,一个是任务池,每个线程执行任务池中的一个任务;

2.使用方法

具体可以查看README,注意需要添加编译选项-fopenmp;

3.关键命令

task支持做两种操作:

  • 一种是recursive function,按照查到的官方教程中的经典例子,最经典的计算斐波那契数列;
  • 另外一种是unbounded loops:

3.1 计算斐波那契数列

int OmpFib(int n) {
  int x, y;
  if (n < 2) {
    return n;
  }
#pragma omp task shared(x)
  { x = OmpFib(n - 1); }
#pragma omp task shared(y)
  { y = OmpFib(n - 2); }
#pragma omp taskwait
  return x + y;
}

#pragma omp parallel num_threads(2)
  {
#pragma omp single
    { OmpFib(Num); }
  }

此外还有一个普通的斐波那契数列作为参照:

int NorFib(int n) {
  int x, y;
  if (n < 2)
    return n;
  x = NorFib(n - 1);
  y = NorFib(n - 2);
  return x + y;
}

测试时间结果为:

,这里发生了非常严重的负优化,猜测原因为task被切分的太细,每个task执行的任务非常短;所以我在这里做了cutoff:

int OmpFib(int n) {
  int x, y;
  if (n < 2) {
    return n;
  }
  if(n > 20){
#pragma omp task shared(x) untied
  { x = OmpFib(n - 1); }
#pragma omp task shared(y) untied
  { y = OmpFib(n - 2); }
#pragma omp taskwait
  } else {
    x = OmpFib(n - 1);
    y = OmpFib(n - 2);
  }
  return x + y;
}

双线程的效果良好,测试结果为:

3.2unbounded loops

OMP task的版本:

int OMPProcess(){
  mulSum = 1;
  NodeList * current;
  current = node.get();
  #pragma omp parallel num_threads(2)
  {
       #pragma omp single 
      {
        while(current){
        #pragma omp task
        subProcess.template operator()<decltype(&SubProcess::SubProcess1)>(mulSum, current->val);
        current = (current->next).get();}
      }
  }
            return mulSum;
}

 Normal 版本:

int NorProcess(){
    mulSum = 1;
    NodeList * current;
    current = node.get();
    while(current){
        subProcess.template operator()<decltype(&SubProcess::SubProcess1)>(mulSum, current->val);
        current = (current->next).get();
    }
    return mulSum;
}

我这里分别测试了两个例子,一个与前后文相关,一个与前后文无关;

  • SubProcess1
  • SubProcess2

3.3 #pragma omp taskloop

主要用来优化loop循环,其基本语法为:

#pragma omp taskloop [clause[, clause] ...]
for (init-expr; test-expr; incr-expr)
{
    // loop body
}

下面来用task和用taskloop来分别对一个循环做处理:

  • task的实现方式:
  • taskloop的实现方式:

可以看到taskloop的实现方式更简单,其中grainsize就是tilesize,我也做了测试,测试核心代码为:

class GrainSizeSubProcess final: public SubProcessBase {
public:
  size_t operator()(size_t n) override {
    size_t sum = 0;
#pragma omp taskloop grainsize(100000) shared(sum)
    for (size_t i = 0; i < n - 1; i++) {
      sum += (i * (i + 1));
    }
    return sum;
  }
};
  • 此处grainsize我选用的是100000,n为500000时,测试结果为:
  • 同样,当grainsize过小时,同样会造成负优化,所以每一个task所处理的grain size不应该过小;

4.总结

  • 如果产生task的数量过多且每个task处理的内容很少,会发生极其严重的负向优化;
  • 在unbloundloop结构中,如果process的的内容与前后的task有关,也是负向优化;
  • 在unbloundloop结构中,只有每个task处理的内容与前后无关,会产生正向优化;
  • taskloop可以有效降低运行时间,但是grainsize不应该选用过小。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
#pragma omp for是OpenMP的编译预处理指令之一,用于并行执行循环。这个指令可以将一个循环并行化,使多个线程同时执行循环体中的代码,从而加快程序的执行速度。在使用#pragma omp for时,需要在循环之前添加#pragma omp parallel来指定并行的范围。使用#pragma omp for时,可以使用schedule子句来指定循环迭代的分配方式,其中包括static、dynamic、guided等多种选项。此外,还可以使用num_threads子句来指定并行执行的线程数量。在C语言中,可以使用#pragma omp parallel for来实现多线程执行循环的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [2、OpenMP的任务调度schedule(static|dynamic|guided|runtime[size])](https://blog.csdn.net/sxj731533730/article/details/118244815)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [c语言多线程执行循环的编译预处理指令 #pragma omp 的用法](https://download.csdn.net/download/lj_70596/86868715)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值