在OpenMP的for任务分担中,各个线程的任务划分是可以由程序员控制调整的。考虑这样一种情况,当在一个循环中每次迭代的计算量不相等时,如果根据系统默认简单的给每个线程分配相同次数的迭代量的话,会导致有些线程先执行玩,有些线程后执行完,造成CPU核的空闲,降低程序的运行效率。这种情况下就有必要人为的对各个线程的任务划分进行分配。

例如对如下的循环:

#pragma omp parallel for
for (int i = 0; i < 100; i++)
{
cout << i*i << endl;
}

显然最后几次的计算量是远远大于前几次的计算量的,解决这种由于各个线程间均分迭代次数造成的负载不平衡的问题,可以通过schedule子句的使用来避免。

schedule子句的用法


使用格式:

schedule(type,size)

type表示调度类型,共有4种类型可选:

  • static
  • dynamic
  • guided
  • runtime

size参数定义了迭代次数最小的划分单位,每个线程依次分配size个迭代次数。

static静态调度


#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel for schedule(static,3)
for (int i = 0; i < 9; i++)
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
system("pause");
}

输出:

从打印结果可以看出每个线程依次分配到3个连续的迭代计算。

dynamic动态调度


动态调度是动态的将迭代分配到各个线程上,可以使用size参数也可以不使用size参数,不适用size参数情况下size值默认为1,根据每个线程的完成情况每次再分配2个迭代给已完成迭代任务的线程,使用size参数则每次分配size个迭代次数。较快迭代完成的线程可能执行更多次迭代,较慢的线程执行较少的迭代,以此来解决各线程间负载分配不均衡的问题。

示例:

#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel for schedule(dynamic,2)
for (int i = 0; i < 12; i++)
{
printf("i=%d, thread_id=%d\n", i*i*i*i, omp_get_thread_num());
}
system("pause");
}

输出:

执行乘法运算,i比较小的时候计算量小,所以可以看到编号为0的线程执行了6次,编号为1、2和3的线程分别执行了2次。

guided调度


guided调度跟dynamic动态调度类似,是一种采用指导性的启发式自调度方法。刚开始时候每个线程会分配到较大的迭代块,之后每次分配到的迭代块会以指数级下降,直到下降到自定义的size大小,如果没有定义size,则默认为1。

runtime调度


runtime调度根据运行时的环境变量OMP_SCHEDULE来确定调度类型,最后还是会落实到schedule、dynamic和guided中的一种上来。

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

setenv OMP_SCHEDULE “dynamic, 2”

如果程序中选择runtime调度,那么上述命令设置调度类型为动态调度,动态调度的size为2。在windows环境中,可以在“系统属性|高级|环境变量”对话框中进行设置环境变量。

sections制导指令

for制导指令用于迭代计算的任务分配,sections制导指令用于非迭代计算的任务分配,sections的语法格式如下:

#pragma omp parallel sections[子句]

#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel sections
{
#pragma omp section
{
for (int i = 0; i < 4; i++)
{
printf("i=%d, thread_id=%d\n", i, omp_get_thread_num());
}
}
#pragma omp section
{ for (int i = 0; i < 4; i++)
{
printf("j=%d, thread_id=%d\n", i, omp_get_thread_num());
}
}
}
system("pause");
}

输出:

sections语句块中一共有2个section段落,所以生成了2个线程并行执行。

single制导指令

在parallel制导指令产生的并行域中的语句,一般会默认生成4个不同的线程对相同的语句分别执行一次,如果想要其中某些操作只执行一次,可以使用single制导指令,其后的语句块只会被单个线程执行。

#include<iostream>
#include"omp.h" using namespace std; void main()
{
#pragma omp parallel
{
#pragma omp single
{
printf("single thread_id=%d\n", omp_get_thread_num());
} printf("多线程执行,thread_id=%d\n", omp_get_thread_num());
}
system("pause");
}

输出:

由single引导的语句块只执行了一次,第二个printf语句没有single指令,所以被4个不同的线程分别执行了一次。

OpenMP编程的任务调度控制的更多相关文章

  1. openMP编程(下篇)之数据私有与任务调度

    title: openMP编程(下篇)之数据处理子句与任务调度 tags: ["openMP"] notebook: 分布式程序_Linux --- openMP并行编程中数据的共 ...

  2. 并行计算之OpenMP中的任务调度

    本文参考<OpenMP中的任务调度>博文,主要讲的是OpenMP中的schedule子句用法. 一.应用需求 在OpenMP并行计算中,任务调度主要用于并行的for循环.当for循环中每次 ...

  3. openMP编程(上篇)之指令和锁

    openMP简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...

  4. openMP编程(上篇)之并行程序设计

    openMP简介 openMP是一个编译器指令和库函数的集合,主要是为共享式存储计算机上的并行程序设计使用的. 当计算机升级到多核时,程序中创建的线程数量需要随CPU核数变化,如在CPU核数超过线程数 ...

  5. 一个openMP编程处理图像的示例

    一个openMP编程处理图像的示例: 从硬盘读入两幅图像,对这两幅图像分别提取特征点,特征点匹配,最后将图像与匹配特征点画出来.理解该例子需要一些图像处理的基本知识,我不在此详细介绍.另外,编译该例需 ...

  6. Java编程基础——流程控制

    Java编程基础——流程控制 摘要:本文主要介绍Java编程中的流程控制语句. 分类 流程控制指的是在程序运行的过程中控制程序运行走向的方式.主要分为以下三种: 顺序结构:从上到下依次执行每条语句操作 ...

  7. OpenMP编程总结表

    本文对OpenMP 2.0的全部语法——Macro(宏定义).Environment Variables(环境变量).Data Types(数据类型).Compiler Directives(编译指导 ...

  8. Win32多线程编程(2) — 线程控制

    Win32线程控制只有是围绕线程这一内核对象的创建.挂起.恢复.终结以及通信等操作,这些操作都依赖于Win32操作系统提供的一组API和具体编译器的C运行时库函数.本篇围绕这些操作接口介绍在Windo ...

  9. Java并发编程:线程控制

    在上一篇文章中(Java并发编程:线程的基本状态)我们介绍了线程状态的 5 种基本状态以及线程的声明周期.这篇文章将深入讲解Java如何对线程进行状态控制,比如:如何将一个线程从一个状态转到另一个状态 ...

随机推荐

  1. linux的几个内核镜像格式Image 和 u-boot启动内核和文件系统时的一些环境变量的设置

    关于编译powerpc linux的几个Image参考原文 http://blog.sina.com.cn/s/blog_86a30b0c0100wfzt.html 转载▼   PowerPC架构 L ...

  2. Android系统开发(8)——linx进程基本概念

    一.proc文件系统 传统意义上的文件系统是用于块设备上信息的存储,/proc这个目录是一个虚拟文件系统,它放置的数据都是在内存当中,所以这个目录本身不占用任何硬盘空间.主要包含如下系统信息: 内存管 ...

  3. PatentTips - Data Plane Packet Processing Tool Chain

    BACKGROUND The present disclosure relates generally to systems and methods for providing a data plan ...

  4. linux下的打包和压缩

    linux中常见的两种压缩包文件的格式是.tar..gz和.tar.gz..tar仅仅是将文件简单地打包,文件的大小没有变化,也就是说.tar文件仅仅是一个包,没有被压缩:.tar.gz文件是打包后用 ...

  5. mac系统创建.开头文件.htaccess

    thinkphp5 隐藏index.php的时候需要用的.htaccess文件,但是mac默认不让创建这种文件 感谢 https://blog.csdn.net/gyz413977349/articl ...

  6. href=“file://” doesn't work

    Local Explorer 2016.6.21.0 CRX for Chrome or Chromium https://www.crx4chrome.com/extensions/eokekhgp ...

  7. vs 外部依赖项、附加依赖项以及如何添加依赖项目

    我们在 VS 中创建 Win32 控制台应用程序,vs 会为解决方案创建默认地创建 4 个 filters(资源管理器中没有对应的目录和文件夹): 头文件:一般为 .h 文件 外部依赖项 源文件:一般 ...

  8. 百度富文本编辑器ueditor使用启示

    百度富文本编辑器ueditor使用启示 一.总结 一句话总结:使用工具,多去看官方demo,非常详细. 二.百度富文本编辑器ueditor使用启示 官方完整demo 官方完整demo对应的源代码 &l ...

  9. [Angular] Adding keyboard events to our control value accessor component

    One of the most important thing when building custom form component is adding accessbility support. ...

  10. 【codeforces 754B】 Ilya and tic-tac-toe game

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...