简述OpenMP中的线程任务调度

OpenMP中任务调度主要针对并行的for循环,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代,则可能会造成各个线程计算负载的不平衡,影响程序的整体性能。

如下面的代码中,如果每个线程执行的任务数量平均分配,有的线程会结束早,有的线程结束晚:

#include<stdio.h>
#include<omp.h>

int main(){
    int a[100][100] = {0};
#pragma omp parallel for
    for (int i =0; i < 100; i++){
        for(int j = i; j < 100; j++ )
            a[i][j] = ((i%7)*(j%13)%23);
    }
    return 0;
}

为此,OpenMP提供了schedule子句来实现任务的调度。

schedule子句:

schedule(type[, size]),

参数type是指调度的类型,可以取值为static,dynamic,guided,runtime四种值。其中runtime允许在运行时确定调度类型,因此实际调度策略只有前面三种。

返回栏目页:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/extra/

参数size表示每次调度的迭代数量,必须是整数。该参数是可选的。当type的值是runtime时,不能够使用该参数。

1.静态调度static

大部分编译器在没有使用schedule子句的时候,默认是static调度。static在编译的时候就已经确定了,那些循环由哪些线程执行。

当不使用size 时,将给每个线程分配┌N/t┐个迭代。当使用size时,将每次给线程分配size次迭代。

如下面代码:

#include<stdio.h>
#include<omp.h>
int main(){
    int a[100][100] = {0};
#pragma omp parallel for schedule(static)
//#pragma omp parallel for schedule(static,5)
    for (int i =0; i < 100; i++){
        printf("id=%d i=%dn",omp_get_thread_num(),i);
    }
    return 0;
}

在四核机器上执行:

(1)当不使用参数时,100/4=25,0-24由1号线程执行;25-49由2号线程执行;50-74由3号线程执行;75-99由4号线程执行

(1)当不使用参数时,x(x=0,1,2,3)线程执行((n/5)%4)任务。其中n=0-99。

2.动态调度dynamic

动态调度依赖于运行时的状态动态确定线程所执行的迭代,也就是线程执行完已经分配的任务后,会去领取还有的任务。由于线程启动和执行完的时间不确定,所以迭代被分配到哪个线程是无法事先知道的。

当不使用size 时,是将迭代逐个地分配到各个线程。当使用size 时,逐个分配size个迭代给各个线程。

如下面代码:

#include<stdio.h>
#include<omp.h>
int main(){
    int a[100][100] = {0};
#pragma omp parallel for schedule(dynamic)
//#pragma omp parallel for schedule(dynamic,5)
    for (int i =0; i < 100; i++){
        printf("id=%d i=%dn",omp_get_thread_num(),i);
    }
    return 0;
}

3.启发式调度guided

采用启发式调度方法进行调度,每次分配给线程迭代次数不同,开始比较大,以后逐渐减小。

size表示每次分配的迭代次数的最小值,由于每次分配的迭代次数会逐渐减少,少到size时,将不再减少。如果不知道size的大小,那么默认size为1,即一直减少到1。具体采用哪一种启发式算法,需要参考具体的编译器和相关手册的信息。

三种运行方式总结:

静态调度static:每次哪些循环由那个线程执行时固定的,编译调试。由于每个线程的任务是固定的,但是可能有的循环任务执行快,有的慢,不能达到最优。

动态调度dynamic:根据线程的执行快慢,已经完成任务的线程会自动请求新的任务或者任务块,每次领取的任务块是固定的。

启发式调度guided:每个任务分配的任务是先大后小,指数下降。当有大量任务需要循环时,刚开始为线程分配大量任务,最后任务不多时,给每个线程少量任务,可以达到线程任务均衡。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索线程
, 任务调度
, 迭代
, openmp
, 调度
, matlab omp
, 任务动态分配选择
, size
, 任务
, 分配
, 迭代循环
线程调度
java 多线程任务调度、多线程任务调度、openmp设置线程数、多线程与openmp的区别、openmp多线程编程,以便于您获取更多的相关知识。

时间: 2024-08-02 21:37:29

简述OpenMP中的线程任务调度的相关文章

OpenMP 中的线程任务调度

OpenMP中任务调度主要针对并行的for循环,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代,则可能会造成各个线程计算负载的不平衡,影响程序的整体性能. 如下面的代码中,如果每个线程执行的任务数量平均分配,有的线程会结束早,有的线程结束晚: 1 #include<stdio.h> 2 #include<omp.h> 3 4 int main(){ 5 int a[100][100] = {0}; 6 #pragma omp parallel for 7

Java基础-创建Java程序中的线程池

程序|创建 线程是Java的一大特性,它可以是给定的指令序列.给定的方法中定义的变量或者一些共享数据(类一级的变量).在Java中每个线程有自己的堆栈和程序计数器(PC),其中堆栈是用来跟踪线程的上下文(上下文是当线程执行到某处时,当前的局部变量的值),而程序计数器则用来跟踪当前线程正在执行的指令. 在通常情况下,一个线程不能访问另外一个线程的堆栈变量,而且这个线程必须处于如下状态之一: 1.排队状态(Ready),在用户创建了一个线程以后,这个线程不会立即运行.当线程中的方法start()被调

Java开发中的线程安全选择与Swing[Z]

安全 Swing API的设计目标是强大.灵活和易用.特别地,我们希望能让程序员们方便地建立新的Swing组件,不论是从头开始还是通过扩展我们所提供的一些组件. 出于这个目的,我们不要求Swing组件支持多线程访问.相反,我们向组件发送请求并在单一线程中执行请求. 本文讨论线程和Swing组件.目的不仅是为了帮助你以线程安全的方式使用Swing API,而且解释了我们为什么会选择现在这样的线程方案. 本文包括以下内容: 单线程规则:Swing线程在同一时刻仅能被一个线程所访问.一般来说,这个线程

Thread and Sync In C# (C#中的线程与同步)

Don't believe everything they've told you. Threads in C# are actually pretty easy.   别相信别人告诉你的所有的事.其实C#中的线程是很简单的.   A thread is an encapsulation of the flow of control in a program. you might be used to writing single-threaded programs - that is, pro

Excel开发中与线程相关的几个问题

采用VSTO或者Shared Add-in等技术开发Excel插件,其实是在与Excel提供的API在打交道,Excel本身的组件大多数都是COM组件,也就是说通过Excel PIA来与COM进行交互.这其中会存在一些问题,这些问题如果处理不好,通常会导致在运行的时候会抛出难以调试的COM异常,从而导致我们开发出的Excel插件的不稳定. 和普通的WinForm程序一样,Excel也是一种STA(Single Thread Apartment)线程的应用程序,Excel插件是寄宿在Excel中运

Lucene 3.6.2入(3) 简述Lucene中常见的搜索功能

package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.

java中的线程

编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield(),join() 还有一个重要的关键字:synchronized 本文将对以上内容进行讲解. 一:run()和start() 示例1: public class threadtest extends thread{public void run(){for(int i=0;i<10;i++){system.out.print(" &q

Delphi中的线程类(2)

首先就是构造函数: constructor TThread.Create(CreateSuspended: Boolean); begin inherited Create; AddThread; FSuspended := CreateSuspended; FCreateSuspended := CreateSuspended; FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThrea

Java 6中的线程优化真的有效么?

介绍 - Java 6中的线程优化 Sun.IBM.BEA和其他公司在各自实现的Java 6虚拟机上都花费了大量的精力 优化锁的管理和同步.诸如偏向锁(biased locking).锁粗化(lock coarsening).由逸出(escape)分析产生的锁省略.自适应自旋锁(adaptive spinning)这些特性,都是通过在应用程序线程之间更高效地共享数据,从而提 高并发效率.尽管这些特性都是成熟且有趣的,但是问题在于:它们的承诺真的 能实现么?在这篇由两部分组成的文章里,我将逐一探究