OpenMP并行计算的使用4

OpenMP任务调度
OpenMP中,任务调度主要用于并行的for循环当中,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代的话,会造成各个线程计算负载不均衡,这会使得有些线程先执行完毕,有的后执行完,造成某些cpu核空闲,影响程序性能。
举例:

int i,j;
int a[100][100]={0};
for(i=0;i<100;i++)
{ 
  for(j=i;j<100;j++)
  {
  a[i][j]=i*j;
 }
}

如果最外层循环并行化的话,比如使用4个线程,如果给每个线程平均分配25次循环迭代计算的话,显然i=0和i=99的计算量相差了100倍,那么各个线程间可能出现较大的负载不平衡情况。为了解决这些问题,openMP以供了几种对for循环并行化的任务调度方案。使用schedule子句来实现。
1.schedule子句用法
使用格式:
schedule(type[,size])
schedule有两个参数,type和size,size参数是可选的。
(1)type参数
表示调度的类型,有四种调度类型如下:
dynamic
guided
runtime
static

实际上只有static、dynamic、guided三种调度方式,runtime实际上是根据环境变量来选择前三种中的某种类型。
(2)size参数
size参数表示循环迭代此时,size参数必须是整数。static、dynamic、guided三只调度方式都可以使用size参数,也可以不使用size参数。当type类型是runtime时,size不需要使用。
2.静态调度(static)
当parallel for编译知道语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大概大约n/t次迭代计算。大约的说法是因为n/t不一定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定size参数,那么可能相差一个size。
静态调度时可以不使用size参数,也可以使用size参数。
不使用size参数时,**分配给每个线程的是n/t次连续的迭代,**用法如下:
schedule(static)
代码:

   #pragma omp parallel for schedule(static)
   for(i=0;i<10;i++)
   {
   cout<<"i="<<i<<", thread="<<omp_get_thread_num()<<endl;
}

执行结果输出schedule(static)结果输出
可以看到,迭代0、1分配给了线程0,迭代2、3分配给了线程1。之后迭代4给了2,5给了3,6给4,7给5,8给了6,9给7。
使用size参数:
schedule(static,2)

  #pragma omp parallel for schedule(static,2)
   for(i=0;i<10;i++)
   {
   cout<<"i="<<i<<", thread="<<omp_get_thread_num()<<endl;
}

输出为:
schedule(static[,size])
可以看到,每个线程一次分配了2次(size大小)连续的迭代计算。
3.动态调度(dynamic)
动态调度是动态的将迭代分配到各个线程,动态调度可以使用size参数也可以不使用size参数,不使用size参数时是将迭代逐个分配到各个线程;使用size参数时,每次分配给线程的迭代次数为指定的size次。
不带size参数时:

  #pragma omp parallel for schedule(dynamic)
   for(i=0;i<10;i++)
   {
   cout<<"i="<<i<<", thread="<<omp_get_thread_num()<<endl;
}

带size参数:

  #pragma omp parallel for schedule(dynamic,3)
   for(i=0;i<10;i++)
   {
   cout<<"i="<<i<<", thread="<<omp_get_thread_num()<<endl;
}

schedule(dynamic,3)输出
4.guided调度(guided)

guided调度是一种采用指导性的启发式自调度方法。开始时每个线程都会分到较大的迭代块,之后分配到的迭代块回逐渐递减,迭代块的大小会按照指数级下降到指定的size大小,如果没有指定size参数,则迭代块大小最小会降到1.
举例:

#pragma omp parallel for schedule(guided,2),num_threads(3)
	for (i = 0; i < 10; i++)
	{
	cout << "i=" << i << ", thread=" << omp_get_thread_num() << endl;
	}

输出为:
在这里插入图片描述

迭代次数0,1,2,3,9,10分配给线程0。4,5,6分配给线程1,剩下7,8分配给线程2。分配的迭代次数呈现递减趋势,最后递减至2次。
5.runtime调度
runtime调度不是和前面三种调度方式似的真实调度方式。而是在运行时更加环境变量OMP_SCHEDULE来确定调度类型,最终使用的调度类型依然是上述三只调度种的某种。例如unix系统中,可以使用setenv命令来设置OMP_SCHEDULE环境变量:setenv OMP_SCHEDULE "dynamic,2"
该命令设置调度类型为动态,size为2。而windows环境中,可以在”系统属性->高级->环境变量“对话框中设置环境变量。

以上文字内容和代码主要转载自:
https://blog.csdn.net/drzhouweiming/article/details/1175848
在此表示感谢!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值