专利名称:一种基于配置文件的帮助线程构造方法
技术领域:
本发明涉及一种基于配置文件的帮助线程构造方法,属于多核多线程技术领域。
背景技术:
多核多线程技术是利用多核处理器中的多处理核来并发执行多线程应用程序的一项技术。片上多核处理器架构通常具有共享的最后一级缓存。传统的硬件预取可对应用程序中的规则数据进行预取,并提前送至该共享缓存中,当应用程序访问到这些规则数据时,在共享缓存中便会找到所需数据,而不用再进行主存访问。然而,对地址不连续的非规则数据访问(如链表、非规则数组),由于访问地址的不连续性,传统硬件预取技术常会失效。这种情况下,基于帮助线程的预取技术被提出,它通过构造应用程序的预取帮助线程和使其在空闲核上执行,来提前访问这些非规则数据,并及时推送它们到共享缓存中,以提高应用程序的访存性能。对用户来说,人工设计这类预取帮助线程是一个困难任务,建立自动生成辅助工具十分必要。这种困难主要表现在两方面一、帮助线程与应用程序间需要建立协同机制,以防止帮助线程因执行太快造成的预取数据过早问题;也要防止帮助线程执行过慢,导致应用程序已访问过这些数据、预取数据已无用的情况出现。二、应用程序需知道帮助线程的执行情况,而帮助线程也需知道应用程序的执行情况。虽然国际上已有基于代码复制的帮助线程自动生成技术,但它未能很好解决上述的预取过早或预取过晚等问题,难以确保帮助线程的构造质量。基于这一原因,本发明实现了一种基于配置文件的帮助线程构造方法。
发明内容
本发明的目的是为克服上述问题,针对非规则数据,提出一种基于配置文件的帮助线程构造方法。该方法在减轻用户或程序员编程困难的同时,通过引入预取提前量、预取量和同步量等控制变量,来对帮助线程预取过早或预取过晚等问题进行有效控制。本发明可广泛用于面向非规则应用的多核编译器优化及数据库性能的改进。为了解释我们方法所涉及的步骤中有关术语的含义,首先给出这些技术术语的定乂 定义I :热函数对应用程序P中的任一函数F (P),利用性能分析工具分别生成该函数F (P)和应用程序P的片外访存缺失计数和时钟周期计数,若该函数F (P)满足“F (P)的片外访存缺失计数/P的片外访存缺失计数和F (P)的时钟周期计数/P的时钟周期计数均大于经验阈值”,则F (P)是一个热函数。定义2:热数据区我们把热函数所访问的数据区域称为一个热数据区。定义3:配置文件针对一个非规则应用程序P的多个热数据区,依次为每个热数据区以字符串形式构造出与帮助线程关联的代码区、帮助线程的控制变量组和帮助线程的“数据推送与同步变量”组,这些字符串经合并后形成一个总字符串,并把该总字符串存为一个文件,我们称该具有帮助线程构造特征的文件为配置文件。本发明的一种基于配置文件的帮助线程构造方法的整体框架设计流程如图I所示,其特征在于其基本思想是在基于共享缓存的多核架构基础上,针对多核应用中非规则数据缺失的问题,通过引入“构造帮助线程的配置文件、构造帮助线程的控制变量和初值、构造帮助线程的生成代码”等步骤,来自动生成帮助线程,以降低程序员或用户的编程难度,提高应用程序的执行性能,并为多核编译辅助工具提供有效的支撑技术。具体实现步骤如下步骤一、构造帮助线程的配置文件在上述相关术语定义的基础上,从应用程序中人工或自动提取帮助线程的构造特征,生成一个配置文件。基本思想是利用应用程序中的多个热数据区,通过提取它们的帮助线程构造特征序列,经合并后构造出配置文件。其主要操作步骤如下第(I)步设置SUM总序列变量为空;依据定义I,确定应用程序P中所有热函数的集合HS ;从肥中选择任一热函数f (P)作为当前需处理的热函数;第(2)步依据定义2确定该热数据区,提取和构造其中与帮助线程相关的代码区标定序列A = ‘〈hot_spot_area>〈换行控制符>hotspotarea_begin=热数据区的起始行号<换行控制符>hotspotarea_end=热数据区的结束行号〈换行控制符>source_file=热数据区所在的源文件名〈换行控制符〉funCti0n_name=热数据区所在的函数名’;第(3)步设置该热数据区的帮助线程控制变量组序列B = ‘ahead_siZe=设定的预取提前量大小〈换行控制符>push_size=设定的预取量大小〈换行控制符>sync_size=设定的同步量大小’;这里ahead_size、push_size和sync_size均为一个非负整数;第(4)步如果该热数据区中不存在任何子区,则依据性能分析工具的数据缺失标注信息,从该热数据区中提取和构造帮助线程的“推送变量和同步变量”组序列C =‘hotspot_line=第I个推送变量所在的行号〈换行控制符>push_variable=第I个推送变量名〈换行控制符>*“hotspot_line=第η个推送变量所在的行号〈换行控制符>push_variable=第η个推送变量名〈换行控制符〉sync_variable=应用程序和帮助线程间第I个同步变量名〈换行控制符〉…sync_variable=应用程序和帮助线程间第m个同步变量名〈换行控制符>〈/h0t_sp0t_area>’ ;否则,如果推送变量在该热数据区中的某个函数内部,则需产生一个<child_hot_spot>. . . </child_hot_spot>子区,从该热数据区中提取和构造帮助线程的“推送变量和同步变量”组序列C = ‘hotspotjine=推送变量所在的行号〈换行控制符>〈child_hot_spot>〈换行控制符>child_source_file=子区中该函数所在的文件〈换行控制符>child_function_name=子区中该函数名〈换行控制符>child_hotspot_line=子区第I个推送变量所在的行号〈换行控制符>child_push_variable=子区中第I个推送变量名〈换行控制符>“child_hotspot_line=子区第η个推送变量所在的行号〈换行控制符>child_push_variable=子区中第η个推送变量名〈换行控制符X/child_hot_spotX换行控制符>sync_variable=应用程序和帮助线程间第I个同步变量名〈换行控制符>··· sync_variable=应用程序和帮助线程间第m个同步变量名〈换行控制符>〈/hot_spot_area>,;
第(5 )步SUM = SUM+<换行控制符>+序列A+〈换行控制符>+序列B+〈换行控制符>+序列C ;第(6)步若HS中存在任何其他未处理的热函数,则转第(2)步;否则,依据定义3,由SUM序列生成帮助线程的配置文件,并在第一行插入〈begin〉,最后一行插入〈/end〉,结束;步骤二、构造帮助线程的控制变量和初值在步骤一构造配置文件的基础上,步骤二自动转换配置文件序列中的数据为构造帮助线程所需的控制变量和初值。其基本思想是将配置文件序列中的数据变换成构造帮助线程代码所需的控制变量和初值,并对推送变量和同步变量的初值进行完整性验证和修正。其主要操作步骤如下第(I)步如果配置文件非空,将配置文件中的第一个<hot_spot_area>. . . </h0t_Sp0t_area>序列作为当前的工作区(WA),并置WAC计数器为I;否则退出结束;第(2)步构造当前工作区的控制变量结构为‘typedefstructpushVarlnfoNode{int line;string varName;int type;}pushVarlnfo;typedefstructsliceNode{int sliceStart;int siiceEnd;string sliceFunc;string sIiceFile;vector<pushVarInfo>var_push;vector<string>var_sync;int K, P,B;vector<string>var_depl;vector<string>var_dep2;SgStatement*copyed;}slice’,并将 slice[WAC]实例化为 slice;第(3)步从当前工作区依序解析该<hot_spot_area>. . . </hot_spot_area> 序列, 并使 siiceStart=hotspotarea_begin, siiceEnd=hotspotarea_end, sliceFunc=function_name, sliceFile=source_file, K=ahead_size, P=push_size,B=sync_size ;var_push=push_variabIe 表,var_sync=sync_variable 表;第⑷步:依据slice [WAC]中 sliceStart, sliceEnd, sliceFunc 和 sliceFile 当前的取值,标定其在应用程序P中的位置,并记录所标定区域的代码到copyed变量中;第(5)步依据var_push和copyed的变量初值,搜索推送变量的所有依赖变量,并记录到推送变量依赖表var_depl中,完成对var_push的验证和修正;具体可分步为5. I)首先将var_push初值放入推送变量依赖表var_depl中;5. 2)对推送变量依赖表var_cbpl中的每一项,在copyed变量值中查找其直接依赖的推送变量,若存在新的依赖变量,将其放入var_depl中;5. 3)重复5. 2)直到没有新的推送变量加入为止;第(6)步依据var_sync和copyed变量初值,在copyed变量值中搜索所有直接依赖的同步变量,并记录到同步变量依赖表中var_dep2,完成对var_sync的验证和修正。具体可分步为6. I)首先将var_sync放入同步变量依赖表var_dep2中;6. 2)对同步依赖表var_cbp2中的每一项,在copyed变量值中查找其直接依赖的同步变量,若存在新的同步变量,将其放入该var_cbp2中;6. 3)重复6. 2)直到没有新的同步变量加入为止;第(7)步如果配置文件序列中还存在其他的‘〈hot_spot_area>. . . </hot_spot_area〉’子串,则选择其中之一作为当前工作区,并置WAC计数器加1,转第(2)步,否则结束。
步骤三、构造帮助线程的生成代码在步骤二构造帮助线程控制变量和初值的基础上,步骤三构造帮助线程的生成代码。其基本思想是依据帮助线程的控制变量和初值,自动生成帮助线程的代码。主要操作步骤如下第(I)步分别在应用程序P的main函数、帮助线程的push, h和push, c文件中增加构造代码,具体可分步为I. I)在main函数所在文件中加入帮助线程头文件名push, h,该push, h头文件中的代石马包括iVoid init_pushthread O {pthread_create (&push_thread_id, O, push_thread_func, 0) ;}〈换行控制符 >void destroy_pushthread () {pthread_cancel (push_thread_id) ;}〈换行控制符 >...〈换行控制符 >#definePUSHDATA (ADDR) asm volatile (Vefetchtl (%0) 〃 〃r〃 (ADDR))〈换行控制符 >,等;I. 2)在main函数的开始部分,增加帮助线程的创建函数init_pushthread();在main函数返回前,调用该帮助线程终止函数destroy_pushthread O ;由于main函数可能有多个返回点,在其中每一个返回点前,都需加上该帮助线程的终止函数;I. 3)构造 push, c 的 push_thread_func 为 ‘void*push_thread_func (void*arg)〈换行控制符>{for(;;)〈换行控制符>{···〈换行控制符>while(! (inter_push_flag!=’ \0’)) {<换行控制符>}〈换行控制符>switch(inter_push_flag) {<换行控制符>casel:〈换行控制符>{}〈换行控制符>case2:〈换行控制符>{}…〈换行控制符>}〈换行控制符>inter_push_flag=’ \0’ ; <换行控制符>} <换行控制符>} <换行控制符>’;I. 4)设置ss变量为I;第(2)步依据ss变量值修改push, c的push_thread_func代码,具体可分步为2. I)在 push, c 的 push_thread_func 中,将 ‘case,+string (ss) + ‘ ,+〈换行控制符 >+ ‘{}’替换为‘case’+string (ss)+ ‘’+〈换行控制符 >+ ‘{’+ ‘slice’+string(ss)+ ‘();break;} ’ ;2. 2)为帮助线程的 push_thread_func 创建一个名为’ slice’ +string(ss)的空函数,即当ss=l时创建一个‘void slicel O {} ’或当ss=2时创建一个‘void slice2 () {} ’等;第(3)步为使应用程序与帮助线程之间能使用同步变量进行共享操作,依据var_dep2初值和激活帮助线程函数所需的inter_push_f lag变量,在push, c文件的开始处加入inter_puSh_flag变量定义和全局共享的同步变量定义;第(4)步在该’slice’+String(SS)空函数中增加帮助线程代码,具体可分步为4. I)增加全局共享的同步变量声明定义;4. 2)针对 slice [ss]的 copyed 中记录的热函数代码 ‘while (condition){whilebody;} ’,在该空函数 ‘ 和 ’ 之间加入执行代码‘synchronization; while (condition){for(j=0 ; j〈B && condition ;j++){for(i=0;i〈K && condition;i++){push_whilebodyI;}for(i=0;i〈P&& condition;i++){push_whilebody2;}}synchronization;},;其中push_whilebodyl是在whilebody基础上,通过对whilebody代码经由删除“写操作”的择取生成的;push_whilebody2也是在whilebody基础上,通过对whilebody代码进行删除“写操作”后择取生成的,不过择取过程必须依据Var_cbpl向量值,来完全删除与数据预取无关的写操作语句,以使帮助线程与应用线程能够并发执行,并且不会对应用线程运行结果的正确性产生影响;‘synchronization’代码是依据var_dep2值依次生成的;第(5)步优化slice’ +string(ss)函数,主要是将其中条件判断语句或复杂语句进行优化,如将 if (condition) {Prefetch (a) ; Prefetch (b) ;} else {Prefetch (a) ;}变换为 Prefetch (a);Prefetch (b);第(6)步在SliCe[SS]所对应的应用程序“热函数”中,加入全局共享的同步变量声明定义,并设置激活帮助线程inter_push_flag变量的打开和关闭操作;第(7)步如果ss小于WAC,则ss=ss+l,转第(2)步,否则结束。有益效果①本发明采用一种基于配置文件的帮助线程构造方法,主要技术包括构造帮助线程的配置文件、构造帮助线程的控制变量和初值、构造帮助线程的生成代码,从而有效降低了编程的复杂性。与人工编程方式相比,有着不可比拟的便利性特点。②为帮助线程引入包含提前量、推送量和同步量等控制变量及经验值,使得在应用线程中无论有无足够的计算工作,都能对过早或过晚的预取问题进行有效控制。特别是在较少计算量的情况下,它可使应用线程和帮助线程进行更有效的交迭计算。③本发明可广泛用于多核计算机编译优化和多核数据库应用的性能优化。
图I为本发明的整体框架设计流程具体实施例方式根据上述技术方案,下面结合实施例对本发明进行详细说明。以SPEC CPU 2006的标准测试程序mcf为例,给出相关术语的定义如下定义I :热函数对应用程序mcf中的refresh_potential函数,利用性能分析工具VTUNE可发现MISS_C0UNT (refresh_potential (mcf)) /MISS_C0UNT (mcf) =3/5 和 CYCLE (refresh,potential (mcf ))/CYCLE (mcf)=29%,两者均大于 25% 的阈值,则 refresh_potential 是一个热函数;同理可发现mcf中primal_bea_mpp也是一个热函数;定义2:热数据区我们把该热函数refresh_potential所访问的数据区域称为一个热数据区;定义3 :配置文件针对mcf 中 refresh_potential 和 primal_bea_mpp 热函数及其热数据区,分别依次构造其与帮助线程关联的代码区、帮助线程的控制变量组和帮助线程的“数据推送与同步变量”组等特征序列,合并形成一个如下的总字符串‘〈begin>〈换行控制符>〈hot_spot_area>〈换行控制符>hotspotarea_begin=84〈换行控制符>hotspotarea_end=l 12< 换行控制符 >source_f ile=〃mcfutil. c〃〈换行控制符 >function_name=〃refresh_potential〃〈换行控制符 >ahead_size=50〈换行控制符 >push_size=50〈换行控制符>sync_size=64<换行控制符>hotspot_line=89<换行控制符>push_variable=〃node->basic_arc->cost〃〈换行控制符 >hotspot_line=92〈换行控制符 >push_variable=〃node->basic_arc_>cost〃〈换行控制符 >sync_variable=〃tmp〃〈换行控制符 >sync—variable=〃root〃〈换行控制符 >sync—variable=〃node〃〈换行控制符 >〈/hot—spot—areaX 换行控制符 Xhot—spot—areaX 换行控制符 >hotspotarea—begin=173〈换行控制符 >hotspotarea—end=188〈换行控制符 >source—file=〃pbeampp. c〃〈换行控制符 >function—name=〃primal—bea—mpp〃〈换行控制符 >ahead—size=5〈换行控制符 >push—size=290<换行控制符>sync_size=l<换行控制符>hotspot_line=178<换行控制符>push—variable=〃arc->tail_>potential〃〈换行控制符 >hotspot—line=178〈换行控制符>push—variable=〃arc->head_>potential〈换行控制符 >〃sync—variable=〃nr—group〃〈换行控制符 >sync—variable=〃stop—arcs〃〈换行控制符 >sync—variable=〃arc〃〈换行控制符></hot_spot_area><换行控制符X/end〉’;我们把该总字符串所标定的构造特征序列存为一个配置文件。下面以包括两个热函数refresh—potential和primal—bea—mpp的应用程序mcf为例,给出具体实施步骤步骤一、构造帮助线程的配置文件第(I)步设置SUM序列为空;依据定义1,确定应用程序mcf中的热函数集合HS= {refresh—potential,primal—bea—mpp},并选择 refresh—potential 作为当前需处理的热函数;第(2)步依据定义2确定其热数据区,提取和构造该热数据区的序列A值如下‘〈hot—spot—areaX换行控制符>hotspotarea—begin=84〈换行控制符>hotspotarea_end=112< 换行控制符 >source—f ile=〃mcfutil. c〃〈换行控制符 >function—name=〃refresh—potential” ;第(3)步设置该热数据区的序列B值如下‘ahead—size=50〈换行控制符〉push—size=50〈换行控制符〉sync—size=64’ ;第(4)步因该热数据区中不存在子区,所以依据Vtune工具的数据缺失标注信息,提取和构造序列C值如下‘hotspot—Iine=89〈换行控制符>push—variable=〃node_>basic—arc_>cost〃〈换行控制符 >hotspot—line=92〈换行控制符 >push—variable=〃node_>basic—arc_>cost〃〈换行控制符 >sync—variable=〃tmp〃〈换行控制符>sync—variable=〃root〃〈换行控制符 >sync—variable=〃node〃〈换行控制符 >〈/hot—spot—area>,;第(5)步合并SUM、序列A、序列B和序列C到总序列SUM中,此时SUM值如下‘〈hot—spot—areaX 换行控制符 >hotspotarea—begin=84〈换行控制符 >hotspotarea—end=112< 换行控制符 >source—file=〃mcfutil. c〃〈换行控制符 >function_name=〃refresh—potential〃〈换行控制符 >ahead—size=50〈换行控制符 >push—size=50〈换行控制符>sync_size=64<换行控制符>hotspot_line=89<换行控制符>push_variable=〃node_>basic—arc_>cost〃〈换行控制符 >hotspot—line=92〈换行控制符 >push—variable=〃node_>basic—arc_>cost〃〈换行控制符 >sync—variable=〃tmp〃〈换行控制符>sync—variable=〃root〃〈换行控制符 >sync—variable=〃node〃〈换行控制符 >〈/hot—spot—area>’ ;第(6)步因HS中还存在着primal—bea—mpp热函数未处理,须继续执行第(2)步到第(5)步一遍;此后,依据定义3生成完整的配置文件如下(并在第一行插入〈begin〉和最后一行插入〈/end〉): ‘〈beginX换行控制符Xhot—spot—areaX换行控制符 >hotspotarea—begin=84〈换行控制符 >hotspotarea—end=112〈换行控制符 >source—file=〃mcfutil. c〃〈换行控制符 >function—name=〃refresh—potential〃〈换行控制符>ahead_size=50<换行控制符>push—size=50〈换行控制符>sync—size=64〈换行控制符>hotspot_line=89< 换行控制符 >push—variable=〃node_>basic—arc_>cost〃〈换行控制符 >hotspot—line=92〈换行控制符 >push—variable=〃node_>basic—arc_>cost〃〈换行控制符 >sync—variable=〃tmp〃〈换行控制符 >sync—variable=〃root〃〈换行控制符 >sync—variable=〃node〃〈换行控制符 >〈/hot—spot—areaX 换行控制符 Xhot—spot—areaX 换行控制符 >hotspotarea—begin=173〈换行控制符 >hotspotarea—end=188〈换行控制符>source_file=//pbeampp. c"〈换行控制符 >function—name^primal—bea—mpp"〈换行控制符>ahead—size=5〈换行控制符>push—size=290〈换行控制符>sync—size=l〈换行控制符>hotspot_line=178< 换行控制符 >push—variable=〃arc->tail_>potential〃〈换行控制符 >hotspot—line=178〈换行控制符 >push—variable=〃arc->head_>potential〈换行控制符 >//sync_variable=//nr_group//< 换行控制符 >sync_variable=//stop_arcs//< 换行控制符>sync—variable=〃arc〃〈换行控制符 >〈/hot—spot—areaX 换行控制符 >〈/end>’ ;步骤二、构造帮助线程的控制变量和初值第(I)步因上述配置文件非空,将配置文件中第一个热数据区即potential 的〈hot—spot—area〉· · ·〈/hot—spot—area〉序列作为当前工作区(WA),并置 WAC计数器为I ;第(2)步建立如下控制变量结构,并实例slice [WAC]为slice ‘typedefstructpushVarlnfoNode {int line;string varName;int type;} pushVarlnfo;typedefstructsliceNode{int sliceStart;int sliceEnd;string sliceFunc;stringsliceFile;vector<pushVarInfo> var_push;vector〈string〉var_sync;int K,P,B;vector <string>var_depl;vector<string>var_dep2;SgStatement氺copyed;}slice;’第(3)步解析帮助线程的控制变量和初值如下sliceStart=hotspotarea—begin=84, siiceEnd=hotspotarea_end=l12, siiceFunc=function_name=〃refresh_potential",sliceFile=source_file=〃mcfutil.c〃,var_push=push_variabIe=< push_variable= 〃node->basic_arc_>cost〃,push_variable=〃node->basic_arc_>cost〃>,var_sync=sync_variable=〈sync_variable=〃tmp〃,sync_variable = 〃root〃,sync_variable=〃node〃>,K=ahead—size=50,P=push_size=50,B=sync_size=64 ;第(4)步据sliceStart, sliceEnd, sliceFunc,sliceFile 的值,定位其在 mst 中的代码区位置,并记录到copyed变量中;第(5)步依据var—push和copyed的变量初值,在copyed变量值中搜索推送变量的所有依赖变量,并记录到var—depl中,经验证和修正得到〈push—variable=〃node->basic_arc_>cost〃, push_variable=〃node->basic_arc_>cost〃> ;第(6)步依据var—sync和copyed的变量初值,在copyed变量值中搜索同步变量的所有依赖变量,并记录到var—dep2中,经验证和修正得到〈sync—variable=〃tmp〃,sync—variable=〃root〃,sync_variable=〃node〃>;
12
第(7)步因还存在primal_bea_mpp热数据区,置WAC计数器加I,转第(2)步再执行一遍后结束;步骤三、构造帮助线程的生成代码第(I)步在main函数中增加如下代码I. I)加入 #include"push. h",其中 push, h 主要包括
iVoid init pushlhreadO {ptliread_create( &push_thread_iciO, pushj;hread_func, O); {void destiOy_pushthread() {pthread_cancel(push_thread_id);}...
#define PUSH DATA (ADDR) asm volatile ("prefetchtl (%())":: "r"( ADDR))' Λ ;
1.2)在intmain(int argc,char *argv[])开始部分加入'initpushthreadO;
if (argc < 2) { destroy_pushthread( );ret.urn (-1);},;
1.3)构iiiipush.c的push—thread—func为
void *push_t:hread_func(\Oid *arg)
/ — —
for (;;){_··
while(!(imer—push—flag != '\0')) {}switch( inter—push—flag)(case I:
.inter—push—flag = '\0';
} —1.4)置 ss=l;第(2)步依据ss变量值修改push, c的push_thread_func代码,具体可分步为2. I)在 push, c 的 push_thread_func 中,将 ‘case,+string (ss) + ‘ ,+〈换行控制符 >+ ‘{}’替换为‘case’+string (ss)+ ‘’+〈换行控制符 >+ ‘{’+ ‘slice’+string(ss)+ ‘();break;} ’ ;2. 2)为帮助线程的 push_thread_func 创建一个名为’ slice’ +string(ss)的空函数;第(3)步在push, c文件中加入全局共享的同步变量定义和激活帮助线程函数的 inter_push_flag 变量定义;如volatile int inter_push_fIag=O; arc_t*volatileg_s2_arc;arc_t*volatiIe g_s2_stop_arcs;volatile long g_s2_nr_group;node_t*volatileg_sl_tmp; ···;第(4)步在该’slice’+String(SS)空函数中增加帮助线程代码,具体可分步为4. I)增加全局共享的同步变量声明定义;4. 2)依据copyed,在slicel空函数中增加如下代码void slicel ()
(extern nodet *voiatile g_s I _tmp;extern node」* volatile g_sl_root;extern node—t^volatile g_s l_node;node_t *node;node t * root; node—t *tmp;int tmp i;node =
g_sl_node;root = g_sl_root;tmp = gsltmp;
while(node != root) [for (tmp i = 0; tmp i < 50 && node != root; tmp i++)上while(node !— (0)) I
tmp = node;node = (node -> child): }node = tmp;
{while((node -> pred) != (0)) {tmp = (node -> sibling); if (tmp != (0)) {node =tmp;break; }
else {node = (node -> pred);.)}}for (tmp i = 0: tmp i < 50 && node != root; tmp i++) {while(node !- (0)) {
if ((node -> orientation) == I)(asm volatile ("prefetchtl (%0)"::"r'!(&(node->basic_arc->cost)));
}eise {
asm volatile ("prefetchtl ((H0)”::”r”(&(.nod.e->basic—arc->cost)));
}tmp = node;node = (node -> child);}node = tmp; {
\vhile((node -> pred) != (0))(tmp = (node -> sibling);if (tmp != (0)) {node = tmp;break;
} else {node = (node -> pred);}})}}node = NULL; root = NULL;tnip = NULL;}其中黑体部分是同步操作,画线
部分是控制机制实现代码。这里设置K、P、B参数分别设为50、50、0 ;第(5)步将node->potential=(((*(node->basic_arc))·cost)+ ((* (node_>pred) )· potential))复杂语句优化为 node_>basic arc->cost 的预取语句;第(6)步在mcf的热函数refresh_potential中加入全局共享的同步变量声明定义,并设置帮助线程函数激活变量inter_push_flag的打开(inter_push_fIag=I)和关闭(inter_push_f Iag=O)操作;第(7)步因存在其他的热数据区如primal_bea_mpp, ss变为2,转第(2)步再执
行一遍,然后结束。在Q6600计算机上,该mcf的综合测试结果如下
权利要求
1.一种基于配置文件的帮助线程构造方法,其特征在于其基本思想是在基于共享缓存的多核架构基础上,针对多核应用中非规则数据缺失的问题,通过引入“构造帮助线程的配置文件、构造帮助线程的控制变量和初值、构造帮助线程的生成代码”等步骤,来自动生成帮助线程,以降低程序员或用户的编程难度,提高应用程序的执行性能,并为多核编译辅助工具提供有效的支撑技术。具体实现步骤如下 步骤一、构造帮助线程的配置文件 利用应用程序中的多个热数据区,人工或自动从中提取帮助线程的构造特征序列,经合并构造后,生成一个配置文件。
步骤二、构造帮助线程的控制变量和初值 在步骤一构造的配置文件基础上,步骤二自动转换配置文件序列中的数据为构造帮助线程所需的控制变量和初值,并对推送变量和同步变量的初值进行完整性验证和修正。
步骤三、构造帮助线程的生成代码 在步骤二构造的帮助线程控制变量和初值基础上,步骤三构造帮助线程的生成代码。
2.根据权利要求I所述的一种基于配置文件的帮助线程构造方法,其特征在于步骤一中构造帮助线程的配置文件步骤为 第(I)步设置SUM总序列变量为空;依据定义1,确定应用程序P中所有热函数的集合HS ;从肥中选择任一热函数f (P)作为当前需处理的热函数; 第(2)步依据定义2确定该热数据区,提取和构造其中与帮助线程相关的代码区标定序列A = ‘〈hot_spot_area>〈换行控制符>hotspotarea_begin=热数据区的起始行号〈换行控制符>hotspotarea_end=热数据区的结束行号〈换行控制符>source_file=热数据区所在的源文件名〈换行控制符〉function_name=热数据区所在的函数名’; 第(3)步设置该热数据区的帮助线程控制变量组序列B = ‘ahead_siZe=设定的预取提前量大小〈换行控制符>push_size=设定的预取量大小〈换行控制符>sync_size=设定的同步量大小’;这里ahead_size、push_size和sync_size均为一个非负整数; 第(4)步如果该热数据区中不存在任何子区,则依据性能分析工具的数据缺失标注信息,从该热数据区中提取和构造帮助线程的“推送变量和同步变量”组序列C =‘hotspot_line =第I个推送变量所在的行号〈换行控制符> push_variable=第I个推送变量名〈换行控制符>*“hotspot_line=第η个推送变量所在的行号〈换行控制符>push_variable=第η个推送变量名〈换行控制符〉sync_variable=应用程序和帮助线程间第I个同步变量名〈换行控制符>*“sync_variable=应用程序和帮助线程间第m个同步变量名〈换行控制符>〈/h0t_sp0t_area>’ ;否则,如果推送变量在该热数据区中的某个函数内部,则需产生一个<child_hot_spot>. . . </child_hot_spot>子区,从该热数据区中提取和构造帮助线程的“推送变量和同步变量”组序列C = ‘hotspotjine=推送变量所在的行号〈换行控制符>〈child_hot_spot>〈换行控制符>child_source_file=子区中该函数所在的文件〈换行控制符>child_function_name=子区中该函数名〈换行控制符>child_hotspot_line=子区第I个推送变量所在的行号〈换行控制符>child_push_variable=子区中第I个推送变量名〈换行控制符>“child_hotspot_line=子区第η个推送变量所在的行号〈换行控制符>child_push_variable=子区中第η个推送变量名〈换行控制符X/child_hot_spotX换行控制符>sync_variable=应用程序和帮助线程间第I个同步变量名〈换行控制符>··· sync_variable=应用程序和帮助线程间第m个同步变量名〈换行控制符>〈/hot_spot_area>,; 第(5)步SUM = SUM+<换行控制符>+序列A+〈换行控制符>+序列B+〈换行控制符>+序列C ; 第(6)步若HS中存在任何其他未处理的热函数,则转第(2)步;否则,依据定义3,由SUM序列生成帮助线程的配置文件,并在第一行插入〈begin〉,最后一行插入〈/end〉,结束。
3.根据权利要求I所述的一种基于配置文件的帮助线程构造方法,其特征在于步骤二构造帮助线程的控制变量和初值步骤为 第(I)步如果配置文件非空,将配置文件中的第一个<hot_spot_area>. . . </hot_sp0t_area>序列作为当前的工作区(WA),并置WAC计数器为I;否则退出结束; 第(2)步构造当前工作区的控制变量结构为‘typedefstructpushVarlnfoNode{int line;string varName;int type;}pushVarlnfo;typedefstructsliceNode{int sliceStart;int sliceEnd;string siiceFunc;string sIiceFile;vector〈pushVarInfo>var_push;vector<string>var_sync;int K, P,B;vector<string>var_depl;vector<string>var_dep2;SgStatement*copyed;}slice’,并将 slice[WAC]实例化为 slice; 第(3)步从当前工作区依序解析该<hot_spot_area>. . . </hot_spot_area>序列,并使,sliceStart=hotspotarea_begin, sliceEnd = hotspotarea_end, siiceFunc =function_name sliceFile=source_file,K = ahead_size,P = push_size,B = sync_size ;var_push=push_variab I e 表,var_sync=sync_variable 表; 第(4)步依据 slice [WAC]中 sliceStart, sliceEnd, sliceFunc 和 sliceFile 当前的取值,标定其在应用程序P中的位置,并记录所标定区域的代码到copyed变量中; 第(5)步依据var_push和copyed的变量初值,搜索推送变量的所有依赖变量,并记录到推送变量依赖表var_depl中,完成对var_push的验证和修正;具体可分步为 5.I)首先将var_push初值放入推送变量依赖表var_depl中; 5.2)对推送变量依赖表var_cbpl中的每一项,在copyed变量值中查找其直接依赖的推送变量,若存在新的依赖变量,将其放入var_depl中; 5.3)重复5. 2)直到没有新的推送变量加入为止; 第(6)步依据var_sync和copyed变量初值,在copyed变量值中搜索所有直接依赖的同步变量,并记录到同步变量依赖表var_dep2中,完成对var_sync的验证和修正。具体可分步为 6.I)首先将var_sync放入同步变量依赖表var_dep2中; 6.2)对同步依赖表var_cbp2中的每一项,在copyed变量值中查找其直接依赖的同步变量,若存在新的同步变量,将其放入该var_cbp2中; 6.3)重复6. 2)直到没有新的同步变量加入为止; 第(7 )步如果配置文件序列中还存在其他的‘ <hot_spot_area>. . . </hot_spot_area〉’子串,则选择其中之一作为当前工作区,并置WAC计数器加1,转第(2)步,否则结束。
4.根据权利要求I所述的一种基于配置文件的帮助线程构造方法,其特征在于步骤三构造帮助线程的生成代码步骤为 第(I)步分别在应用程序P的main函数、帮助线程的push, h和push, c文件中增加构造代码,具体可分步为 I. I)在main函数所在文件中加入帮助线程头文件名push, h,该push, h头文件中的代石马包括iVoid init_pushthread O {pthread_create (&push_thread_id, O, push_thread_func, 0) ;}〈换行控制符 >void destroy_pushthread () {pthread_cancel (push_thread_id) ;}〈换行控制符 〈换行控制符 >#definePUSHDATA (ADDR) asm volatile (VefetchtI (%0) 〃: : 〃r〃 (ADDR)) < 换行控制符 >’等; I. 2)在main函数的开始部分,增加帮助线程的创建函数init_pushthreadO ;在1]1&;[11函数返回前,调用该帮助线程终止函数destix)y_pushthread0 ;由于main函数可能有多个返回点,在其中每一个返回点前,都需加上该帮助线程的终止函数; I. 3)构造 push.c 白勺 push_thread_func 为 <void*push_thread_func(void*arg)< 换行控制符 >{for(;;)〈换行控制符 >{···〈换行控制符 >while (! (inter_push_flag! =' \0’)){<换行控制符>} <换行控制符>switch (inter_push_flag) {<换行控制符>casel: <换行控制符> H〈换行控制符>case2: <换行控制符> {}… < 换行控制符>} <换行控制符>inter_push_f lag=’ \0’ ; <换行控制符>} <换行控制符>} <换行控制符>’; .1.4)设置ss变量为I; 第(2)步依据ss变量值修改push, c的push_thread_func代码,具体可分步为.2.I)在 push, c 的 push_thread_func 中,将 ‘case’ +string (ss) + ‘ ’ +〈换行控制符 >+ ‘{}’替换为‘case’+string (ss)+ ‘’+〈换行控制符 >+ ‘{’+ ‘slice’+string(ss)+ ‘ O ;break;}’ ; .2.2)为帮助线程的push_thread_func创建一个名为’ slice’ +string(ss)的空函数,即当 ss=l 时创建一个 ‘void slicel O {} ’ 或当 ss=2 时创建一个 ‘void slice2 O {} ’ 等;第(3)步为使应用程序与帮助线程之间能使用同步变量进行共享操作,依据var_dep2初值和激活帮助线程函数所需的inter_push_flag变量,在push, c文件的开始处加入inter_push_flag变量定义和全局共享的同步变量定义; 第(4)步在该’ slice’ +string (ss)空函数中增加帮助线程代码,具体可分步为 .4.I)增加全局共享的同步变量声明定义; .4. 2)针对slice[ss]的copyed中记录的热函数代码‘while (condition){whilebody;} ’,在该空函数 ‘ 和 ’ 之间加入执行代码‘synchronization; while (condition){for(j=0 ;j〈B && condition ; j ++){for(i=0;i<K && condition;i++){push_whilebodyI;}for(i=0;i〈P&& condition;i++){push_whilebody2;}}synchronization;},;其中push_whilebodyl是在whilebody基础上,通过对whilebody代码经由删除“写操作”的择取生成的;push_whilebody2也是在whilebody基础上,通过对whilebody代码进行删除“写操作”后择取生成的,不过择取过程必须依据Var_cbpl向量值,来完全删除与数据预取无关的写操作语句,以使帮助线程与应用线程能够并发执行,并且不会对应用线程运行结果的正确性产生影响;‘synchronization’代码是依据var_dep2值依次生成的; 第(5)步优化slice’ +string(ss)函数,主要是将其中条件判断语句或复杂语句进行优化,如将 if (condition) {Prefetch (a) ; Prefetch (b) ;} else {Prefetch (a) ;}变换为Prefetch(a);Prefetch (b); 第(6)步在slice[ss]所对应的应用程序“热函数”中,加入全局共享的同步变量声明定义,并设置激活帮助线程inter_pUsh_flag变量的打开和关闭操 作; 第(7)步如果ss小于WAC,则ss=ss+l,转第(2)步,否则结束。
全文摘要
本发明涉及一种基于配置文件的帮助线程构造方法,属于多核多线程技术领域。在基于共享缓存的多核架构基础上,针对多核应用中非规则数据缺失的问题,通过引入“构造帮助线程的配置文件、构造帮助线程的控制变量和初值、构造帮助线程的生成代码”等步骤,来自动生成帮助线程,以降低程序员或用户的编程难度,提高应用程序的执行性能,并为多核编译辅助工具提供有效的支撑技术。
文档编号G06F9/44GK102929616SQ201210396209
公开日2013年2月13日 申请日期2012年10月18日 优先权日2012年10月18日
发明者郑宁汉, 古志民, 付引霞, 杨四才 申请人:北京理工大学