2、shedule条件
把并行循环中的计算指定给线程这种方式称为循环队列(loop’s schedule)。对于并行循环中并形体计算量接近的情况,使用默认的队列方式是最优的。但也存在并行循环中每个并行计算量大小不一致的情况,如果计算量大小差距很大,并行程序的执行时间是以最后完成的那个线程为结束标记的,所以如果还采用相同的队列方式,计算量小的线程会先执行完,然后等计算量大的线程执行完,最后才结束并行。在这种情况下,队列分布的不均将会影响整个并行的运行效率,因此,需要去设置其队列选项来控制队列的分布。
schedule条件的格式如下:
schedule(type[,chunk])
其中type有static,dynamic,guided和auto四种,chunk是表示一个并行块的大小。如果需要对1000个循环进行并行,可以将它分成8个并行块(chunk),每个并行块就包括125个循环,则并行块的大小就是125,即chunk size。线程执行的具体对象就是这些并行块chunk。static表示静态分割并行块,在整个并行计算过程中并行块的大小都一样。dynamic则表示动态分割,默认其并行块尺寸为1。guided表示向导性的分割,指定第一个并行块的大小,后面每个并行块的尺寸都会递减,直到最小的并行块尺寸。采用auto或runtime时,不需要设置chunk参数,此时队列类型将由环境变量omp_schedule来控制。
循环结构并行队列过程以及在CPU中执行队列过程如下图所示:
若循环结构中循环次数为100次,通过schedule队列指定每块尺寸为20(即20个循环),则有5个并行块,每个并行块中并形体(一个循环)仍然按串行方式排列。每个并行块对应一个新的线程。若计算机CPU具有4个执行核或4线程,那么每一时刻最多只能执行4个线程,而现在有5个并行块,所以最多只能执行4个并行块,剩下一个并行块就只有在后面,并行计算所耗时间是由最慢的那个线程(并行块)来决定的,所以尽量让这些并行块数目是计算机CPU核心的倍数(1倍或其它整数倍),以充分利用计算机CPU资源。
下面通过一个程序动态设置并行块大小来测试对计算效率的影响,代码如下:
// File: ScheduleTest.cpp
#include "stdafx.h"
#include<omp.h>
#include<iostream>
using namespace std;
//private测试
int ScheduleTest()
{
cout<<"ScheduleTest输出:\n";
inti=0,j,chunkSize = 1;
doublestarttime,endtime;
cout<<"请输入并行块的大小(-200):\n";
cin>>chunkSize;
starttime=omp_get_wtime();
#pragmaomp parallel for private(j)schedule(static,chunkSize)
for(i=0;i<200;i++)
{
for(j=0;j<100000000;j++);
}
endtime=omp_get_wtime();
cout<<"计算耗时为:"<<endtime-starttime<<"s\n";
return0;
}
分别设置并行块大小为1、2等,分别测试其计算耗时,结果如下表所示:
并行块大小 |
计算耗时(s) |
并行块数目 |
每核平均执行并行块数目 |
空闲线程数 |
并行块大小 |
计算耗时(s) |
并行块数目 |
每核平均执行并行块数目 |
空闲线程数 |
1 |
7.08998 |
200 |
25.0 |
0 |
24 |
8.57893 |
9 |
1.0 |
7 |
2 |
7.2503 |
100 |
12.5 |
4 |
25 |
7.05088 |
8 |
1.0 |
0 |
3 |
7.44965 |
67 |
8.3 |
5 |
26 |
7.25465 |
8 |
1.0 |
0 |
4 |
7.67307 |
50 |
6.3 |
6 |
27 |
7.45207 |
8 |
0.9 |
0 |
5 |
7.09083 |
40 |
5.0 |
0 |
28 |
7.87446 |
8 |
0.9 |
0 |
6 |
8.1865 |
34 |
4.2 |
6 |
29 |
8.4484 |
7 |
0.9 |
1 |
7 |
7.69326 |
29 |
3.6 |
3 |
30 |
8.17421 |
7 |
0.8 |
1 |
8 |
8.57003 |
25 |
3.1 |
7 |
31 |
8.41376 |
7 |
0.8 |
1 |
9 |
7.36662 |
23 |
2.8 |
1 |
32 |
8.62639 |
7 |
0.8 |
1 |
10 |
8.30294 |
20 |
2.5 |
4 |
33 |
9.14871 |
7 |
0.8 |
1 |
11 |
9.01532 |
19 |
2.3 |
5 |
34 |
9.09194 |
6 |
0.7 |
2 |
12 |
8.58991 |
17 |
2.1 |
7 |
35 |
9.32059 |
6 |
0.7 |
2 |
13 |
7.27074 |
16 |
1.9 |
0 |
36 |
9.5623 |
6 |
0.7 |
2 |
14 |
7.70015 |
15 |
1.8 |
1 |
37 |
10.0546 |
6 |
0.7 |
2 |
15 |
8.26512 |
14 |
1.7 |
2 |
38 |
10.1078 |
6 |
0.7 |
2 |
16 |
8.72735 |
13 |
1.6 |
3 |
39 |
10.248 |
6 |
0.6 |
2 |
17 |
9.05444 |
12 |
1.5 |
4 |
40 |
10.472 |
5 |
0.6 |
3 |
18 |
9.52952 |
12 |
1.4 |
4 |
50 |
12.572 |
4 |
0.5 |
4 |
19 |
10.0843 |
11 |
1.3 |
5 |
80 |
20.2732 |
3 |
0.3 |
5 |
20 |
10.5465 |
10 |
1.3 |
6 |
100 |
24.5377 |
2 |
0.3 |
6 |
21 |
10.9686 |
10 |
1.2 |
6 |
150 |
36.5224 |
2 |
0.2 |
6 |
22 |
11.4323 |
10 |
1.1 |
6 |
200 |
48.5702 |
1 |
0.1 |
7 |
23 |
10.2983 |
9 |
1.1 |
7 |
从上图以及测试结果可以得知:在每核平均执行并行块数目大于或等于1.0时,并行块数目对计算效率的影响呈锯齿状形态;当每核平均执行并行块数目小于1.0时,计算效率急剧下降;空闲线程数目越多,计算效率越低。当每核平均执行并行块数目为1,且每个并行块中尺寸均匀相等时,计算效率会提供到极大值,上例中即并行块尺寸为25时。若每个循环的计算量相差不大,建议采用static设置每个并行块尺寸一样。
相关程序源码下载地址:
http://download.youkuaiyun.com/detail/xwebsite/3843187