OpenMP #03-2任务调度schedule子句的用法

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

OpenMP #03-2任务调度schedule子句的用法_第1张图片
OpenMP #03-2任务调度schedule子句的用法_第2张图片
DEFAULT schedule is to split the iterations in blocks across OpenMP threads

在这个例子中,schedule默认将并行域里的循环迭代分割,交给线程执行

如果将最外层循环并行,使用2个线程

> 绿色行 [即 row=1,2,3 ] 被thread 0 执行

> 紫色行 [即 row=4,5,6] 被thread 1 执行

如果给每个线程平均分配3次循环迭代计算的话,thread 0 进行了6次运算,thread 1 进行了15次运算。那么各个线程间可能出现较大的负载不平衡情况。为了解决这些问题,OpenMP中提供了几种对for循环并行化的任务调度方案。




在OpenMP中,对for循环并行化的任务调度使用schedule子句来实现,下面介绍schedule的用法:

schedule的使用格式为: schedule(type, chunk_size)

schedule有两个参数:type  和 chunk_sizechunk_size参数是可选择是否设置的)


1. type参数

表示调度类型,有四种调度类型如下:

> dynamic

> guided

> runtime

> static

这四种调度类型实际上只有static、dynamic、guided三种调度方式,runtime实际上是根据环境变量来选择前三种中的某中类型。   run-sched-var


2. chunk_size参数 (可选择是否设置)

chunk_size参数表示循环迭代次数,chunk_size参数必须是整数。static、dynamic、guided三种调度方式都可以使用chunk_size参数,也可以不使用chunk_size参数。当type参数类型为runtime时,chunk_size参数是非法的(不需要使用,如果使用的话编译器会报错)




1. 静态调度(static)

当parallel for编译指导语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大约n/t次迭代计算。

这里为什么说大约分配n/t次呢?因为n/t不一定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定了chunk_size参数的话,那么可能相差一个chunk_size

静态调度时可以不使用chunk_size参数,也可以使用sichunk_sizeze参数。

> 不使用chunk_size参数时,分配给每个线程的是n/t次连续的迭代,不使用chunk_size参数的用法如下:

#pragma omp parallel for schedule(static)

OpenMP #03-2任务调度schedule子句的用法_第3张图片
静态调度(static) & 不使用chunk_size参数

四核,每个运行2-3次。


> 使用chunk_size参数时,分配给每个线程的chunk_size次连续的迭代计算,用法如下:

#pragma omp parallel for schedule(static, N)

OpenMP #03-2任务调度schedule子句的用法_第4张图片
静态调度(static) & 使用chunk_size参数

每次指定运行2次计算,所以线程0运行了4次,其他都是2次。


2. 动态调度(dynamic)

动态调度是动态地将迭代分配到各个线程,动态调度可以使用chunk_size参数也可以不使用chunk_size参数,不使用chunk_size参数时是将迭代逐个地分配到各个线程,使用chunk_size参数时,每次分配给线程的迭代次数为指定的chunk_size次。

> 下面为使用动态调度不带chunk_size参数的例子:

#pragma omp parallel for schedule(dynamic)

OpenMP #03-2任务调度schedule子句的用法_第5张图片
动态调度(dynamic) &  不使用chunk_size参数

任务0-3分配给了线程1-4,之后任务分配给了线程0、2


> 下面为使用动态调度带chunk_size参数的例子:

#pragma omp parallel for schedule(dynamic, N)

OpenMP #03-2任务调度schedule子句的用法_第6张图片
动态调度(dynamic) &  使用chunk_size参数

每3个作一次动态分配


3. guided调度(guided)

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

> 下面为使用引导调度不带chunk_size参数的例子:

#pragma omp parallel for schedule(guided)

OpenMP #03-2任务调度schedule子句的用法_第7张图片
guided调度(guided)& 不使用chunk_size参数 

分配数量逐渐从5,4,3,2减小。


> 下面为使用引导调度带chunk_size参数的例子:

#pragma omp parallel for schedule(guided,N)

OpenMP #03-2任务调度schedule子句的用法_第8张图片
guided调度(guided)& 使用chunk_size参数

分配数量逐渐从5减小到4


4. runtime调度(rumtime)

runtime调度并不是和前面三种调度方式似的真实调度方式,它是在运行时根据环境变量OMP_SCHEDULE来确定调度类型,最终使用的调度类型仍然是上述三种调度方式中的某种。

#pragma omp parallel for schedule(runtime)

OpenMP #03-2任务调度schedule子句的用法_第9张图片
runtime调度(rumtime)

> 在unix系统中,可以使用setenv命令来设置OMP_SCHEDULE环境变量:

setenv OMP_SCHEDULE “dynamic, 2”

上述命令设置调度类型为动态调度,动态调度的迭代次数为2。

> 在windows环境中,可以在”系统属性|高级|环境变量”对话框中进行设置环境变量

set OMP_SCHEDULE="type, chunk_size"

举例: export OMP_SCHEDULE=“guided,10”



原文链接:https://blog.csdn.net/billbliss/article/details/44131919

你可能感兴趣的:(OpenMP #03-2任务调度schedule子句的用法)