openmp 任务调度 for schedule static dynamic guided runtime
2015-03-08 11:48
411 查看
OpenMP中,任务调度主要用于并行的for循环中,当循环中每次迭代的计算量不相等时,如果简单地给各个线程分配相同次数的迭代的话,会造成各个线程计算负载不均衡,这会使得有些线程先执行完,有些后执行完,造成某些CPU核空闲,影响程序性能。例如以下代码。
如果将最外层循环并行化的话,比如使用4个线程,如果给每个线程平均分配25次循环迭代计算的话,显然i=0和i=99的计算量相差了100倍,那么各个线程间可能出现较大的负载不平衡情况。为了解决这些问题,OpenMP中提供了几种对for循环并行化的任务调度方案。
在OpenMP中,对for循环并行化的任务调度使用schedule子句来实现,下面介绍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参数是非法的(不需要使用,如果使用的话编译器会报错)。
静态调度(static)
当parallel for编译指导语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大约n/t次迭代计算。
这里为什么说大约分配n/t次呢?因为n/t不一定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定了size参数的话,那么可能相差一个size。
静态调度时可以不使用size参数,也可以使用size参数。
不使用size参数时,分配给每个线程的是n/t次连续的迭代,不使用size参数的用法如下:
#pragma omp parallel for schedule(static)
例如以下代码:
四核,每个运行2-3次。
使用size参数时,分配给每个线程的size次连续的迭代计算,用法如下:
#pragma omp parallel for schedule(static, N)
例如以下代码:
动态调度(dynamic)
动态调度是动态地将迭代分配到各个线程,动态调度可以使用size参数也可以不使用size参数,不使用size参数时是将迭代逐个地分配到各个线程,使用size参数时,每次分配给线程的迭代次数为指定的size次。
下面为使用动态调度不带size参数的例子:
#pragma omp parallel for schedule(dynamic)
任务0-3分配给了线程1-4,之后任务分配给了线程0、2
下面为使用动态调度带size参数的例子:
#pragma omp parallel for schedule(dynamic, N)
每3个作一次动态分配
guided调度(guided)
guided调度是一种采用指导性的启发式自调度方法。开始时每个线程会分配到较大的迭代块,之后分配到的迭代块会逐渐递减。迭代块的大小会按指数级下降到指定的size大小,如果没有指定size参数,那么迭代块大小最小会降到1。
下面为使用引导调度不带size参数的例子:
#pragma omp parallel for schedule(guided)
分配数量逐渐从5,4,3,2减小。
下面为使用引导调度不带size参数的例子:
#pragma omp parallel for schedule(guided,N)
runtime调度(rumtime)
runtime调度并不是和前面三种调度方式似的真实调度方式,它是在运行时根据环境变量OMP_SCHEDULE来确定调度类型,最终使用的调度类型仍然是上述三种调度方式中的某种。
例如在unix系统中,可以使用setenv命令来设置OMP_SCHEDULE环境变量:
setenv OMP_SCHEDULE “dynamic, 2”
上述命令设置调度类型为动态调度,动态调度的迭代次数为2。
在windows环境中,可以在”系统属性|高级|环境变量”对话框中进行设置环境变量。
#pragma omp parallel for schedule(runtime)
void test1() { 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的用法。
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参数是非法的(不需要使用,如果使用的话编译器会报错)。
静态调度(static)
当parallel for编译指导语句没有带schedule子句时,大部分系统中默认采用static调度方式,这种调度方式非常简单。假设有n次循环迭代,t个线程,那么给每个线程静态分配大约n/t次迭代计算。
这里为什么说大约分配n/t次呢?因为n/t不一定是整数,因此实际分配的迭代次数可能存在差1的情况,如果指定了size参数的话,那么可能相差一个size。
静态调度时可以不使用size参数,也可以使用size参数。
不使用size参数时,分配给每个线程的是n/t次连续的迭代,不使用size参数的用法如下:
#pragma omp parallel for schedule(static)
例如以下代码:
void parallel_for_schedule_static1() { #pragma omp parallel for schedule(static) for(int i = 0; i < 10; i++ ) { printf("i=%d, thread NO=%d\n", i, omp_get_thread_num()); } }
四核,每个运行2-3次。
使用size参数时,分配给每个线程的size次连续的迭代计算,用法如下:
#pragma omp parallel for schedule(static, N)
例如以下代码:
void parallel_for_schedule_static2() { #pragma omp parallel for schedule(static, 2) for(int i = 0; i < 10; i++ ) { printf("i=%d, thread NO=%d\n", i, omp_get_thread_num()); } }每次指定运行2次。所以线程0运行了4次,其他都是2次。
动态调度(dynamic)
动态调度是动态地将迭代分配到各个线程,动态调度可以使用size参数也可以不使用size参数,不使用size参数时是将迭代逐个地分配到各个线程,使用size参数时,每次分配给线程的迭代次数为指定的size次。
下面为使用动态调度不带size参数的例子:
#pragma omp parallel for schedule(dynamic)
void parallel_for_schedule_dynamic1() { #pragma omp parallel for schedule(dynamic) for(int i = 0; i < 10; i++ ) { printf("i=%d, thread NO=%d\n", i, omp_get_thread_num()); } }
任务0-3分配给了线程1-4,之后任务分配给了线程0、2
下面为使用动态调度带size参数的例子:
#pragma omp parallel for schedule(dynamic, N)
void parallel_for_schedule_dynamic2() { #pragma omp parallel for schedule(dynamic, 3) for(int i = 0; i < 10; i++ ) { printf("i=%d, thread NO=%d\n", i, omp_get_thread_num()); } }
每3个作一次动态分配
guided调度(guided)
guided调度是一种采用指导性的启发式自调度方法。开始时每个线程会分配到较大的迭代块,之后分配到的迭代块会逐渐递减。迭代块的大小会按指数级下降到指定的size大小,如果没有指定size参数,那么迭代块大小最小会降到1。
下面为使用引导调度不带size参数的例子:
#pragma omp parallel for schedule(guided)
void parallel_for_schedule_guided1() { #pragma omp parallel for schedule(guided) for(int i = 0; i < 20; i++ ) { printf("i=%2d, thread NO=%d\n", i, omp_get_thread_num()); } }
分配数量逐渐从5,4,3,2减小。
下面为使用引导调度不带size参数的例子:
#pragma omp parallel for schedule(guided,N)
void parallel_for_schedule_guided2() { #pragma omp parallel for schedule(guided, 4) for(int i = 0; i < 20; i++ ) { printf("i=%2d, thread NO=%d\n", i, omp_get_thread_num()); } }分配数量逐渐从5减小到4。
runtime调度(rumtime)
runtime调度并不是和前面三种调度方式似的真实调度方式,它是在运行时根据环境变量OMP_SCHEDULE来确定调度类型,最终使用的调度类型仍然是上述三种调度方式中的某种。
例如在unix系统中,可以使用setenv命令来设置OMP_SCHEDULE环境变量:
setenv OMP_SCHEDULE “dynamic, 2”
上述命令设置调度类型为动态调度,动态调度的迭代次数为2。
在windows环境中,可以在”系统属性|高级|环境变量”对话框中进行设置环境变量。
#pragma omp parallel for schedule(runtime)
void parallel_for_schedule_runtime() { #pragma omp parallel for schedule(runtime) for(int i = 0; i < 10; i++ ) { printf("i=%2d, thread NO=%d\n", i, omp_get_thread_num()); } }
相关文章推荐
- openmp 任务调度 for schedule static dynamic guided runtime
- OpenMP中的任务调度----schedule()
- Java任务调度框架Quartz入门教程指南(二) 使用job、trigger、schedule调用定时任务
- [论文阅读笔记]DyTa: dynamic symbolic execution guided with static verification results
- OpenMP学习之--任务划分与调度(代码示例)
- 任务调度平台Cuckoo-Schedule
- LTS 轻量级分布式任务调度框架(Light Task Schedule)
- DYNAMIC_DOWNCAST、STATIC_DOWNCAST、CRuntimeClass和IsKindOf
- OpenMP中的任务调度
- LTS 轻量级分布式任务调度框架(Light Task Schedule) - 推酷
- OpenMP中的任务调度
- python中的轻量级定时任务调度库:schedule
- 06 Spring 异步执行,任务调度(@Schedule、@Async)
- OpenMP编程的任务调度控制
- OpenMP中的任务调度
- 06 Spring 异步执行,任务调度(@Schedule、@Async)
- Microsoft Visual Studio ~ C/C++ Runtime Library ~ Static/dynamic linking
- OpenMP中的任务调度
- Using the ASP.Net Runtime for extending desktop applications with dynamic HTML Scripts
- 开源分布式任务调度平台Cuckoo-Schedule