资 源 简 介
OpenMP是由The Board of the OpenMP Architecture Review Board(ARB)提出的一套用于共享内存并行系统的多线程程序设计标准。目前,OpenMP仅支持C、C++和Fortran语言。由于OpenMP是一种共享存储的标准,所以在非共享存储系统上不能使用,如集群(Cluster)(目前在非共享存储系统上并行主要采用MPI)。简而言之,OpenMP就是一种多线程程序设计的标准,适合在个人计算机上进行并行计算。它提供了对并行算法的抽象描述,程序员只需在源代码中加入专用的pragma来指明,编译器将自动将程序进行并行。并行计算程序设计基础可竿的例子性C)活动bug)≌P:活动wn32)禁月话H将 WHer t视为内置光型是( Zc char t削kcr环汇回中的合规性是 VLc forscoM启月运行叶型信是 openmp).CCt出文件浏信息命令行D接器洁兰T具XML文栏生成器浏览信息D主Y事件D自定义生成骤b代分析penMP支持H用(enMp)请扩, openmp)在文件中添加如下代码循环测试函数这是一个串行测试程序获取起始时间计算耗时为并行计算程序设计基础以上代码中红色字体为添加的代码,以上程序是一个典型的串行程序,经过随机运行次,其平均耗时约(具体所耗时间跟测试计算机有密切的关系,测试电脑采用核)下面将其转换成并行程序,只需要在循环加上即可,如下代码(注意红色部分):循环测试函数这是一个并行测试程序获取起始时间计算耗时为:上述并行程序如果采用编写,其代码为progran maininteger 1real starttime endl imestarttime=omp get wtime oSomp parallel doDOi=0,10000call testoEND DOendtime=omp get wtime o)Write(*,*)“计算耗时为:", endt ime- starttime并行计算程序设计基础Read(=,*end!子程序subroutine testointeger 1doi=0,10000End do同样,也绎过次随机的运行,采用编写的并行程序平均耗时约为采用编写的并行程序平均耗时约为。两种不同运行方式的比较结果如下表所示匚次数串行串行并行并行「平均值注:时间单位为。两种运行方式的结果如下图所示:串行与并行运行方式比较←串行(++)串行( otrar2)a并行〔C++)并行(xtr0.24各6次数从上面的分析结果可见,采用并行所耗时间仗为串行的节约近倍的时间。并行计算程序设计基础二、0 penMP概述根据计算平台和规模的不同,并行计算可以分为两种:第一种是基于单计算机系统的多核处理器或多处理器进行多线程并行计算,采川共享存储的方式,主要的标准有如下左图所小;第二种就是基于多台计算机组件的集群()计算系统进行并行讣算,采用消息传递方式,主要的标准有如下右图所示。本文将主要介绍多线程方式的并行讣算。②e②ProcessorsMemonMemoryIntcrconncction nctwork首先来了解一下单核处理器上程序运行方式,系统中包括操作系统和应用程序等都以进程()形式存在,当程序结束时这个进程也就跟着消亡。每个进程中不少包含一个线程(),一个线程用于完成程序的某个功能个程序中一般都包含多个线程,所有的这些线程在系统中都成队列形式。对于个核心的处理器来说,某·吋刻,它只能处理一个线程。这个线程处理之后就处理下一个线程,依次循环处理。由于的主频都非常高,如的奔四可到,所以每个线程处理的时间都非常短,以致我们并不会察觉。但是它们实际上是以串行的形式在上运行。所以在物理上,对于单核处理器来说,是无法实现物理上的并行。在单核处理器上,即使使用多线程来分发程序,但实际上还是以单线程的形式在运行。如果将执行核增加一个,那么在同一时刻,将会有两个线程在运行,这样将会在一定程度上提供计算机的运行速度,但对于某些单线程的程序过程来说,实际情况并没用得到改善。至于系统中的线程怎么分发到两个核上,这就是操作系统的任务了。很多应用程序都不止包含一个线程,一般都包含有多个线程,如用工具查看系统所有的线程,如下图所示□监视(S①)图帮出-□n MSC TFIMF I IMSC TFIM= ll口000100D4 tooltips class=z1n2FF否详细+ onltips class2214 000 10306 MSCTF ME JIMSCTFIME UI苦变获取帮励,请安F1并行计算程序设计基础这多个线程如果在一个执行核上运行,它们呈一个队列来执行。如果在两个执行核上运行的话,它们将呈两队来执行。如果某个程序中包括有四个线程,而这四个线程又分别在两个核上执行,那么执行该程序将节约一半的时间。但如果该程序是单线程,无论是单核还是多核,运行该程序所需的时间都将是一样的所以,以前有人在某单线程程序中将一些程序分廾放在两个线程中分别执行,效率得到了提高,节约将近一倍的时间,其原因就在此。桌面应用程序1应用程序X之MCH ES日BUs IFBUs lFCacheCacheExecutionExecutionCoreCore提供的就是一个多线程编程标准,现在平台也提供了并行编程的类,可以使多个线程能够同时执行。如果直接采用多个线程去实现并行,需要绎常处理线程或线程池,采用这些多线程编程标准可以简化并行开发,也不必直接处理线程或线程池在中采用指令的格式如下:关键字表示这个指令是指令,所以它会被编译器处理,其他编译器将不会理会。由于指令都预先定义了,所以很容易被识別出来。这样程序员编写的并行代码就可以在不同的平台上运行。如果平台不支持并行,也会直接跳过并行指令把程序当作串行程序来运行。提供了两种控制并行的结构:第一种就是提供了一个用于创建多线程程序的指令,这些线程相互之间是并行的,这个指令实际上就是创建了一些线程去执行并形体中的程序;第二种就是对已存在的并行结构进行分工的指令,像循环中的指令)或(个程序通常都是从一个单线程程序开始,我们通常把这个单线程程序叫做主线程(),在主线程的程序中应该要包含整个程序中并行计算程序设计基础需要使用的数据变量,包括全局变量。当主线程遇到并行结构时,将会创建新的线程来执行并形体中的程序。每个线程都会独立的执行并形体中的程序,相互之间不会影响,但是它们之间可以共用主线程里面定义的全局变量。在并行过程中具体哪些变量是共享的、哪些变量是线程私有的,可以通过条件.对每个变量进行指定,这些条件用并行线程中决定哪些可用。一个变量可以有三种类型,即和其中表小在并行结构中将有个单独的内存位置来存放这个变量,所有的并行线程都可以使用这个变量,所有的并行线程将共享这块内存地址,因此,线程间的通信通过普通的读写操作方式就可以实现,当然,这个变量也可以随意被任何一个线程修改。相反,变量将会有多个内存地址,每个线程里面一个。这个变量的所有读写操作都只限于木线程,其他线程是无法访问木线程中该变量的内存地址的。所以,一般都用于定义临时变量就有点难理解了,它具有和的特征就像它的字面意思一样,属性用于需要下降的变量(指值的减少)操作在很多程序中都非常重要,最常见的例子就是计算并行结构中最后的临时局部变量的总和。除了这三种之外,还提供了许多其他数据属性参数。多个线程之间可以采用共享变量()通过简单的读写操作来进行通信,但是这需要在多个线程中协调一致。如果协调不一致,可能会出现多个线程同时修改这个变量,或者这个线程正在读而那个线程又正在写,这些潜在的冲突都将导致数据的错误,因此,在多线程中必须避免这种情况,必须明确地协调好。在并行程序中设置同步()就可以协调这些执行的多线程。最常见的两种情况就是相互排斥和事件同步,互斥就是在这段代码中通过一个线程不让其他线程读取这个共享变量。当很多线程正在修改同一个变量时,为了确保这个变量值是对的,在修改之前就需要进行互斥存取,中提供指标来表示互斥。事件同步常用于表示多线程间的事件,最简单的形式就是阻塞。在并行程序中指标表示在某点处每个线程都在这等待其他的线程也运行到这里,一日所有的线程都达到这个点后,它们又继续执行。就像跑步的时候,有的人跑得快,有的人跑得慢,在跑了两圈的时候,所有人都在这里等待最后一个人,当最后一个人也饱到两圈的时侯,然后大家又接着继续跑,这个过程就称为阻塞。指令能保证所有线程都执行了在之前的代码。一个典型的并行程序结构如下图所示:并行计算程序设计基础开始并行阻塞 barrier(主线栏在比遇等待所有线程到:r|令形体在此结束法代)主线程高转稈王■日日日日日日日口日口■■■■■■■■■■■串行程序許行程序串行程序是一套非常简便的共享存储并行计算应用程序接口,它是一个多线程、共享存储的模型。线程间通过共享的变量进行交换,并可以通过线程同步来防止数据冲突,当然,同步是需要耗费很多的资源的,所以尽量减少同步的需要。三、并行数目与并形体对运行效率的影响接下来再做一个测试,将并行和串行的循环次数设置为即将上例的函数中更改为:然后分别运行次,其结果如下表所示:次数串行平均值并行计算程序设计基础串行与并行运行方式北较0.008∩.∩0.0024从上面的分析结果可见,在循环次的时候,只有极少数情況下并行计算比串行计算所需的吋间要少,许多情况下并行需要更多的时问,这与我们设计并行程序的初衷是截然相反的。出现这种情况的原因之一就是,在分发并行的吋候,系统也是需要消耗资源的,如果用于并行分发所耗的时间大于并行计算中节约的时间,那么这种情况下的并行计算就显得亳无意义,正如上例中的测试。所以,在并行计算中,并不是所有的并行计算都比串行计算要节约时间,具体要看并行的任务是否值得去做并行计算。还有一个重要的原因就是每次并行的线程数目,由于计算机同时支持的并行线程有限,不可能指定并行次,在同一时刻就能运行个线程。另外,由于这个比较程序的计算量非常小,很容易受到系统中其他因素的影响而导致计算结果的不稳定,所以,建议在进行测试时,尽量将计算量稍微调大一点,同时每次测试时应尽量保讦运行环境相近,以减少系统中其他程序对测试结果的干扰。下面用一个例子更能说明并行数目与程序运行效率问的关系,设置并形体中的计算量都一样,每次只是并行的次数不同,具体代码如下:循环测试函数