CN1287281C - 单线程代码到推测预执行启用代码的变换 - Google Patents

单线程代码到推测预执行启用代码的变换 Download PDF

Info

Publication number
CN1287281C
CN1287281C CNB2003101240682A CN200310124068A CN1287281C CN 1287281 C CN1287281 C CN 1287281C CN B2003101240682 A CNB2003101240682 A CN B2003101240682A CN 200310124068 A CN200310124068 A CN 200310124068A CN 1287281 C CN1287281 C CN 1287281C
Authority
CN
China
Prior art keywords
thread
processor
speculative threads
speculative
node
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Expired - Fee Related
Application number
CNB2003101240682A
Other languages
English (en)
Other versions
CN1514365A (zh
Inventor
H·王
P·H·王
R·D·维尔顿
S·M·埃廷格尔
H·塞托
M·B·吉尔卡
S·S·-W·廖
M·R·哈希哈特
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Intel Corp
Original Assignee
Intel Corp
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Intel Corp filed Critical Intel Corp
Publication of CN1514365A publication Critical patent/CN1514365A/zh
Application granted granted Critical
Publication of CN1287281C publication Critical patent/CN1287281C/zh
Anticipated expiration legal-status Critical
Expired - Fee Related legal-status Critical Current

Links

Images

Classifications

    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/54Interprogram communication
    • G06F9/544Buffers; Shared memory; Pipes
    • GPHYSICS
    • G06COMPUTING; CALCULATING OR COUNTING
    • G06FELECTRIC DIGITAL DATA PROCESSING
    • G06F9/00Arrangements for program control, e.g. control units
    • G06F9/06Arrangements for program control, e.g. control units using stored programs, i.e. using an internal store of processing equipment to receive or retain programs
    • G06F9/46Multiprogramming arrangements
    • G06F9/52Program synchronisation; Mutual exclusion, e.g. by means of semaphores

Landscapes

  • Engineering & Computer Science (AREA)
  • Software Systems (AREA)
  • Theoretical Computer Science (AREA)
  • Physics & Mathematics (AREA)
  • General Engineering & Computer Science (AREA)
  • General Physics & Mathematics (AREA)
  • Devices For Executing Special Programs (AREA)

Abstract

描述了一种系统(10)、处理器(12)和优化模块(32),诸如编译器或者传递后优化层。在一个实施例中,所述优化模块(32)在一主程序中标识一组可被动态激活作为一个或多个推测预执行线程的指令。所述优化模块(32)可以生成提供所述推测线程大量产生以便生成实际上的多线程编码的指令。系统(10)和处理器(12)提供多个线程上下文,以便执行同时执行非推测线程(24)和推测线程(26)。系统(10)和处理器(12)提供共享的存储装置区域来存储一组一个或多个可以被推测和非推测线程访问的全局变量。对于至少一个处理器的实施例,所述共享存储装置区域是一个共享的内部寄存器(14)。对于至少一个其它的实施例,所述共享存储装置区域是一个高速缓冲存储器或者外部存储器(16)。通过监控所述全局变量组来规范非推测线程(24)的进度,允许推测线程确定其相对于非推测线程的进度。

Description

单线程代码到推测预执行启用代码的变换
技术领域
本发明涉及计算系统软件,尤其是线程管理。
背景技术
对现代计算系统的有效操作通常需要多指令“线程”支持,每个线程是在一程序中提供清楚的控制流的指令流。为提高整体系统速度和响应,多线程可通过具有多处理器的计算系统同时实现,其中每个处理器支持一单线程。在更先进的计算系统中,可利用具有能同时执行多线程的多线程处理器结构的处理器来支持多线程。可替换的方案是,在通常被称为时间片多线程的技术中,在一固定时间段之后可在线程之间复用一单个处理器。在另一被称为事件切换多线程的方法中,依据诸如一长等候高速缓存未中的触发器事件的发生,一单个处理器在线程之间切换。
多线程的概念已发展到被称作同步多线程(“SMT”)的技术。同步多线程是将硬件多线程与超标量处理器技术结合起来的处理器设计,从而允许多线程每周期发布指令。SMT典型地允许所有线程上下文(thread context)同时竞争并共享处理器资源。在一些实现中,一单个物理处理器可作为操作系统和用户程序的多逻辑处理器,其中每个逻辑处理器保持一整组结构状态,但物理处理器的几乎所有其它资源,例如高速缓存、执行单元、分支预测器、控制逻辑和总线,均被共享。线程同时执行并且比时间片多线程或事件切换多线程更好地利用共享资源。此多线程支持处理器的有效应用需要用于自动优化程序行为的过程和最好的优化候选者的代码标识部分。通过将一原始单线程应用变换为一实际多线程代码,采用一组线程机制标识的代码优化区域增强了程序性能。在一现有技术中,创建一“推测预执行”(SP)线程,从而与作为一主线程的原始代码并行运行。此SP线程将在主线程之前运行并遇到未来高速缓存未中,因此执行用于主线程的有效预取。然而,由于线程同步发布,此技术不总是有效。
发明内容
本发明第一方面提供一代码转换方法,包括:
在一主程序中标识一组可被动态激活作为推测预执行线程的指令,并
通过一组全局变量指示非推测线程进度,允许此推测预执行线程规范相对于非推测线程的相对进度。
本发明第二方面提供一种包括具有存储在其上的指令的存储介质的产品,所述指令被执行时将导致:
在一主程序中标识一组可被动态激活作为推测预执行线程的指令,并
通过一组全局变量指示非推测线程进度,允许此推测预执行线程规范相对于非推测线程的相关进度。
本发明第三方面提供一种计算系统,包括:
一优化模块,用来在一主程序中标识一组可被动态激活作为推测预执行线程的指令;以及
一同步模块,包括存储全局变量的存储器,此同步模块通过一组全局变量指示非推测线程的进度,允许此推测预执行线程规范相对于非推测线程的相关进度。
附图说明
通过以下详细描述和本发明实施例的附图,本发明将更被充分理解,然而以下详细描述和本发明实施例的附图不是将本发明局限于特定实施例,而仅用于解释和理解。
图1示意性地表示支持多线程处理的一计算系统;
图2示意性地表示在推测预执行期间的一存储器访问模式;而且
图3示意性地表示用作推测预执行的程序逻辑,该推测预执行包括对用于线程同步的全局变量的存储器访问。
具体实施方式
图1表示一计算系统10,用于执行作为计算机程序产品的软件外部提供并存储在数据储存单元的指令,计算系统10包括一或多个处理器12和存储系统13(此存储系统可为外部高速缓冲存储器,外部RAM,和/或部分在处理器内部的存储器)。处理器12表示一或多个用于执行软件线程并能支持多线程的处理单元。处理器12可包括但不局限于:传统多路复用处理器、共享一些普通存储器的多处理器、在一单个芯片上具有多指令设置处理单元的芯片多处理器“CMP”、对称多处理器“SMP”或同步多线程处理器“SMT处理器”。
本发明的计算机系统10可包括一或多个I/O(输入/输出)设备15,包括诸如监控器的一显示设备。此I/O设备也可包括一输入设备,例如一键盘和诸如鼠标、跟踪球或轨迹板的一光标控制。而且,I/O设备也可包括一网络连接器以便计算机系统10是局域网(LAN)或广域网(WAN)的一部分。
例如,一系统10包括但不局限于或限制于:一计算机(例如,一台式机、一便携机、一服务器、刀片式服务器、一工作站、一个人数字助理等)或任何与之关联的外部设备;通信装备(例如手提电话、传呼机等);一电视机机顶盒等。“连接”或“链接”被广泛定义为逻辑或物理通信路径,例如电线、光纤、电缆、总线跟踪或者甚至是利用红外、射频(RF)或任何其他无线信号机制的无线通道。而且,术语“信息”被定义为一或多个比特数据、地址和/或控制。“代码”包括运行时执行一定功能的软件或固件。例如,代码包括一应用、操作系统、一小程序、引导代码或任何其他指令序列或微代码(即,在特权级别且在OS下操作的代码)。
可选地,此处讨论的执行所述方法和系统的逻辑可在附加计算机和/或机器可读介质上实现,诸如作为大规模集成电路(LSI)的分离硬件组件、专用集成电路(ASIC)、微代码或诸如电可擦除可编程只读存储器(EEPROM)的固件;或通过电、光、声以及其他形式的传播信号的空间距离计算机延迟信息(例如,无线电波或红外光学信号)。
在一实施例中,依据本发明,由数据储存单元18可读的一计算机程序产品包括一机器或计算机可读介质,该计算机可读介质具有存储其上的指令,该指令可用于编程(即定义其操作)一计算机(或其他电子设备)来执行一处理的程序。数据储存单元18的计算机可读介质可包括但不局限于:软盘、光盘、高密度磁盘、只读存储器(CD-ROM)和磁-光盘、只读存储器(ROM)、随机存取存储器(RAM)、可擦除可编程只读存储器(EEPROM)、电可擦除可编程只读存储器(EEPROM)、磁或光卡、闪存等,包括升级或重编程或产生或激活或保留激活微代码增强的任何方法。
因此,计算机可读介质包括任何种适合存储电子指令的介质/机器可读介质。而且,本发明也可作为一计算机程序产品下载。因此,可将此程序从一远程计算机(例如,一服务器)传输到一请求计算机(例如,一客户机)。可利用载波或其他传播介质中内嵌的数据信号经由通信链接(例如,一调制解调器、网络连接等)来传输所述程序。
在一实施例中,本发明的方法被嵌入到机器可执行指令,此指令直接控制计算系统10的操作,而且更具体地是控制处理器12、寄存器14、高速缓冲存储器(参见16)和通用存储器(参见16和18)的操作。该指令可用于使得采用该指令编程的通用目的或特定目的处理器执行本发明的步骤。可选地,可通过包含用于执行此步骤的硬线逻辑的特定硬件组件(包括微代码)或者通过编程计算机组件和客户硬件组件的任意组合执行本发明的步骤。
本领域普通技术人员可以理解用来描述通信、协议、应用、实现、机制等所使用的各术语和技术。此技术是对依据算法或数学表达式的技术实现的描述。也就是,例如,当此技术作为计算机上的执行代码来实现时,此技术的表达式作为伪代码可更适当和简明地传送和通信,此伪代码通常通过公式、算法或数学表达式来定义程序流逻辑。
因此,本领域普通技术人员将认识表示A+B=C的块,它是作为加法功能,其在硬件和/或软件中是通过获得两个输入(A和B)并产生一和输出(C)来实现的。因此,描述中公式、算法或数学表达式的作用是至少在硬件和/或软件上具有一物理实施例(例如,本发明的技术可作为一实施例在其中实践或实现的一计算机系统)。
图2中20表示在一计算系统中的线程运行,此计算系统支持能将单线程应用变换为推测预执行(SP)增强多线程代码的一编译器或传递后优化层,该增强多线程代码使用操作系统线程所明显支持的线程(例如WIN32线程API)、对OS透明的用户层线程或经由微代码等的硬件线程支持。应该注意的是,支持SP代码转换可用于实际上将任何可包括错误预测的间接分支的长等候操作作为目标。例如,在一实施例中,转换到SP代码典型地需要标识一小组“非法加载”,也就是在发生最多高速缓存未中的程序中的加载指令。标识此组导致用于这些非法加载的地址计算的指令,并从可被动态激活的主线程24将用于这些非法加载的指令创建为一分离SP线程26。实际上,由于在主线程运行期间SP线程26不用时进入休眠,可在初始化时创建SP线程26,在运行期间产生最小处理器开销。然而,SP线程26,如果在初始化之后被一合适的同步或异步触发器唤醒并在主线程24之前执行到早计算地址和执行存储器访问,仍可导致用于非法加载的有效存储器预取。通过在主线程24(不将产生未中)访问之前确保在SP线程26发生高速缓存未中,SP线程26的早期存储器预取可大大提高主线程性能。
如图3所示,SP线程创建和运行的处理30从一优化模块32开始,此模块用于在一主程序中标识一组可作为推测预执行线程被动态派生的指令。可在程序初始化时动态标识或通过编译器脱机进行标识。在任一情况下(动态运行时间创建或脱机编译器标识),在程序初始化期间此SP线程被动态创建为一运行时间实体。由于线程创建典型地为大计算量过程,此一次SP线程创建是有用的。只要需要一线程那么就创建一新SP线程,将否定通过利用推测预执行所获得的加速。只在开始所有应用时创建SP线程来分期偿还线程创建的整体花销。
一延迟软件模块34用于在线程创建和激活之间对推测预执行线程执行一个等待/休眠操作。SP线程与其相应非推测线程的相应部分运行频率相同。在大多数应用中,在SP线程创建和SP线程激活之间存在一些离散时间,在连续SP线程激活之间也存在一些离散时间。在这些时间期间,SP线程执行一等待/休眠操作从而允许SP线程转入系统希望在逻辑处理器上运行的其他处理。
一同步模块36(包括存储全局变量的存储器访问功能性)通过一组全局变量跟踪非推测线程的进度,允许推测预执行(SP)线程指示相对于非推测线程的进度。所给SP和非SP线程可读并写入一组共享变量,此组共享变量有助于约束所有对此组带有一快速、同步对象的全局变量的访问。此同步对象可直接来自OS线程API,例如在Win32线程API或p线程的等价API中通过setEvent( )和waitForSingleObject( )来操作的事件对象。可选地,此同步对象可经由合适的硬件线程等待监控器实现,此监控器允许一线程将一与存储器地址对准的缓存线定义为监控器,而且对此监控器对象的加载访问可挂起所述线程运行——使之语义地与WaitForSingleObject( )等价;而且访问监控器的存储器可唤醒挂起线程——因此与setEvent( )等价。然而,值得注意的是,虽然监控器写和m等待比一OS水平线程API有效得多,所述实施例可采用任何支持等待和唤醒的软件、硬件或软件硬件混合机制实现。
除了采用全局变量并提供一等待状态,用于SP优化操作的代码变换还可包括限制SP线程和非推测主线程之间的通信频率。定义“stride”为一变量,等于一SP线程相对于一非推测主线程之前运行的循环迭代数,这些线程可被设置为只在stride操作之后访问此组共享全局变量。这最小化了通信,线程提前运行和推后完成也局限于stride单位的大小。在某些实施例中,SP线程经常在非推测线程之前运行,而且任何同步通信均为不必要的开销,不使用依赖stride的通信限制。如所期望地,stride选择经常影响应用性能。如果stride设置太低(提前运行距离太短,所需线程间通信更频繁,而且SP线程的非时存储器访问更频繁),则通信开销开始否定SP线程的好处。另一方面,假如设置得太高,SP线程太提前运行而且一些以前的预取数据在主线程使用之前被覆盖,则为不充分线程通信,而且可产生错误或不必要(即非时)预取。
在多数应用中,SP线程在非推测线程之后完成和/或之前运行。通过动态增加或减少推测线程运行,经由线程之间优质通信,推后完成和/或提前运行频率可最小。假如SP线程发现其在非推测线程之后,它可通过试图跳转到上一次通信位置之前来有效增加它的执行。另一方面,假如SP线程发现其在非推测线程之前运行,它可使用两个技术之一来减少执行:等待和跳回。采用等待技术,SP线程简单产生并等待非推测线程发信号。可选地,一跳回技术可用于SP线程运行需要跳回到非推测线程的最后已知位置并开始再次预取的情况。
一SP线程也可在其非推测线程之后完成。这样的话,非推测线程已经完成了SP预取的代码部分,当SP线程继续执行时此应用产生附加的不必要的高速缓存未中。在一个实施例中,SP线程在每个提前执行操作跨距的终点包括一调节机制,用来检查主线程的相关进度(经由用于行程计数的全局变量),然后确定此SP线程是否相对于主线程太早或太晚执行。提前执行策略因此可以被调节或者继续另一轮预取(假如未太早执行),或进入休眠和等待主线程的下一唤醒(假如太早或太晚执行),或者与主线程进度同步进行(通过经由全局变量的同步预取的开始指针)并继续执行预取。
为提高效率,SP线程在其核心应当只包括那些确定非推测主线程所需的长等候操作(例如一存储器加载)顺序所必须的指令。因此,可以最小化经由函数内嵌从SP线程调用的函数数量。例如,在诸如一列重复哈希表(hash tables)循环并在这些表中的每一个执行查找(需要遍历另一列表)的最小生成树(MST)的应用中,内嵌是有用的。
通过增加SP线程功能性,递归函数也可使得非法加载最小化。由于以下两个原因递归函数难以直接变换为SP线程:递归调用之上的堆栈花销高得惊人,而且如果难以(或不可能)实现则提前跳转代码,因此将递归函数变换到用于SP线程的基于循环的函数有时是有用的。
为更好地描述用于将单个线程代码转换为具有推测预执行的优化代码的方法和系统的实施例,考虑以下单线程伪代码:
    1   main()

        {

    2       n=NodeArray[0]

  3       while(n and remaining)

          {

  4            work()

  5            n->i=n->next->j+n->next->k+n->next->l

  6            n=n->next

  7            remaining--

          }

      }
在一个实施例中,当执行时,行4需要整体执行时间的49.47%,而行5:需要大约整体执行时间的49.46%。行5也具有整体L2未中的99.95%,这使得它成为采用推测预执行线程优化的理想候选者。
以下描述了适合运行前述具有提高了效率的伪代码伪代码的一个例子。由此产生一“主”线程:
  1    main()

  {

  2        CreateThread(T)

  3        WaitForEvent()

  4        n=NodeArray[0]

  5        while(n and remaining)

           {

  6        work()
        <!-- SIPO <DP n="7"> -->
        <dp n="d7"/>
  7        n->i=n->next->j+n->next->k+n->next->l

  8        n=n->next

  9        remaining--

  10       Every stride times

  11             global_n=n

  12             global_r=remaining

  13             SetEvent()

           }

  }
行7对应单个线程代码的行5,而且行13 SetEvent是一同步触发器(其中一API调用是被静态地放置在代码特定位置,与最初并不知道触发时代码位置的异步触发器相反),该同步触发器用来启动以下推测预执行(SP)线程(以下可选地公知为“侦察者”、“工作者”或“帮助者”线程):
  1 T()

    {

  2    Do Stride times

  3     n->i=n->next->j+n->next->k+n->next->l

  4    n=n->next

  5    remaining--

  6     SetEvent()

  7    while(remaining)

       {

  8    Do Stride time

  9    n->i=n->next->j+n->next->k+n->next->l

  10     n=n->next

  11     remaining--

  12     WaitForEvent()

  13     if(remaining<global_r)

  14        remaining=global_r
        <!-- SIPO <DP n="8"> -->
        <dp n="d8"/>
  15          n=global_n

          }

  }
行9负责提前执行所导致的最有效预取,而行15检测推后执行并通过提前跳转调节。
总的来说,在主线程中行7的执行时间(对应单个线程情况下的行5)为19%而在单个线程代码中为49.46%。L2高速缓存未中是可忽略不计的0.61%而在单线程代码中为99.95%。推测预执行线程的行9(对应主线程的行7)具有26.21%的执行时间和97.61%的L2未中,表示可成功承担大多数L2高速缓存未中。
为达到此性能结果,推测预执行(SP)工作者线程T( )基本上在主循环执行指针跟踪任务,而且不执行work( )操作。本质上,工作者探察或侦察主循环所采用的加载顺序并有效预取所需数据。
只存在一个在程序开始时创建的工作者线程,而且它一直存在直到不再有任何循环迭代执行。在某些实施例中,支持两个或更多物理硬件线程上下文并具有与创建一新线程相关的大花销的处理器结构可将此工作者线程映射到一第二硬件线程。实际上,未产生附加线程,而且产生线程的花销分散在程序中因而实质上是不显著的。
一旦创建SP线程,主线程等待SP线程指示它已完成预循环工作。一更完善的调谐SP线程可探察多于一个用于预循环工作的初始指针跟踪迭代。
实质上,SP工作者线程执行在先前定义的stride单位大小的所有预执行。当对在主线程之前执行的预执行线程的迭代数进行有效设置限制时,这既最小化通信又限制了线程提前执行。假如太提前执行,预执行产生的预取不仅临时取代主线程使用的重要数据还可能取代主线程未使用的更早预取数据。另一方面,假如提前运行的距离太短,那么该预取可能太晚而导致无用。
在前述一推测预执行工作者线程的伪代码例子中,工作者线程的预循环工作包括执行跨距循环,即行2-5之间所示的预取。如行10-12之间所示,在主线程中的每个跨距回路、当前指针的全局复制以及回路保持数量被更新。而且,假如由于太提前执行而安装了工作者,主线程向工作者线程发送可继续预取的信号,如行13所示。在预取多块跨距长度之后,如行8-11所示,工作者线程等待来自主线程的信号而继续。此外,这使得不会在主线程之前太早执行工作者。更重要的是,在另一跨距迭代循环之前,工作者线程检查其剩余迭代是否比全局版本多。假如剩余迭代是比全局版本多,那么工作者线程推后完成,而且必须通过将其状态变量更新为存储在全局变量中的状态变量来“提前跳转”(行13-15)。
以下相应的“单线程代码”和改进的“推测计算多线程版本”表示利用对应前述伪代码的算法所进行的单线程代码的转换:
单线程代码
  #include<stdio.h>

  #include<stdlib.h>

  typedef struct node node;

  node*  pNodes=NULL;           //所有结点数组的指针

  struct node

  {

  node* next;                   //下一结点的指针

  int  index;                   //此结点在数组中的位置

  int  in;                      //入度

  int  out;                     //出度

  int  i;

  int  j;

  int  k;

  int  l;

  int  m;

  };

  //函数说明

  void InitModes(int num_nodes);

  int main(int argc,char *argv[])

  {

        int num_nodes=500;      //结点总量
        <!-- SIPO <DP n="10"> -->
        <dp n="d10"/>
      node*n;

      register int num_work=200;

      regiscer int remaining=1;//将要执行的迭代数量

      regiscer int i=0;

      if(argc>1)

           num_nodes=atoi(argv[1]);

      if(argc>2)

           num_work=atoi(argv12]);

      if(argc>3)

           remaining=atoi(argv(3));

      remaining=num_nodes*remaining;

      InitNodes(num_nodes);

      n=&(pNodes[0]);

      while(n && remaining)

      {

             for(i=0;i<num_work;i++)

             {

             _asm(pause};

             }

             n->I=n->next->j+n->next->k+n->next->l+n->next->m;

             n=n->next;

             remaining--;

      }

      free(pNodes);

  }

  void InitNodes(int num_nodes)

  {

     int i=0;

     int r=0;

     node*pTemp==NULL;

     pNodes=malloc(num_nodes*sizeof(node));

  //给”随机”数产生器一个种子
        <!-- SIPO <DP n="11"> -->
        <dp n="d11"/>
    srand(123456);

    for(i=0;i<num_nodes;i++)

    {

            pNodes[i].index=i;

            pNodes[i].in=0;

           pNodes[i].out=0;

            pNodes[i].i          =0;

            pNodes[i].j          =1;

            pNodes[i].k          =1;

            pNodes[i].l          =1;

            pNodes[i].m          =1;

  }

  pNodes[num_nodes-1].next=&(pNodes[0]);

  pNodes[num_nodes-1].out=1;

  pNodes[0].in=1;

  for(I=0;i<num_nodes-1;i++)

  {

        r=i;

        while(r==i||pNodes[r].in==1)

        r=rand()%num_nodes;

        pNodes[i].out=1;

        pNodes[r].in=1;

        pNodes[i].next=&(pNodes[r]);

      }

  }
推测计算多线程版本
  #include<stdio.h>

  #include<stdlib.h>

  #include"..\..\IML\libiml\iml.h"

  typedef struct node node;

  typedef struct param param;

  node*pNodes=NULL;             //所有结点数组的指针
        <!-- SIPO <DP n="12"> -->
        <dp n="d12"/>
      HANDLE event;               //用于跨线程间事件信号

      node*global_n=NULL;         //共享用于T0/T1通信的变量

      int  global_r=0;

      struct node

      {

          node*next;              //下一结点的指针

          int    index;           //此结点在数组中的位置

          int    in;              //入度

          int    out;             //出度

          int    i;

          int    j;

          int    k;

          int    l;

          int    m;

      };

      struct param                //将传递给工作者线程的参量

      {

          node*n;                 //用来循环的第一结点指针

          int r;                  //循环迭代总量

          int s;                  //″预见″跨距

  }

  //函数说明

  void InitNodes(int num_nodes);

  void Task(param*p);

  int main(int argc,char*argv[])

  {

      int remaining=1;             //循环迭代总量

      int num_nodes=500;         //结点总量

      int stride      =4;     //工作者线程在等待主线程之前可执行的加载量

      node*n;

      register int num_work=200;

      register int i              =0;
        <!-- SIPO <DP n="13"> -->
        <dp n="d13"/>
       register int j             =0;

        param P;

        if(argc>1)

              num_nodes=atoi(argv[1));

        if(argc>2)

              num_work=acoi(argv[2]);

        if(argc>3)

              remaining=acoi(argv(3]);

        if(argc>4)

              stride=atoi(argv[4));

        remaining=num_nodes*remaining;

        InitNodes(num_nodes);

        Event=CreateEvent(NULL,FALSE,FALSE,NULL);

        n=&(pNodes[01]);

        P.n=n;

        P.r=remaining;

        P.s=stride;

        CreateThread(NULL,0,(LPTHREAD_START_ROUTIHE)Task,&P,0,NULL);

      //等待工作者线程进行预循环工作

      WaitForSingleObject(event,INFINITE);

      while(n && remaining)

      {

           for(i=0;i<num_work;i++)

           {

            _asm{pause};

           }

           n->I=n->next->j+n->next->k+n->next->l+n->next->m;

           n=n->next;

           remaining--;

           if(++j>=stride)

           {
        <!-- SIPO <DP n="14"> -->
        <dp n="d14"/>
                  j=o;

                  global_n=n;

                  global_r=remaining;

                  SetEvent(event);

              }

          }

          free(pNodes);

      }

  void Task(param*p)

  {

              register node*n                =p->n;

              register int stride            =p->s;

              register int local_remaining   =p->r;

              register int i                 =0;

      //预循环工作

      for(i=0;i<stride;i++)

      {

              n->i=n->next->j+n->next->k+n->next->l+n->next->m;

              n=n->next;

              local_remaining--;

      }

    //允许主循环中的主线程开始

      Set Event(event);

      //主循环工作

      while(local_remaining)

      {

              i=0;

              while(i<stride)

              {
        <!-- SIPO <DP n="15"> -->
        <dp n="d15"/>
                        n->i=n->next->j+n->next->k+n->next->l+n->next->m;

                        n=n->next;

                        local_remaining--;

                        i++;

                    }

                    WaitForSingleObject(event,INFIMITE);

                    if(local_remaining>global_r)

                    {

                        local_remaining=global_r;

                        n=global_n;

                    }

        }

    }

  void InitNodes(int num_nodes)

  {

      int i=0;

      int r=0;

      node*pTemp=NULL;

      pNodes=malloc(num_nodes*sizeof(node));

      //给“随机”数产生器一个种子

      srand(123456);

      for(I=0;i<num_nodes;i++)

      {

          pNodes[i].index =i;

          pNodes[i].in    =0;

          pNodes[i].out   =0;

          pNodes[i].i     =0;

          pNodes[i].j     =1;

          pNodes[i].k     =1;

          pNodes[i].l     =1;
        <!-- SIPO <DP n="16"> -->
        <dp n="d16"/>
          pNodes[il.m      =1;

      }

      pNodea[num_nodes-1].next=&(pNodes[0]);

      pNodes(num_nodes-1].out=1;

      pNodes[0].in=1;

      for(I=0;i<num_nodes-1;i++)

      {

            r=i;

            while(r==i||pNodes[r].in==1)

                      r=rand()%num_nodes;

          pNodes[i].out=1;

          pNodes[r].in=1;

          pNodes[I].next=&(pNodes[r]);

      }

  }
在用于描述将代码片断转换为适合有效操作推测预执行的形式的另一特定实施例中,推测预执行线程结构如下:
while(1){
    等待来自主线程的信号
    for/while循环
       循环控制
           间歇预取来非法加载
      调节未同步线程
  }
被修改用来支持前述结构线程的代码段为现有的MCF程序:
  while(node!=root){

       while(node){

         if(node->orientation==UP)

         node->potential=node->basic_arc->cost+node->pred->potential;

         else/*==DOWN*/

         {

         node->potential=node->pred->potential-node->basic_arc->cost;
        <!-- SIPO <DP n="17"> -->
        <dp n="d17"/>
              checksum++;

          }

          tmp=node;

          node=node->child;

    }

    node=tmp;

    while(node->pred){

    tmp=node->sibling;

    if(tmp){

       node=tmp;

       break;

      }

      else

          node=node->pred;

      }

  }

  设置SP线程以便:

  SP线程:

  g_root=root;

  SetEvent(g_event_start_a);

  while(node !=root){

        while(node){

          if(node->orientation==UP)

  node->potential=node->basic_arc->cost

                 +node->pred->potential;

        else/*==DOWN*/

        {

            node->potential=node->pred->potential

                           -node->basic arc->cost;

            checksum++;

        }

        tmp=node;
        <!-- SIPO <DP n="18"> -->
        <dp n="d18"/>
          node=node->child;

      }

      node=tmp;

      while(node->pred){

          tmp=node->sibling;

          if(tmp){

             node=tmp;

             break;

          }

          else

              node=node->pred;

      }

  }

  SP线程:

  while(1){

      WaitForSingleObject(g_event_start_a,INFINITE);

      sp_root=g_root;

      sp_tmp=sp_node=sp_root->child;

  /此处插入SP代码/

       }
重复循环控制如下:
  SP线程:

  while(1){

      WaitForSingleObject(g_event_start_a,INFINITE);

      sp_root=g_root;

      sp_tmp=sp_node=sp_root->child;

      while(sp_node!=sp_root){

         while(sp_node){

            sp_tmp=sp_node;

            sp_node=sp_node->child;

        }
        <!-- SIPO <DP n="19"> -->
        <dp n="d19"/>
            sp_node=sp_tmp;

            while(sp_node->pred){

                sp_tmp=sp_node->sibling;

                if(sp_tmp){

                   sp_node=sp_tmp;

                   break;

                }

                else

                  sp_node=sp_node->pred;

          }

      }

  }
当通过插入一内部环路计数器和跨距计数器来调节推后完成或提前执行的线程,从而处理同步问题:
主线程:
  g_root=root;

  SetEvent(g_event_start_a);

  while(node!=root){

      ……

      ……

      m_stride_count++;

      m_loop_count++;

  }

  SP线程:

  while(1){

      WaitForSingleObject(g_event_start_a,INFINITE)

      sp_root=g_root;

      sp_tmp=sp_node=sp_root->child;

      while(sp_node!=sp_root){

             ……

             ……

             sp_stride_count++;
        <!-- SIPO <DP n="20"> -->
        <dp n="d20"/>
                    sp_loop_count++;

       }

  }

      与主线程的同步如下:

      主线程:

      m_stride_count++;

      m_loop_count++;

      if(m_stride_count>=STRIDE){

          g_node=node;

          g_loop_count=m_loop_count;

          SetEvent(g_event_continue);

          m_stride_count=0;

      }

      SP线程:

      Sp_scride_count++;

      sp_loop_count++;

      If(sp_scride_count>=STRIDE){

      WaitForSingleObject(g_event_continue,INFINITE);

      if(g_loop_count>sp_loop_count)

      {   //推后完成、跳转开始

          sp_loop_count=g_loop_count;

          sp_node=g_node;

      }

      else if((g_loop_count+STRIDE)<sp_loop_count)

      {   //又提前、推后并开始

          sp_loop_count=g_loop_count;

          sp_node=g node;

      }

      sp_stride_count=0;

  }
对带有内部计数器的MCF代码进行基本更新如下:
主线程:
  m_stride_count++;

  m_loop_count++;

  if(m_stride_count>=STRIDE){

     EnterCriticalSection(&cs);

     g_node=node;

     g_loop_count=m_loop_count;

     LeaveCriticalSection(&cs);

     m_stride_count=0;

  }

  SP线程:

  sp_stride_count++;

  sp_loop__count++;

  If(sp_stride_count>=STRIDE){

     if(g_loop_count>sp_loop_count)

     {  //推后完成、跳转开始

        EnterCriticalSection(&cs);

        sp_loop_count=g_loop_count;

        sp_node=g_node;

        LeaveCriticalSection(&cs);

     }

     else if((g_loop_count+STRIDE)<sp_loop_count)

     {//又提前、推后并开始

        EnterCriticalSection(&cs);

        sp_loop__count=g_loop_count;

        sp_node=g_node;

        LeaveCriticalSection(&cs);

     }

     sp_stride_count=0;

  }
其他MCF代码增强包括其它通过提前运行主线程和循环体中非法加载的间歇预取来增强SP线程终止:
主线程:
  while(node!=root){

        ……

  }

  EnterCriticalSection(&cs);

  g_node=root;

  g_loop_count=m_loop_count;

  LeaveCriticalSection(&cs);

  SP线程:

  while(sp_node!=sp_root){

    while(sp_node){

      if((sp_loop__count % 100)==0||

         (ahead_count--)>0)

        temp=node->basic_arc->cost

            +node->pred->potential;

      sp_tmp=sp_node;

      sp_node=sp_node->child;

  }

  ……

  If(sp_stride_count>=STRIDE){

      ……

      else if((g_loop_count+STRIDE)<sp_loop_count)

      {//不推后

        ahead_count=15;

      }

      sp_stride_count=0;

      }

  }
说明书中所提到的“实施例”、“一个实施例”、“一些实施例”或“其它实施例”表示与至少一些实施例中所包括的实施例相关的一特殊特征、结构或特性,但不一定是本发明的所有实施例。所出现的“实施例”、“一个实施例”或“一些实施例”并不都指相同实施例。
如果说明书表达一组件、特征、结构或特性时包括“可”、“可以”或“能”,则不需包括特殊组件、特征、结构或特性。如果说明书或权利要求提到“一”元件,那不表示只有一个元件。假如说明书或权利要求书提到“一附加”元件,那不排除存在多于一个附加元件。
从本公开中获益的本领域普通技术人员可以理解,在本发明的范围内可对前述描述和附图做许多其他变化。因此,下列权利要求包括定义本发明范围的任何修改。

Claims (20)

1.一种执行推测多线程并且提供多线程之间的同步的系统,包括:
一个或多个处理器,所述一个或多个处理器提供执行一个非推测软件线程的第一线程上下文和能够执行一个与所述非推测线程并发的推测软件线程的第二线程上下文;
一个与所述第一和第二线程上下文耦合的存储器单元,所述存储器单元存储至少一个可被所述非推测和推测线程访问的全局变量;和
允许所述推测线程访问所述至少一个全局变量来规范其相对于所述非推测线程的相对进度并且提供同步非推测和推测线程的执行的效果的逻辑。
2、依据权利要求1的系统,其中所述逻辑是一个硬件模块。
3、依据权利要求1的系统,其中所述逻辑是一组一个或多个软件指令。
4、依据权利要求3的系统,其中所述逻辑是一个或多个编译器生成的软件指令。
5、依据权利要求2的系统,其中所述逻辑是微代码。
6、依据权利要求1的系统,其中所述一个或多个处理器包括一个SMT处理器。
7、依据权利要求1的系统,其中所述一个或多个处理器包括多个处理器。
8、依据权利要求7的系统,其中所述多个处理器还包括一个芯片多处理器。
9、依据权利要求1的系统,其中所述存储器单元还包括一个随机存取存储器。
10、依据权利要求1的系统,其中所述存储器单元还包括:
一个编译器程序,该编译器程序具有当被所述一个或多个处理器的至少一个执行时使所述处理器执行下述操作的指令:
标识所述非推测软件线程的一个或多个指令;和
生成对应于所述标识的指令的一个或多个推测线程指令。
11、一种执行推测多线程的处理器,包括:
执行一个非推测软件线程的第一线程上下文和能够执行一个与所述非推测线程并发的推测软件线程的第二线程上下文;
存储器装置,存储一个可被所述第一和第二线程上下文访问的全局变量来指示所述非推测线程的进度,和
同步所述推测和非推测线程的逻辑。
12、依据权利要求11的处理器,其中所述存储器装置还包括一个内部寄存器。
13、依据权利要求12的处理器,其中所述处理器能够动态地创建所述推测线程。
14、依据权利要求13的处理器,其中所述处理器能够通过执行诸如派生指令的线程创建指令来动态地创建所述推测线程。
15、依据权利要求11的处理器,其中所述处理器能够执行一个或多个指令来当推测线程的进度已落后于由全局变量所指示的非猜测线程之后时,使推测线程提前跳到非推测线程的上一通信位置。
16、依据权利要求11的处理器,其中所述处理器能够执行一个或多个指令来当推测预执行线程的进度已处于由全局变量所指示的非猜测线程之前时,使推测线程等待直到非推测线程发信号来继续执行。
17、依据权利要求11的处理器,其中所述处理器能够执行一个或多个指令来当推测线程的进度已处于由全局变量所指示的非推测线程之前时,使推测线程跳回到上一通信位置。
18、依据权利要求11的处理器,其中所述推测线程是一个为所述非推测线程执行推测预取的推测预执行线程。
19、依据权利要求11的处理器,其中所述处理器还包括在程序初始阶段动态标识发生推测预执行线程的硬件。
20、依据权利要求11的处理器,其中所述处理器能够允许所述推测线程产生另一个处理以便另一个处理可以在所述第二线程上下文上执行同时所述推测线程处于等待状态。
CNB2003101240682A 2002-12-31 2003-12-31 单线程代码到推测预执行启用代码的变换 Expired - Fee Related CN1287281C (zh)

Applications Claiming Priority (2)

Application Number Priority Date Filing Date Title
US10/334868 2002-12-31
US10/334,868 US20040128489A1 (en) 2002-12-31 2002-12-31 Transformation of single-threaded code to speculative precomputation enabled code

Publications (2)

Publication Number Publication Date
CN1514365A CN1514365A (zh) 2004-07-21
CN1287281C true CN1287281C (zh) 2006-11-29

Family

ID=32655190

Family Applications (1)

Application Number Title Priority Date Filing Date
CNB2003101240682A Expired - Fee Related CN1287281C (zh) 2002-12-31 2003-12-31 单线程代码到推测预执行启用代码的变换

Country Status (2)

Country Link
US (2) US20040128489A1 (zh)
CN (1) CN1287281C (zh)

Families Citing this family (22)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
US7502910B2 (en) * 2003-01-28 2009-03-10 Sun Microsystems, Inc. Sideband scout thread processor for reducing latency associated with a main processor
US20040148489A1 (en) * 2003-01-28 2004-07-29 Sun Microsystems, Inc. Sideband VLIW processor
US20040243767A1 (en) * 2003-06-02 2004-12-02 Cierniak Michal J. Method and apparatus for prefetching based upon type identifier tags
US20050034108A1 (en) * 2003-08-15 2005-02-10 Johnson Erik J. Processing instructions
US20050071438A1 (en) * 2003-09-30 2005-03-31 Shih-Wei Liao Methods and apparatuses for compiler-creating helper threads for multi-threading
US7434004B1 (en) * 2004-06-17 2008-10-07 Sun Microsystems, Inc. Prefetch prediction
US20070113056A1 (en) * 2005-11-15 2007-05-17 Dale Jason N Apparatus and method for using multiple thread contexts to improve single thread performance
US20070113055A1 (en) * 2005-11-15 2007-05-17 Dale Jason N Apparatus and method for improving single thread performance through speculative processing
US9003421B2 (en) * 2005-11-28 2015-04-07 Intel Corporation Acceleration threads on idle OS-visible thread execution units
US20080141268A1 (en) * 2006-12-12 2008-06-12 Tirumalai Partha P Utility function execution using scout threads
US8448154B2 (en) * 2008-02-04 2013-05-21 International Business Machines Corporation Method, apparatus and software for processing software for use in a multithreaded processing environment
CA2680597C (en) * 2009-10-16 2011-06-07 Ibm Canada Limited - Ibm Canada Limitee Managing speculative assist threads
US9310875B2 (en) 2011-12-22 2016-04-12 Intel Corporation Instruction that specifies an application thread performance state
US9396020B2 (en) 2012-03-30 2016-07-19 Intel Corporation Context switching mechanism for a processing core having a general purpose CPU core and a tightly coupled accelerator
US9830206B2 (en) * 2013-12-18 2017-11-28 Cray Inc. Cross-thread exception handling
GB2522910B (en) * 2014-02-10 2021-04-07 Advanced Risc Mach Ltd Thread issue control
US10185564B2 (en) * 2016-04-28 2019-01-22 Oracle International Corporation Method for managing software threads dependent on condition variables
CN108733409B (zh) * 2017-04-24 2022-10-25 华为技术有限公司 执行推测线程的方法以及片上多核处理器
US10802882B2 (en) * 2018-12-13 2020-10-13 International Business Machines Corporation Accelerating memory access in a network using thread progress based arbitration
CN113360280B (zh) * 2021-06-02 2023-11-28 西安中锐创联科技有限公司 基于多线程运行、动态全局变量处理的仿真曲线显示方法
US11531544B1 (en) 2021-07-29 2022-12-20 Hewlett Packard Enterprise Development Lp Method and system for selective early release of physical registers based on a release field value in a scheduler
US11687344B2 (en) * 2021-08-25 2023-06-27 Hewlett Packard Enterprise Development Lp Method and system for hard ware-assisted pre-execution

Family Cites Families (7)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
WO1994027216A1 (en) * 1993-05-14 1994-11-24 Massachusetts Institute Of Technology Multiprocessor coupling system with integrated compile and run time scheduling for parallelism
US6073159A (en) * 1996-12-31 2000-06-06 Compaq Computer Corporation Thread properties attribute vector based thread selection in multithreading processor
US6101524A (en) * 1997-10-23 2000-08-08 International Business Machines Corporation Deterministic replay of multithreaded applications
US6341347B1 (en) * 1999-05-11 2002-01-22 Sun Microsystems, Inc. Thread switch logic in a multiple-thread processor
US6353881B1 (en) * 1999-05-17 2002-03-05 Sun Microsystems, Inc. Supporting space-time dimensional program execution by selectively versioning memory updates
US7328433B2 (en) * 2003-10-02 2008-02-05 Intel Corporation Methods and apparatus for reducing memory latency in a software application
US7950012B2 (en) * 2005-03-16 2011-05-24 Oracle America, Inc. Facilitating communication and synchronization between main and scout threads

Also Published As

Publication number Publication date
US20040128489A1 (en) 2004-07-01
US20110067011A1 (en) 2011-03-17
CN1514365A (zh) 2004-07-21

Similar Documents

Publication Publication Date Title
CN1287281C (zh) 单线程代码到推测预执行启用代码的变换
Falsafi et al. A primer on hardware prefetching
CN108027766B (zh) 预取指令块
US10101978B2 (en) Statically speculative compilation and execution
US7950012B2 (en) Facilitating communication and synchronization between main and scout threads
US7849453B2 (en) Method and apparatus for software scouting regions of a program
US20180219795A1 (en) Secure memory with restricted access by processors
US20170083338A1 (en) Prefetching associated with predicated load instructions
US10592430B2 (en) Memory structure comprising scratchpad memory
EP1459169B1 (en) Aggressive prefetch of dependency chains
US20170083339A1 (en) Prefetching associated with predicated store instructions
JP6690811B2 (ja) ランアヘッドランタイムゲスト命令変換/デコードプロセスと、ゲストコードが、命令シーケンスにおけるゲスト分岐のターゲットからプリフェッチされるプリフェッチプロセスとを実施するシステム変換器
JP6690813B2 (ja) 変換ルックアサイドバッファを用いた命令セットアグノスティックランタイムアーキテクチャの実施
Zhang et al. Leveraging caches to accelerate hash tables and memoization
JP6683321B2 (ja) ゲストイメージからのコードを実行するための実行時オプティマイザを実行するシステム変換器
Byna et al. Taxonomy of data prefetching for multicore processors
CN1650266A (zh) 支持单线程应用程序的时分多路复用推理性多线程
US20120226892A1 (en) Method and apparatus for generating efficient code for scout thread to prefetch data values for a main thread
Lin et al. JACO: JAva Code Layout Optimizer Enabling Continuous Optimization without Pausing Application Services
Psaropoulos Improving Main-memory Database System Performance through Cooperative Multitasking
Gibert et al. Distributed data cache designs for clustered VLIW processors

Legal Events

Date Code Title Description
C06 Publication
PB01 Publication
C10 Entry into substantive examination
SE01 Entry into force of request for substantive examination
C14 Grant of patent or utility model
GR01 Patent grant
C17 Cessation of patent right
CF01 Termination of patent right due to non-payment of annual fee

Granted publication date: 20061129

Termination date: 20131231