`
lovnet
  • 浏览: 6871699 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

OpenMP中的任务调度

阅读更多
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循环并行化的任务调度方案。
在OpenMP中,对for循环并行化的任务调度使用schedule子句来实现,下面介绍schedule字句的用法。
1.1.1 Schedule子句用法
schedule子句的使用格式为:
schedule(type[,size])
schedule有两个参数:type和size,size参数是可选的。
1. type参数
表示调度类型,有四种调度类型如下:
·dynamic
·guided
·runtime
·static
这四种调度类型实际上只有static、dynamic、guided三种调度方式,runtime实际上是根据环境变量来选择前三种中的某中类型。
run-sched-var
2. size参数 (可选)
size参数表示循环迭代次数,size参数必须是整数。static、dynamic、guided三种调度方式都可以使用size参数,也可以不使用size参数。type参数类型为runtime时,size参数是非法的(不需要使用,如果使用的话编译器会报错)。
当parallel for编译指导语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大约n/t次迭代计算。这里为什么说大约分配n/t次呢?因为n/t不一定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定了size参数的话,那么可能相差一个size。
静态调度时可以不使用size参数,也可以使用size参数。
3. 不使用size参数
不使用size参数时,分配给每个线程的是n/t次连续的迭代,不使用size参数的用法如下:
schedule(static)
例如以下代码:
#pragma omp parallel for schedule(static)
for(i = 0; i < 10; i++ )
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
上面代码执行时打印的结果如下:
i=0, thread_id=0
i=1, thread_id=0
i=2, thread_id=0
i=3, thread_id=0
i=4, thread_id=0
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
i=8, thread_id=1
i=9, thread_id=1
可以看出线程0得到了0~4次连续迭代,线程1得到5~9次连续迭代。注意由于多线程执行时序的随机性,每次执行时打印的结果顺序可能存在差别,后面的例子也一样。
4. 使用size参数
使用size参数时,分配给每个线程的size次连续的迭代计算,用法如下:
schedule(static, size)
例如以下代码:
#pragma omp parallel for schedule(static, 2)
for(i = 0; i < 10; i++ )
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
执行时会打印以下结果:
i=0, thread_id=0
i=1, thread_id=0
i=4, thread_id=0
i=5, thread_id=0
i=8, thread_id=0
i=9, thread_id=0
i=2, thread_id=1
i=3, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
从打印结果可以看出,0、1次迭代分配给线程0,2、3次迭代分配给线程1,4、5次迭代分配给线程0,6、7次迭代分配给线程1,…。每个线程依次分配到2次连续的迭代计算。
动态调度是动态地将迭代分配到各个线程,动态调度可以使用size参数也可以不使用size参数,不使用size参数时是将迭代逐个地分配到各个线程,使用size参数时,每次分配给线程的迭代次数为指定的size次。
下面为使用动态调度不带size参数的例子:
#pragma omp parallel for schedule(dynamic)
for(i = 0; i < 10; i++ )
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
打印结果如下:
i=0, thread_id=0
i=1, thread_id=1
i=2, thread_id=0
i=3, thread_id=1
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
i=8, thread_id=1
i=4, thread_id=0
i=9, thread_id=1
下面为动态调度使用size参数的例子:
#pragma omp parallel for schedule(dynamic, 2)
for(i = 0; i < 10; i++ )
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
打印结果如下:
i=0, thread_id=0
i=1, thread_id=0
i=4, thread_id=0
i=2, thread_id=1
i=5, thread_id=0
i=3, thread_id=1
i=6, thread_id=0
i=8, thread_id=1
i=7, thread_id=0
i=9, thread_id=1
从打印结果可以看出第0、1,4、5,6、7次迭代被分配给了线程0,第2、3,8、9次迭代则分配给了线程1,每次分配的迭代次数为2。
1.1.4 guided调度(guided
guided调度是一种采用指导性的启发式自调度方法。开始时每个线程会分配到较大的迭代块,之后分配到的迭代块会逐渐递减。迭代块的大小会按指数级下降到指定的size大小,如果没有指定size参数,那么迭代块大小最小会降到1。
例如以下代码:
#pragma omp parallel for schedule(guided,2)
for(i = 0; i < 10; i++ )
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
打印结果如下:
i=0, thread_id=0
i=1, thread_id=0
i=2, thread_id=0
i=3, thread_id=0
i=4, thread_id=0
i=8, thread_id=0
i=9, thread_id=0
i=5, thread_id=1
i=6, thread_id=1
i=7, thread_id=1
第0、1、2、3、4次迭代被分配给线程0,第5、6、7次迭代被分配给线程1,第8、9次迭代被分配给线程0,分配的迭代次数呈递减趋势,最后一次递减到2次。
1.1.5 runtime调度(rumtime
runtime调度并不是和前面三种调度方式似的真实调度方式,它是在运行时根据环境变量OMP_SCHEDULE来确定调度类型,最终使用的调度类型仍然是上述三种调度方式中的某种。
例如在unix系统中,可以使用setenv命令来设置OMP_SCHEDULE环境变量:
setenv OMP_SCHEDULE“dynamic, 2”
上述命令设置调度类型为动态调度,动态调度的迭代次数为2。
在windows环境中,可以在”系统属性|高级|环境变量”对话框中进行设置环境变量。
分享到:
评论

相关推荐

    OpenMP任务调度开销及负载均衡分析

    ### OpenMP任务调度开销及负载均衡分析 #### 一、引言 随着多核处理器技术的发展,如何高效利用计算资源成为了程序设计的关键问题之一。OpenMP作为一种流行的并行编程模型,提供了简单而强大的工具来支持共享内存...

    任务图调度算法(非成员函数版).rar_mixziz_orderv77_任务图调度算法_任务调度

    任务调度是计算机科学中的关键问题,特别是在并行计算和分布式系统领域。本文将探讨一种个人编写的非成员函数版本的任务图调度算法,该算法充分利用了OpenMP库,适用于处理具有依赖关系的任务图模型,旨在优化计算...

    OpenMP用户手册(中文).docx

    4. **任务(Tasks)**:`task`指令引入了异步任务执行,允许在执行过程中动态创建和调度任务,增加了灵活性。 5. **数据环境(Data Environment)**:通过`private`、`shared`、`default`、`firstprivate`、`...

    C 代码 演示默认、静态和动态调度方法 OpenMP 中的循环迭代以避免工作不平衡.rar

    还可以通过调整`chunk_size`来优化性能,使得调度更加灵活或减少任务调度的开销。 通过这个压缩包中的代码,开发者可以学习如何利用OpenMP进行并行编程,以及如何根据任务特点选择合适的调度策略,从而提高程序的...

    OpenMP中文版教程

    任务调度方面,OpenMP提供了多种调度策略,包括静态调度、动态调度、guided调度和runtime调度。每种调度方式都有其适用的场景,程序员可以根据任务的特点和系统资源情况选择合适的调度策略。 OpenMP还提供了创建...

    很不错OpenMP入门资料,中文的

    通过`#pragma omp task`指令,可以创建独立的任务,这些任务可以在并行区内外自由调度执行。 ##### 5.3 原子操作 在并行程序中,某些变量可能需要在多个线程之间同步更新。OpenMP提供了一种简单的机制——原子操作...

    OpenMP中使用task子句的几个方法

    在OpenMP中,可以利用`single`子句来启动一个具有初始根任务的并行区域。这有助于更好地组织并行代码,并确保在执行并行任务前先完成一些初始化工作。下面是一个示例: ```c #pragma omp parallel { #pragma omp ...

    OpenMP 3.0 What's new

    数据范围子句如`shared`、`private`、`firstprivate`以及`default`等用于定义任务的数据环境,而调度子句如`untied`则提供了对任务调度的控制。此外,`if`子句可以根据表达式的值决定是否创建任务。 ### 任务同步 ...

    openmp-examples-master_openmp_源码

    5. **动态调度**:OpenMP允许动态调整线程数和任务分配,以适应运行时系统的变化。 6. **环境变量**:通过设置环境变量,如`OMP_NUM_THREADS`,可以控制OpenMP的行为。 【压缩包子文件的文件名称列表】"openmp-...

    并行任务调度算法与分析.doc

    1. **算法1**:将矩阵乘法中的16个元素计算均匀分配到各个线程中,以达到任务调度的目的。这种算法适用于数据之间的计算相对独立的情况。 2. **算法2**:采用分块策略,将矩阵乘法任务分为几个较大的块,每个块再...

    OpenMP用户指南.pdf

    OpenMP指令中的子句,例如data scope子句、schedule子句和num_threads子句,则用来控制数据的作用域、任务调度和线程数量。 OpenMP的运行时库提供了丰富的例程来支持并行程序的设计,这些例程涵盖线程管理、同步...

    行业分类-设备装置-任务调度装置、方法及并行处理数据的设备.zip

    在IT行业中,任务调度装置、方法以及并行处理数据的设备是关键的组成部分,尤其是在大数据、云计算和高性能计算领域。这些技术旨在优化系统资源的利用,提高效率,并确保任务能够及时、有效地完成。以下是关于这个...

    openmp-3.0.rar

    OpenMP 3.0引入了任务(Task)概念,这是一种更加灵活的并行化方式,允许程序创建异步执行的任务,它们可以在需要时被调度执行。任务可以嵌套,并且可以使用任务依赖(task dependency)来处理任务间的依赖关系。 ...

    第一个OpenMP程序

    其主要特点包括并行区域、同步机制、数据共享与私有化、任务调度和动态调整并行度等。 1. **并行区域(Parallel Regions)**: OpenMP中的并行区域是通过`#pragma omp parallel`指令来定义的,这将告知编译器在该...

    OpenMP 3.0 英文规范

    - 任务调度机制允许开发人员指定任务执行的顺序。 - 支持自适应和指导式调度。 **2.8 主线程与同步构造** 这些构造用于控制并行区域内的线程活动,确保正确性和数据一致性。 - **2.8.1 master 构造** - 指定一...

    OpenMPOpenMPOpenMP

    6. **环境变量**:OpenMP支持一系列环境变量,如`OMP_NUM_THREADS`用于设置默认线程数,`OMP_SCHEDULE`用于控制循环调度策略,以及`OMP_DYNAMIC`来启用或禁用动态调整线程数。 7. **并行化最佳实践**:在使用OpenMP...

    Parallel_Programming_in_OpenMP_并行计算_openmp_warn4fw_

    3. **动态任务调度**:OpenMP支持动态生成任务,允许程序在运行时创建新的并行任务,增强了灵活性。 4. **循环并行化**:`#pragma omp for`用于并行化循环,自动分配循环迭代给不同的线程。 5. **同步和通信**:`#...

Global site tag (gtag.js) - Google Analytics