• OpenMP模式下多线程文件操作(五)


    线程的调度优化

    1. 引言

        通过前边的介绍,知道了并行区域,默认情况下会自动生成与CPU个数相等的线程,然后并行执行并行区域中的代码。对于并行区域中的for循环有特殊的声明方式,这样不同的线程可以分别运行for循环变量的不同部分。通过锁同步(atomic、critical、mutex函数)或事件同步(nowait、single、section、master)来实现并行区域的同步控制。

        那么系统是如何对线程进行调度的呢?具体的调度策略均有底层完成,本节介绍几种for可以在上层对for循环进行控制的调度策略。

    2. 调度策略

       

        调度策略                  功能                                                                                                 适用场合

        static                     循环变量区域分为n等份,每个线程平分n份任务                                       各个cpu的性能差别不大

        dynamic                 循环变量区域分为n等份,某个线程执行完1份之后执行其他需要执行的         cpu之间运行能力差异很大

                                      那一份任务

        guided                   循环变量区域由大到小分为不等的n份,运行方法类似dynamic                   由于任务比dynamic不同,

                                                                                                                                             所以可以减少调度开销

        runtime                  在运行时来适用上述三种调度策略中的一种,默认使用static

        示例:

    3.1. static

       

    ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
    1. #include <iostream>   
    2. #include <omp.h>   
    3.   
    4. int main()  
    5. {  
    6.   
    7. //static调度策略,for循环每两次迭代分为一个任务   
    8. #pragma omp parallel for schedule(static, 2)   
    9.     for(int i = 0; i < 10; ++i)  
    10.     {  
    11.     //被分为5个任务,其中循环0~1,4~5, 8~9分配给了第一个线程,   
    12.      //其余的分配给第二个线程   
    13.          std::cout << "thread id: " << omp_get_thread_num() << " value: " << i << std::endl;  
    14.     }  
    15.   
    16.     return 0;  
    17. }  

    3.2. dynamic

       

    ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
    1. #include <iostream>   
    2. #include <omp.h>   
    3.   
    4. int main()  
    5. {  
    6.     //dynamic调度策略,for循环每两次迭代分为一个任务   
    7.     #pragma om parallel for schedule(dnamic, 2)   
    8.     for(int i = 0; i < 10; ++i)  
    9.     {  
    10.     //分为5个任务,只要有任务并且线程空闲,那么该线程会执行该任务   
    11.          std::cout << "thread id: " << omp_get_thread_num() << " value: " << i << std::endl;  
    12.     }  
    13.   
    14.     return 0;  
    15. }  

    3.3. guided

        guided调度策略与dynamic区别在于,所分的任务块是从大到小排列的。具体分块算法为:每块的任务大小为:【迭代次数/线程个数的二倍】。其中每个任务的最小迭代次数由guided声明设定,默认为1。

        举例说明:

       

    ·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
    1. #pragma omp for schedule [guided, 80]   
    2.   
    3. for(int i = 0; i < 800; ++i)  
    4. {  
    5.     // .....   
    6. }  

    两个cpu,那么任务分配如下:

    第一个任务: [800/(2*2)] = 200

    第二个任务:第一个任务分了200,还有600,那么[600/(2*2)] = 150

    第三个任务:第二个任务分了150,还有450,那么[450/2*2)] = 113

    第四个人任务:第三个任务分了113,还有337,那么[337/(2*2)] = 85

    第五个任务:第四个任务分了85,还有252,那么[252/(2*2)] = 63, 小于声明的80,那么这里为80

    第六个任务:第五个任务分了80,还有172,根据声明,这里为80(因为会小于80)

    第七个任务:第六个任务分了80,还有92,根据声明,这里为80(因为会小于80)

    第八个任务:第七个任务分了80,还有12,根据声明,这里为12(因为不够80)

    3.4.runtime

    运行时底层动态选择调度策略。

  • 相关阅读:
    Vue.js中学习使用Vuex详解
    vuex存储和本地存储(localstorage、sessionstorage)的区别
    Java 编译与反编译
    Vue导航守卫beforeRouteEnter,beforeRouteUpdate,beforeRouteLeave详解
    Vue生命周期简介和钩子函数
    微信开发----被动回复用户消息
    C#4.0 System.Dynamic
    Mvc5 控制器,视图简单说明
    JQuery 禁用后退按钮
    防止用户多次点击
  • 原文地址:https://www.cnblogs.com/BIGFOOT/p/2162235.html
Copyright © 2020-2023  润新知