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.csdn.net/detail/xwebsite/3843187