一种多核并行离散事件仿真的内存管理方法
【技术领域】
[0001]本发明涉及多核并行离散事件仿真系统的内存管理方法,尤其是针对多核并行离散仿真系统的内存管理问题,提供一种基于事件包全局虚拟时间估计的逻辑进程循环内存分配与回收管理方法。
【背景技术】
[0002]并行离散事件仿真(ParallelDiscrete Event Simulat1n, PDES)由一组逻辑进程(Logical Process,LP)构成,每个LP有独立的状态,负责自身的模型解算,并且有自己独立的仿真逻辑时间,称为本地虚拟时间(Local Virtual Time,LVT)。并行离散事件仿真系统的LP是并行运行的。LP之间不共享任何的状态变量,仅通过发送和接收事件的方式进行数据传递。
[0003]一般地,多核并行离散事件仿真系统是指在一个或多个CPU上运行的并行离散时间仿真系统,其最主要特征是每个逻辑进程关联到一个CPU物理核,整个仿真系统的程序在一个进程空间内,逻辑进程不需要跨进程通信。多核并行离散事件仿真系统和分布式并行离散事件仿真系统相比,最大优势是逻辑进程间的通信开销小、运行效率高。但由于操作系统的全局统一分配内存需要同步,因此,需要对多核并行离散事件仿真系统使用的内存进行管理。多核并行离散事件仿真系统的内存管理过程包括内存分配、全局虚拟时间(Global Virtual Time, GVT)估计、内存回收三个步骤。
[0004]首先,多个逻辑进程在创建事件时需要同时向操作系统申请内存空间,逻辑进程申请内存的操作容易成为仿真系统运行性能的瓶颈。需要有合适的内存分配方式来解决多个逻辑进程申请内存的竞争问题。
[0005]其次,并行离散事件仿真系统的每个事件都有一个时戳(timestamp),时戳表示事件发生的仿真逻辑时间。为了确保仿真因果关系,每个LP必须按照事件时戳的增序关系顺序处理事件,否则仿真系统将出现因果错误(causality errors)。因此,这样的并行执行机制和因果关系要求,使得并行离散事件仿真必须引入时间同步机制协调LP的运行。当前,同步机制主要有保守时间同步算法和乐观时间同步算法。保守时间同步算法能够严格的防止出现因果错误,但会阻塞LP的运行,使得LP的并行性较差。乐观时间同步算法,也称为时间弯曲(Time Wrap)算法,则不阻塞LP的运行,允许因果错误出现。在乐观时间同步机制下,已处理的事件占用的内存空间不能被逻辑进程立刻回收。逻辑进程将已处理的事件保存起来,当检测到出现因果错误时,通过回滚(rollback)的方式将逻辑进程的状态恢复到之前正常的状态,然后重新按照事件的时序关系继续执行。只有时戳小于全局虚拟时间(Global Virtual Time, GVT)的事件才不会被回滚,其占用的内存空间才可以被安全的回收。全局虚拟时间估计算法的效率和精度直接影响仿真系统内存使用的效率。
[0006]最后,内存的回收方式也会影响内存的使用效率。例如,全局内存池虽然可以解决内存分配竞争的问题,但是内存回收和内存分配还是需要同步操作。
[0007]因此,多核并行离散事件仿真系统的内存管理与内存分配方式、全局虚拟时间估计的精度、内存回收方式相关。仿真系统的内存管理直接影响了仿真系统的运行效率,已经成为仿真领域研宄人员关心的一个关键技术问题。很多研宄人员在这方面做了很多研宄工作,例如全局内存池方法、基于线程的内存池方法等。这些方法可以部分解决内存分配竞争的问题,但是没有和全局虚拟时间的估计相结合,没有完全解决内存是否可回收以及回收方式的问题。
【发明内容】
[0008]本发明要解决的技术问题是:提供一种多核并行离散事件仿真的内存管理方法,满足仿真实验过程中多个逻辑进程同时申请内存空间的要求,避免内存申请同步操作。通过准确估计全局虚拟时间GVT,快速、精确回收事件占用的内存,提高内存的使用效率。
[0009]本方法由N个逻辑进程和一个GVT计算进程实现,其中N为自然数且满足N多2。逻辑进程用LPi表示,下标i为逻辑进程的唯一标识,I ^ i ^ No GVT计算进程用GP (GVTProcess)表示。每个逻辑进程LPi都有一个独立的内存池MemPool i。]^1]1?00]^是一个先入先出(FIFO)的动态队列,队列的大小一般取128、256、512、1024几个典型值,队列的每个元素是一个内存块,在一个内存块上,逻辑进程LPi可以创建用于与其他逻辑进程间进行数据交换的事件。事件定义为四元组BE (s, t, ebi, ts, ed),其中BE.s表示发送该事件的逻辑进程的唯一标识,BE.t表示接收该事件的逻辑进程的唯一标识;BE.ebi是事件的索引,为正整数;BE.ts是事件的仿真时戳,为正实数;BE.ed是事件携带的和具体应用相关的数据,为通用型指针,如void*。逻辑进程LPi有一个事件缓冲队列EventCacheList 1、一个待处理事件队列 UnProEventListjP—个已处理事件队列 ProEventList iD EventCacheListi是一个线程安全的并发队列,用于接收其他逻辑进程发来的事件。对于EventCacheListi,多个事件的插入和读取操作可以并行进行。UnPr0EventListi用于存放逻辑进程LP i的还没有处理事件,ProEventListi用于存放逻辑进程LP ^勺已处理但还没有回收内存的事件。
[0010]此外,所有的逻辑进程都包含以下变量,以逻辑进程1^为例:用于记录逻辑进程LPi的事件包索引的变量ebi i,ebiiS正整数;事件包的大小EventSize p EventSizei为正整数;逻辑进程LPi自身记录的全局虚拟时间GVTValue PGVTValueiS正实数;记录LPi的仿真结束时间的变量StopTimei,正实数;逻辑进程LP ^勺本地虚拟时间LVT ^ LVTi为正实数;逻辑进程1^发送的事件的最小时戳MTS i,MTS^正实数;逻辑进程LP i给其他逻辑进程发送的事件的计数器SntCi, SntCiS正整数;记录逻辑进程LP ,收到的其他进程发来的事件的计数器,称为暂态事件计数器RcvMapi。一个大小可以动态变化的动态队列,队列的每个元素是一个形如(eventKey、EValue)的二元组,二元组的键eventKey是事件的索引,值EValue是逻辑进程LPi收到的索引为对应键值的事件的数量。
[0011]所有的逻辑进程通过构建自己的事件包消息向GVT计算进程GP发送估计GVT所需的数据。事件包消息定义为五元组EBR(id,ebi, LVT, MTS, TMMap),其中EBR.1d是发送该事件包消息的逻辑进程的唯一标识,若逻辑进程LPi*送事件包消息,那么EBR.1d的取值为i。EBR.ebi是事件包消息产生时对应的逻辑进程的事件包索引,若逻辑进程LPi发送事件包消息,那么EBR.ebi取值为eb1- EBR.LVT记录逻辑进程的本地虚拟时间,EBR.MTS记录逻辑进程发送的事件的最小时戳。EBR.TMMap称为事件包消息的暂态事件计数器,它和逻辑进程LPi的暂态事件计数器RcvMap i有相同的数据结构。逻辑进程LP 送事件包消息时,LP^f RcvMap i的数据完全赋值给EBR.TMMap。
[0012]GVT计算进程GP通过事件包消息缓冲队列EBRCacheList储存所有逻辑进程发来的事件包消息。EBRCacheList是一个线程安全的并发队列。多个逻辑进程可以并发地向一个GVT计算进程的事件包消息缓冲队列插入多个事件包消息。此外,GP通过三个动态队列TMCMap, MTSMap和LVTMap记录所有逻辑进程发来的每个事件包消息的数据。其中,暂态消息队列TMCMap是大小可以动态变化的队列,队列的每个元素是一个形如(ebKey、EBValue)的二元组,二元组的键ebKey是事件包消息的索引,值EBValue是有相同索引的事件的数量。事件最小时戳队列MTSMap是大小可以动态变化的队列队列的每个元素是一个形如(ebKey、MTValue)的二元组,二元组的键ebKey是事件包消息的索引,值MTValue记录事件包消息的发送事件的时戳最小值EBR.MTS ;本地虚拟时间队列LVTMap是大小可以动态变化的队列,队列的每个元素是一个形如(ebKey、TValue)的二元组,二元组的键ebKey是事件包消息的索引,值TValue记录事件包消息记录的本地虚拟时间EBR.LVT。此外,GVT计算进程还包含一个GVTValue变量和一个StopTime变量。GVTValue变量用于记录估计出的GVT时间,GVTValue是正实数;变量StopTime记录仿真结束时间,StopTime是正实数。
[0013]GP通过计算获得GVT的新的估计值后,通过GVT通知消息给其他逻辑进程发送GVT的值,GVT通知消息表示为GN(NewGVTValue),其中GN.NewGVTValue表示新的GVT估计值,为正实数。
[0014]本方法的基本处理过程是:首先创建N个逻辑进程和一个GVT计算进程,N个逻辑进程、GVT计算进程同时进行初始化;然后N个逻辑进程并行地处理事件、向自己的内存池申请内存、发送事件、接收事件、向GVT计算进程发送事件包消息;GVT计算进程收集到N个具有相同索引的事件包消息后计算GVT的值,然后向所有逻辑进程发送GVT通知消息;最后N个逻辑进程并行地读取GVT通知消息并获取GVT的值,再回收时戳小于全局虚拟时间的事件占用的内存。回收的内存放入处理事件的逻辑进程的内存池,而非内存被分配时所在的内存池。例如,逻辑进程LPi向MemPool i申请的内存,创建事件BE (i,j, ebi, ts, ed)并发给逻辑进程LPj (i Φ j),事件BE(i,j,ebi,tS,ed)占用的内存将被逻辑进程LPj的内存池MemPoolj回收。反之,逻辑进程LP」给逻辑进程LP i发送的事件BE(j, i, ebi, ts, ed)占用的内存被逻辑进程LPi的内存池MemPool i回收。这就是循环内存分配与回收方法。
[0015]具体的技术方案如下:
[0016]第一步:创建N个逻辑进程和一个GVT计算进程,GVT计算进程进行初始化,N个逻辑进程并发地进行初始化并分配内存池。1.1,1.2是两个并行的步骤。
[0017]1.1:GVT计算进程初始化,具体步骤是:首先给StopTime赋值,如StopTime =5000。StopTime的取值和具体的应用相关,可以取任何的正实数,如5000,单位可以为秒、分钟、小时等时间单位。然后令GVTValue = 0,GVTValue的单位和StopTime的单位相同。最后GVT计算进程转到第四步。
[0018]1.2:N个逻辑进程并行地初始化,逻辑进程LPi进行初始化的方法是=StopTimei =StopTime,GVTValuei= O, ebi j= I, LVT j = 0,MTS j = 0,SntCi= 0, RcvMap 丨为空,EventSize j的取值为 2P 形式,P 为自然数,EventSize i—般取值为 8、16、32、64、128,EventCacheList $空,ProEventLiSti为空。逻辑进程LP i将初始事件插入待处理事件队列UnProEventList ^初始事件的个数不小于I。N个逻辑进程执行第二步。
[0019]第二步:N个逻辑进程并行地处理事件、发送事件和接收事件。每个逻辑进程通过自己的并发事件缓冲队列实现同时接收多个事件以及读取事件所需的同步操作。逻辑进程1^处理事件、发送事件和接收事件的方法为:
[0020]2.1:设置逻辑进程1^的变量,MTSi= OjntCi= 0,RcvMap i为空,令已处理事件计数器PEventCoun