用于将顺序程序分解为多个线程、执行所述线程和重构该顺序执行的系统、方法和装置的制作方法

文档序号:6595121阅读:179来源:国知局
专利名称:用于将顺序程序分解为多个线程、执行所述线程和重构该顺序执行的系统、方法和装置的制作方法
技术领域
本发明的实施例总体上涉及信息处理领域,并且更具体地说,涉及在计算系统和微处理器中的多线程执行领域。
背景技术
在过去几十年间,通过对指令级并行性(ILP)的使用,单线程处理器已经表现出显著的性能提高。然而,这种并行性有时难以使用并且需要复杂的硬件结构,而复杂的硬件结构可能导致过高功耗和设计复杂性。此外,复杂性和功率的这种增加使得回报越来越小。 芯片多处理器(CMP)已经成为前景看好的替代品,以在合理的功率预算下提供进一步的处理器性能提高。


在附图中以示例的方式而非限制的方式说明了本发明的实施例,在附图中相同的标记指示相同的元件,并且在附图中图1是说明细粒度多线程化系统的至少一个实施例的硬件和软件元件的框图。图2说明了使用SpMT的示例性流程。图3说明了由四个基本块构成的小循环的示例性细粒度线程分解。图4说明了要在两个处理核心中运行的两个线程的示例,其中它们间具有示出为数据依赖图(“DDG”)的两个数据依赖。图5示出了当考虑控制流时线程划分结果的三个不同示例。图6说明了一些实施例的分解方案的概述。图7说明了用于在优化器中使用细粒度SpMT生成程序代码的方法的实施例。图8说明了示例性多层图。图9说明了粗化方法的实施例。图10说明了粗化方法的伪代码表示的实施例。图11说明了正在被提交到FIFO队列中的线程的实施例。图12说明了用于确定用于优化区域的POP标记的方法的实施例。图13说明了使用具有集合活动(hammock)的循环的示例。图14说明了用于使用POP标记来重构流的方法的实施例。图15是说明在其上可以使用线程排序重构机制的实施例的多核心系统的实施例的框图。图16说明了在协作模式中工作的区块(tile)的示例。图17是说明根据本发明的至少一个实施例的、支持推测多线程化的示例性存储器层级的框图。图18说明了当一存储指令在优化模式中全局地引退时要进行的动作的方法的实施例。图19说明了当一加载指令将在优化模式中全局地引退时要进行的动作的方法的实施例。图20说明了 ICMC的实施例。图21说明了检查点机制的ROB的至少一个实施例。图22是说明寄存器检查点硬件的至少一个实施例的框图。图23说明了使用检查点的实施例。图M说明了使用线程级重构的微处理器的实施例。图25说明了在其中可以使用本发明的一个实施例的前端总线(FSB)计算机系统。图沈示出了根据本发明的一个实施例的系统的框图。图27示出了根据本发明的实施例的系统实施例的框图。图观示出了根据本发明的实施例的系统实施例的框图。
具体实施例方式本发明的实施例涉及用于将顺序程序分解为多个线程或执行流、并行地执行它们和重构该顺序执行的技术。例如,本文描述的一些实施例允许在指令被任意地分配给多个线程时重构指令的顺序次序。因此,本文描述的这些实施例可以与将顺序程序分解为多个线程或执行流的任意技术一起使用。特别地,本文可以使用它们来重构已经以指令粒度被分解为推测线程的应用程序的顺序次序。推测多线程化是一种并行化技术,其中将顺序代码段分解为要在不同核心或相同核心的不同逻辑处理器(功能单元)中并行执行的线程。推测多线程化(“SpMT”)可以使用多个核心或功能单元来提高单个线程性能。SpMT支持的线程可以取决于运行时条件而被原子地提交或销毁(squash)。尽管下文在运行于不同核心上的线程的环境下进行讨论,但是本文讨论的概念也适用于类似推测多线程化的执行。即,本文讨论的概念也适用于在相同核心的不同SMT逻辑处理器上运行的推测线程。细粒度SpMT范例推测多线程化使用多个核心来提高单个线程性能。它支持的线程可以取决于运行时条件而被原子地提交或销毁。在传统的推测多线程化方案中,每一个线程执行一大块连续指令(例如,循环迭代或函数调用)。概念上,这相当于将动态指令流划分成多个块并且并行地执行它们。然而,这种划分可能最终在线程间有太多依赖,这限制了可使用的TLP并且损害性能。在细粒度SpMT中,可以以比传统线程化方案中更细的粒度将指令分布在线程中。在该意义上,该新的模型是先前线程化范例的超集并且其能够比传统方案更好地使用 TLP。下文描述的是使用静态或动态优化器的推测多线程化范例的实施例,其中,所述静态或动态优化器使用多硬件环境(即,处理核心)来加速单线程应用程序。与其中大块的连续指令被分配给线程的传统线程化技术相比,顺序代码或动态流以非常细的粒度(单独指令级)被分解为多个推测线程。该灵活性允许在顺序应用程序上使用TLP,而传统划分方案最终具有可能限制性能的许多线程间数据依赖。这还可以提高线程的工作平衡和/或增加可以使用的存储器级并行性的量。在存在线程间数据依赖的情况下,描述了用来管理它们的三种不同途径1)使用显式线程间通信;2)使用预计算片(复制的指令)来在本地满足这些依赖;和/或3)忽略它们,推测没有依赖并且允许硬件检测可能的违反(violation)。在该细粒度线程化中,线程中的控制流被本地管理并且仅需要包括线程中影响其被分配的指令的执行的那些分支指令。因此,核心前端不需要任何额外的硬件来处理线程的控制流或管理分支指令误预测, 并且每一个核心独立地取得、执行和提交指令(除了由显式线程间通信引起的同步点)。图1是说明细粒度多线程化系统的至少一个实施例的硬件和软件元件的框图。原始线程101被送入包括用于线程生成103的一个或多个模块的软件,诸如编译器、优化器等。由一个或多个模块将线程或其区域分解为多个线程105。每一个线程将在其自己的核心/硬件环境107上被执行。这些核心/环境107耦合到若干不同的逻辑部件,例如用于重构原始程序次序或其子集的逻辑109、用于存储器状态的逻辑111、用于寄存器状态的逻辑113和其它逻辑115。图2说明了使用SpMT的示例性流程。在201,由编译器、优化器或其他实体接收顺序应用程序(程序)。该程序可以是可执行代码或源代码形式。在203,顺序应用程序的至少一部分被分解为构成一个或多个优化区的细粒度线程。下文描述了该分解的实施例并且其可以由编译器、优化器或其他实体执行。在205,正常地执行该顺序应用程序。在207确定应用程序是否应当进入优化区。 通常地,孵化(spawn)指令表示优化区的开始。例如由编译器在程序执行之前正常地添加该指令或等价物。如果代码应当正常地处理,那么在205进行处理。然而,如果存在孵化指令,那么为优化区创建一个或更多线程,并且在209以协作(推测多线程化)模式执行程序直到在 211确定优化区完成为止。在213,当优化区完成时,将其提交,并且继续应用程序的正常执行。细粒度线程分解细粒度线程分解是从顺序代码或动态流中生成线程,从而将单独指令灵活地分布在其中。这可以在编译时由动态优化器实现或静态地实现。图3说明了由四个基本块(A、B、C*D)构成的小循环的示例性细粒度线程分解。 每一个基本块由标记为Ai、Bi、Ci和Di的若干指令组成。附图左侧示出了循环的原始控制流图(“CFG”),和当其在一环境中随时间被执行时的一段动态流。附图的右侧示出了一种可能的细粒度线程分解的结果,即被分解为两个线程,每一个线程具有其自己的环境。在该图中示出了每一个结果线程的CRi和当并行执行它们时每一个的动态流。该线程分解比传统方案更加灵活,在传统方案中将大块指令分配给线程(典型地,传统线程化方案将循环迭代分配给每一个线程)。虽然在图3中将循环示出为示例,但是细粒度线程分解是与任何高级代码结构不相关的,并且可以应用到任何一段顺序代码或动态流。这种在线程中分布单独指令的灵活性可以用来实现用于生成它们的不同策略。可以有助于顺序代码或动态流的线程分解并允许使用更多线程级并行性的一些策略包括但不限于以下策略中的一个或多个1)将指令分配给线程以最小化线程间数据依赖的量;2) 将指令分配给线程以平衡其工作负荷(细粒度线程分解允许工作负荷的细调,因为可以在指令级作出平衡线程的决定);以及3)可以将指令分配给线程以更好地使用存储器级并行性(“MLP”)。MLP是用于存储器限制的应用程序的并行性的来源。对于这些应用程序,MLP 的增加可以带来性能上显著的提高。细粒度线程分解允许在线程中分布加载指令以便增加 MLP。线程间数据依赖管理推测多线程化范例的一个问题是对线程间数据依赖的处理。下文描述了用来解决线程间数据依赖的两种机制1)预计算和2、通信。第一种机制是使用预计算片(简称“pslice”)来断开线程间数据依赖并在本地满足它们。例如,给定分配给线程Tl、需要由线程T2生成的数据的指令“I”,将还没有分配给 Tl的、属于其pslice的所有需要的指令(生成I需要的数据所需的指令的子集)复制(复写)到Tl中。在本文中这些指令称为被复制的指令。这些被复制的指令被视为常规指令并且可以与分配给线程的其余指令一起调度。因此,在推测线程中,被复制的指令与其余指令混合并且可以被重排序以最小化线程的执行时间。此外,预计算一值不意味着复制属于其 pslice的所有指令,因为计算该值所需的一些中间数据可以在不同的线程中被计算并且可以如下文所解释的那样被传送。第二种是通过显式的线程间通信来解决依赖,其中这些依赖(i)可能需要太多被复制的指令来在本地满足它们或(ii)可以延迟一定的周期量而不损害执行时间。这减少了必须复制的指令量,但是(至少在接收机指令中)引入了针对每一个显式通信的同步点。图4说明了要在两个处理核心中运行的两个线程的示例,其中它们间具有示出为数据依赖图(“DDG”)的两个数据依赖。然而,本领域技术人员将认识到,本文描述的重排序实施例可以与涉及分解为更大数量的线程和/或更大数量的在其上运行分解后的线程的核心或逻辑处理器的细粒度多线程化一起使用。在该图中,圆圈是指令,箭头表示两个指令之间的数据依赖。在左侧是原始顺序控制流图(“CFG”)和循环的顺序执行的示例性指令动态执行流。在该CFG中,指令“b”和“d”具有与指令“a”的数据依赖。右侧示出了针对左侧的顺序循环CFG的示例性线程分解。在以指令粒度将循环分解为两个线程(在两个线程中都复制指令Dl)后,创建了两个CFG和两个动态执行流。这说明了用于两个分解后的线程的分解后的控制流图,并且还说明了并发执行循环的分解后的线程的示例性可能的指令动态执行流。为此假设孵化指令被执行并且孵化程序(spawner) 和孵化(spawnee)线程开始取得和执行其被分配的指令,而在两个执行流之间的没有任何明确次序。右侧说明知道属于该示例中不同线程执行流的两个给定指令之间的次序不是无关紧要的。如能看到的,一个依赖通过在线程1中需要一个被复制的指令(“a”)的预计算片来解决,而另一个依赖通过(“h”和“f”之间)的显式通信来解决。在运行时可能出现在线程分解时没有预见的额外的依赖。实现细粒度SpMT的系统(硬件、固件、软件和其组合)应当检测这种依赖违反并且销毁违反的线程并重启它/它们的执行。对于至少一个实施例,在硬件中进行从分解后的指令流来重构顺序执行。对于一些实施例,由下文更详细描述的核心间存储器一致性模块(Inter-Core Memory Coherence Module) (ICMC)执行该硬件功能。
控制流管理当使用细粒度SpMT、以指令粒度将指令分布到线程以并行地执行它们时,应当考虑和/或管理原始顺序执行的控制流。例如,当生成推测线程时可以由软件来管理控制流。 这样,使用细粒度SpMT的处理器前端不需要任何额外的硬件来处理细粒度SpMT线程的控制流或管理分支指令误预测。相反,在其通过使用传统预测和恢复机制来执行的环境中,在本地管理给定线程的控制推测。在细粒度SpMT中,每一个线程包括其需要用来计算其指令的控制路径的所有分支指令。执行给定线程的任意指令所需要但不是原始地包括在该线程中的那些分支指令被复制。注意,并非所有分支指令在所有线程中都是需要的,仅影响其指令的执行的那些分支指令是需要的。此外,在线程中具有分支指令不意味着也需要包括线程中计算该分支指令所需的所有指令,因为SpMT范例允许线程间通信。例如,一种可能的情形是,仅一个线程计算分支指令条件并且它会将该分支指令条件传送到其余的线程。另一情形是,给定分支指令的控制流的计算被完全地分散在所有线程中。图5示出了当考虑控制流时线程划分结果的三个不同示例。控制流中涉及的指令被突出,并且箭头示出了显式的线程间通信。如能够看到的,在所有三种情况中,分支指令 (原始代码中的Bz LABEL)在需要它的所有线程(Tl和T2)中被复制。在单个控制流计算的情况(a)中,计算该分支指令的指令由T2执行,并且结果被发送到Tl。在完整复制控制流的情况(b)中,该计算在两个线程(Tl和T2)中被复制,并且不需要显式通信。像程序中任意其他计算一样划分该分支指令的计算,从而其可以被拆分到显式通信的不同线程中 (包括不真正关心该分支指令的线程)。该示例示出在控制流的拆分计算(c)中。对于至少一个实施例,顺序代码段可以是无法用传统工具有效并行化的完整顺序程序。对于至少一个其他实施例,顺序代码段可以是并行化应用程序的一串行部分。推测多线程化使得多核心架构表现为能够更快地执行单线程应用程序的有效复杂度 (complexity-effective)很宽的核心。对于本文描述的至少一些实施例,假设原始的单线程应用程序或其部分已被分解为若干推测线程,其中这些线程的每一个执行原始顺序应用程序或其部分的全部工作的子集。这种分解可以例如由外部工具(例如,动态优化器、编译器等)执行。从单线程程序生成多个推测线程其中将顺序应用程序分解为推测线程的处理阶段在本文中称为“后期”(anaphase)。为了讨论的目的,将假设这种分解在编译时发生。然而,如上文所提及的, 这种分解可以经由除了编译器之外的其他外部工具(例如,动态优化器)进行。为覆盖应用程序的大部分执行时间的那些区生成SpMT线程。在本部分,首先描述该模型中考虑的推测线程,然后描述相关联的执行模型,最后描述用于生成它们的编译器技术。推测线程间可能出现线程间依赖。当另一个推测线程中需要一个推测线程中产生的值时,产生这些依赖。可以在编译时通过分析代码和/或使用简档(profile)信息来检测线程间依赖。然而,可能不是所有可能的依赖都在编译时被检测到,并且分解为线程的分解以推测方式执行。对于至少一个实施例,硬件负责处理可能在运行时期间在分配给不同推测线程的两个指令间出现的并且当编辑器生成线程时未考虑到的存储器依赖。对于在编译时识别的所有线程间依赖,在推测线程中生成适当的代码来处理它们。特别地,应用以下技术中的一种⑴通过显式通信来满足所述依赖;或( )通过预计算片(p-slice)来满足所述依赖,所述预计算片是生成消耗的数据(“存活期” (live-in)) 所需的指令的子集。包括在P-slice中的指令可能需要被分配给多于一个线程。因此,推测线程可以包括被复制的指令,如图3中的指令Dl的情况。最后,从控制流的角度看,每一个推测线程都是自包含的。这意味着每一个线程具有其需要用来解决其自身执行的所有分支指令。注意,为了达到该目的,需要将影响线程指令执行的那些分支指令放置在相同的线程上。如果一分支指令需要被放置在多于一个线程上,那么其被复制。这也由编译器在生成线程时处理。关于执行,如下文所说明的,以协作方式在多核心处理器上执行推测线程。在图6 中给出了一些实施例的分解方案的概述。为了该讨论的目的,假设由两个不同核心(例如参见图15的区块)或由相同或不同核心的两个不同逻辑处理器并发执行推测线程(对应于线程id 0( "tid 0”)和线程id 1( "tid 1”))。然而,本领域的技术人员将认识到,用于执行一组原本为排序指令的并发执行的区块可以包括多于两个核心。类似地,本文描述的技术可应用到每个核心包括多个SMT逻辑处理器的系统。如上所讨论的,编译器或类似实体检测适于应用推测多线程化的特定区(在该说明中为区B 610)。然后该区610被分解为推测线程620、630,推测线程620、630被映射到应用程序代码中其他位置,以作为区610的优化版本640。在进入被优化的区(区B 610)之前,将孵化指令650插入到原始代码中。孵化操作创建新的线程,并且孵化程序和孵化推测线程二者开始执行代码的优化版本640。对于示出的示例,孵化程序线程可以执行一个推测线程(例如,620),而孵化线程可以执行另一个 (例如,630)。当两个推测线程处于协作方式时,当通过显式通信满足线程间依赖时,在线程间进行同步。然而,通信可能暗示仅使用者侧进行同步,只要合适的通信机制被适当设置即可。常规存储器或专用逻辑可以用于这些通信。另一方面,当处于协作模式时可能发生违反、异常和/或中断,并且推测线程可能需要被回滚。这可以由硬件以对软件线程完全透明的方式来处理,或通过包括一些额外代码来在编译时对其进行处理(例如,见回滚代码660)。当两个线程到达最后指令时,它们同步以退出优化区,推测状态变为非推测,并且执行以一个单线程继续进行,区块恢复到单核心模式。下文结合附图15更详细地描述本文所使用的“区块”。一般地,区块是工作来并发地执行一组原本为顺序指令的一组指令的不同部分的两个或更多核心的组(其中,所述“不同”部分还可以包括被复制的指令)。推测线程通常在编译时生成。这样,编译器负责(1)剖析应用程序,(2)分析代码并且检测代码中最适宜进行并行化的区,(3)将所选择的区分解为推测线程;以及(4)生成优化代码和回滚代码。然而,下文描述的技术可以应用到已经编译的代码。另外,本文讨论的技术可以应用到所有类型的循环以及非循环代码。对于至少一个实施例,针对其生成推测线程的循环可以是展开的和/或频繁执行内联例程的。图7说明了用于在优化器中使用细粒度SpMT生成程序代码的方法的实施例。在 701,接收或生成“原始”程序代码。该程序代码通常包括若干代码区。在703,原始程序代码用于生成数据依赖图(DDG)和控制流图(CFG)。可替换地,可以由优化器接收DDG和ere。分析这些图来查找将为多线程推测执行的候选的一个或多个区。例如,“热”(hot) 区可以指示SpMT将是有益的。作为该分析的一部分,通过其动态发生和在指令间出现的数据依赖(寄存器或存储器)的次数来加权DDG中的节点(例如x86指令)和边,并且通过所采取路径的频率来加权CRi中的控制边。在705,将该简档信息添加到图并且将两个图压缩(collapse)成程序依赖图(PDG)。在其他实施例中,所述图不被压缩。在一些实施例中,通过应用如代码重排序、常量传播、循环展开和例程专门化等的安全数据流和控制流代码转换来优化PDG。在707执行粗化(coarsening)。在粗化期间,将节点(指令)迭代地压缩成更大的节点直到具有与所期望的划分数量一样多的节点为止(例如,在两个线程的情况中的两个划分)。粗化提供相对好的划分。在粗化步骤中,通过将节点对压缩成超节点直到最终图具有与线程一样多的超节点为止来迭代地减小图大小,描述了到线程的指令的第一划分。在该过程期间,在多层图 (在图8中说明了示例性多层图)中创建不同层的超节点。来自给定层的节点包括来自其下层的一个或多个节点。这可以在图8中看到,其中,层0的节点是单独的指令。较粗的节点称为超节点,并且术语节点和超节点在整个本说明书中是可互换的。此外,每一层以如下方式具有更少的节点底层包含原始图(传递到算法的该步骤的图)并且最高层仅包含与期望生成的线程一样多的超节点。属于一个超节点的节点将被分配给相同的线程。为此,在实施例中,在图中的层i选择一对节点来进行粗化并且在层i+Ι构造包括这两个节点的超节点。该示例可以在图8中看到,其中层0的节点a和b被联合来形成层1 的节点ab。重复该过程直到所有的节点都被投影到下一层或再没有要压缩的有效对为止。 当这发生时,只是在当前层还没有压缩的节点才被添加到下一层以作为新的超节点。这样, 完成了新的层并且针对该新的层重复算法直到获取了期望数量的超节点(线程)为止。当粗化所述图时,对于至少一个实施例,将最高优先级给予属于关键路径的那些指令的融合。在同等重要的情况下,可以将优先级给予具有更大数量的共同祖先的那些指令。共同祖先的数量越多,连通性越强,并且因此通常更适合将它们融合到相同线程中。另一方面,为了在线程中合适地分布工作负荷,极低的优先级被给予以下的融合(1)彼此不 (直接地或间接地)依赖的节点;以及( 不良加载指令及其使用者。在剖析期间在L2高速缓存中具有很高未命中率的加载指令可以被认为是不良的。图9说明了粗化方法的实施例。在920,创建多层图,其中区的指令位于该多层图的第一层,并且将多层图的当前层设置为例如0的初始值。参考图8,这是多层图中的L0。在930判决划分的数量是否大于期望的线程数量。例如,划分的数量大于2 (将创建3个线程而不是2个)?如果已经获取了所述数量的划分,那么粗化完成。然而,如果划分的数量大于期望的数量,那么在940创建矩阵。再次参考图8的例子,层0的划分数量是9,因此将需要创建矩阵来创建下一层(Li)。在实施例中,矩阵的创建包括三个子例程。在971,初始化矩阵M并且将其值设置为0。根据节点之间的关系构建矩阵M,其中矩阵位置M[i,j]描述节点i和j之间的关系比率,并且M[i,j] =M[j,i]。这个比率是范围在0(最差比率)和2(最好比率)之间的值比率越高,两个节点越相关。在被初始化为全0后,根据一组预定准则来填充矩阵M的单元。这种准则的第一个是检测不良加载指令,所述不良加载指令是将很可能在高速缓存中经常未命中并且因此影响性能的那些加载指令。在实施例中,确定未命中率高于阈值(例如,10%)的那些不良加载指令。具有不良加载指令的节点和其预计算片的形成有助于进行改善(晚些描述),以将这些加载指令建模为与其使用者相分离。因此,连接不良加载指令和使用者的数据边被给予非常低的优先级。在实施例中,这些节点的比率在矩阵M中被固定为0. 1(非常低的优先级),而不管下面的松弛度(slack)和公共前驱评估。因此,对于矩阵M中被识别为不良节点的那些节点,其被给予值0. 1。在图10中表示了该情况的实施例的伪代码表示。在972,计算PDG的每一条边的松弛度并且相应地更新矩阵M。松弛度是指令必须延迟其执行而不影响总的执行时间的自由度。为了计算该松弛度,首先,计算每一个指令的最早调度时间。对于该计算,只考虑数据依赖。此外,忽略不同迭代之间的依赖。在这之后, 用类似或相同的方式计算每一个指令的最晚调度时间。每一条边的松弛度被定义为使用者和产生者节点分别的最早和最晚调度时间之间的差。这种方式下不具有松弛度的边(控制边和迭代间依赖)具有缺省松弛度值(例如,100)。由具有非常低松弛度的边连接的两个节点i和j被认为是关键路径的一部分并且将被压缩为具有更高优先级。关键边是具有松弛度为0的那些边,并且那些节点的比率M[I,j] mm, i]被设置为最佳比率(例如,2. 0)。 在图10中表示了该情况的伪代码表示。在973,通过查看公共前驱来填充矩阵M的剩余节点。通过向后遍历边来计算每一个节点对(i,j)共享的前驱指令的数量。这帮助将依赖指令分配给相同线程和将独立指令分配给不同线程。在实施例中,每一个节点对的前驱关系被计算为其祖先的交集和其祖先的并集之间的比率。以下等式定义了节点i和j之间的比率(R)函数P(i)和P(j)表示前驱i或j的集合,其包括节点i或j。在实施例中,通过其剖析的执行频率来加权P(i)中的每一个前驱指令,以给予对动态指令流具有更深影响的指令更高的重要度。该比率一定程度上描述了两个节点有多相关。如果当向后遍历图时两个节点共享节点的重要量,那么这意味着它们共享许多计算并且因此将它们映射到相同线程是有意义的。它们在矩阵M中应当具有大的关系比率。另一方面,如果两个节点不具有公共前驱,那么它们是独立的并且是被映射到不同线程的良好候选。在存在重现的情况下,许多节点具有比率1. 0(他们共享所有的前驱)。为了解决这些问题,比率被计算两次,一次是正常计算,而第二次忽略不同迭代(重现)之间的依赖。 最终比率是这两个比率之和。这提高了所获取线程化的质量并且因此提高了性能。使用最终比率来填充矩阵M的剩余单元。图10中表示了这种情况的伪代码表示。注意,可以开启/关闭这三个给出的准则中的任意一个以便生成良好的线程。当矩阵已在940被填充时,在950递增当前层并且在960压缩节点。该压缩将节点对联合为新的超节点。对于每一个节点对,如果该节点对满足一条件集合,那么将他们进行压缩。例如,在实施例中,对于给定的节点,针对压缩的一个条件是节点i和j都没有从先前层压缩到当前层。在另一实施例中,M[i,j]的值应当最多比任意k的M[i,k] /Jn 5%, 并且最多比任意一个节点的M[l,j]小5%。换言之,有效对是具有高比率值的那些对,并且一个节点只能与最多比其最好选择差5%的另一节点成为伙伴。不具有有效伙伴的那些节点被投影到下一层,并且一个节点在每层只能被压缩一次。在压缩之后,迭代过程返回到930处的对划分数量的确定。随着矩阵大小的减小,因为节点可以包含多于一个来自层0(原始节点位于其中) 的节点,所以层0的所有依赖被投影到其余层。例如,通过层0节点a和b以及节点b和c 之间的所有依赖来将图8中层1的节点ab连接到节点Cd。因此,矩阵M在所有层自然地被填充。当完成粗化时,在709形成了多层图。在实施例中,在711重评估和改善该多层图。改善也是迭代过程,该迭代过程从最高层到最底层经过多层图的层,并且在每一层通过将一个节点移动到另一划分来试图找到更好的划分。可以在图8中看到移动的示例,其中在层2判决节点efg应当在线程0还是线程1。改善通过在粗化期间改善已经找到的“良好”划分来找到更好的划分。在每一次改善尝试中研究的划分不仅包括分解后的指令,还包括每一个线程中用于允许其控制独立执行以及需要的所有通信和ρ-slice的所有必要分支指令。因此,编译器是在改善过程中决定如何管理线程间依赖。在每一层,使用Kernighan-Lin(K-L)算法来改进划分。K-L算法工作过程如下 对于层1的每一个超节点n,计算使用目标函数将η移动到另一线程tid的增益F (n, tid)。 将超节点从一个线程移动到另一个意味着移动属于该超节点的所有层0的节点。然后,选择和移动具有最高F(n,tid)的超节点。重复该过程直到所有的超节点都被移动为止。注意,一个节点不能被移动两次。还注意,所有的节点均被移动,即使基于目标函数,新的解决方案比先前的解决方案更糟糕。这使得K-L算法胜过本地优化解决方案。在所有节点都被移动后,在该层完成了一轮操作。如果一层包含N个节点,那么一轮操作期间存在N+1个解决方案(划分)每节点移动为一个解决方案再加上初始的一个解决方案。选择这些解决方案中最优的解决方案。如果最优解决方案与初始解决方案不同 (即,最优解决方案涉及移动至少一个节点),那么在同一层执行另一轮操作。这是因为在当前层找到了更好的解决方案,因此在当前层探索其他可能的移动。注意,较高层中的移动拖动较低层中的节点。因此,当在层1找到解决方案时,该解决方案是层1-1的开始点。该方法的优点是可以在上层找到好的解决方案,其中存在少量节点并且K-L算法表现良好。 在低层中,对于K-L而言经常存在太多节点而不能从头开始找到好的解决方案,但是因为算法从已经是好的解决方案开始,所以低层的任务仅是提供细粒度提高。正常地,在高层获取大部分增益。因此,如果期望的话,可以使用启发式方法来避免遍历低层以减少算法的计算时间。因此,在给定层,通过使用目标函数、移动过滤和查看线程间依赖来获得益处或将每一个节点η移动到另一个线程。在实施例中,在用目标函数评估划分之前,执行移动过滤和线程间依赖评估。试图移动给定层的所有节点是高代价的,尤其是当PDG中有许多节点时。可以首先将节点过滤为在提高线程间工作负荷平衡和/或减少线程间依赖方面具有更高影响的节点。为了提高工作负荷平衡,关注于可以帮助工作负荷平衡的前K个节点。通过将分配给给定线程的动态指令的最大估计数量除以分配给给定线程的动态指令的总数来计算工作负荷平衡,其中通过估计的动态指令的总数来向给定线程分配动态指令。线程之间的好的平衡可以是.5。前L个节点用来减少线程间依赖的数量。在实施例中,L和K是10。在评估通过一次移动得到的划分之前,判决如何处理线程间依赖和是否应当复制一些指令,包括可能重新安排控制流。这些可以被显示传送,或者通过指令复制来预计算。 一些控制指令必须在线程中被复制,以使得所有需要的分支指令都在需要它们的线程中。在评估特定划分之前,算法决定如何管理线程间依赖。它们可以通过以下方式来实现1)使用显式的线程间通信(可以用显式的发送/接收指令或由指令提示来标记通信并且(至少在接收者端)引入线程间的同步);幻使用预计算片来在本地满足这些依赖(预计算片由在本地满足依赖所需的最少指令构成,并且可以将这些指令复制到其他核心中以避免所述通信);和/或3)它们被忽略,如果依赖很少出现那么推测没有依赖,并且如果出现可能的违反那么允许硬件检测可能的违反。传送依赖是相对昂贵的,因为所传送的值在产生者到达其对应核心的ROB的头部时要经过共享L2高速缓存(下文描述)。另一方面,过度复制指令可能最终会延迟推测线程的执行并且还会影响性能。因此,为每一个线程间依赖选择最合适的替换可能对性能具有影响。在实施例中,如果要复制的指令的加权量没有超过特定阈值,那么可以肯定地作出预计算依赖的判决。否则,通过显式通信来满足依赖。在我们的实验中已经发现值500 是好的阈值,但是在其他环境和实施例中其他值可能更合适。给定线程间依赖,如果估计用来在本地满足依赖的被复制的动态指令的量超过了阈值,那么算法可以决定显式传送该依赖。否则,可以构造该依赖的p-slice,并将其复制在目标线程中。为了合适地定义每一个区的有效阈值,通过多层图划分方法改变复制阈值和外层循环的展开因素来生成若干替换划分。然后,可以通过考虑预期加速来选择最终代码生成的最优候选。选择具有最大预期加速的候选。在预期加速相等的情况下,选择在线程间提供更好指令平衡的替换。在改善期间,每一个划分(线程化解决方案)必须被评估并与其他划分进行比较。 目标函数估计该划分在多核心处理器的区块上运行时的执行时间。在实施例中,为了估计划分的执行时间,使用通过剖析获取的区的20,000个动态指令流。使用该指令序列,基于考虑数据依赖、线程间通信、发射宽度资源(issue width resource)和目标核心的ROB的大小的简单性能模型,将执行时间估计为最长线程。在713,改善的完成产生表示代码区的优化版本的多个线程。在715,在已经生成线程之后,编译器创建用于执行这些线程的代码。该生成包括在合适点插入孵化指令和映射属于逻辑地址空间的不同区中的不同线程的指令,以及相应地调整分支指令偏移量。从分解后的指令流重构顺序执行如上文所讨论的,将原始单线程应用程序分解为若干推测线程,其中每一个线程执行原始顺序应用程序的全部工作的子集。尽管大部分时间可以并行地执行生成的线程, 但是程序的并行化有时可能是不正确的,因为它是推测地生成的。因此,执行这些线程的硬件应当能够识别和从这些情形中恢复。这种硬件机制依靠缓冲来保持推测状态(例如,使用显式的缓冲器、扩展有额外状态的存储器层级等),并依靠逻辑来确定分配给线程的指令的顺序次序。线程有效性和存储器一致性需要确定/重构推测多线程化执行的顺序次序。应当检测和纠正影响程序结果的顺序次序违反(线程有效性)。例如,加载操作读取失效值,因为产生正确值的存储操作在不同核心中执行。附加地,外部设备和软件应当看到推测线程的执行,如同以顺序次序执行原始应用程序一样(存储器一致性)。因此,存储器更新应当以与执行原始单线程应用程序时的次序一样的次序对网络互连可见。在一个实施例中,推测多线程化通过将全部迭代(或连续迭代的块)分配给每一个线程来并行地执行多个循环迭代。由一个核心在迭代i中执行的孵化指令创建开始在另一核心中执行迭代i+Ι的新线程。在该情况中,由孵化程序线程执行的所有指令比由孵化线程执行的那些指令更老。因此,重构顺序次序是直接的,并且以与线程被创建的次序相同的次序验证线程。在使用细粒度推测多线程化的实施例中,以指令粒度将顺序代码分解为线程,并且可以将一些指令分配给多于一个线程(称为被复制的指令)。在使用细粒度推测多线程化的实施例中,为了清楚的目的,假设要在两个核心中运行的两个线程,孵化指令被执行, 并且孵化程序和孵化线程开始取得并执行其被分配的指令,而在二者之间没有任何显式的次序。在图3中示出了这种范例的示例,其中在左边示出了原始顺序CFG和可能的动态流, 在右侧示出了可能的线程分解。注意,知道两个给定指令之间的次序并非无关紧要的。本文中的实施例关注在细粒度推测线程化的假设下重构存储器指令的顺序次序。 然而,这里介绍的描述可以外推到除了存储器之外的为任何其他处理器状态重构顺序排序。在并行执行中,出于许多原因,包括支持处理器一致性、调试或分析程序,能够重构原始顺序次序是有用的。用于进行此重构的有成本效益的机制可以包括以下特征中的一个或多个1)将简单POP标记(其可以仅是几比特)分配给静态指令的子集(不需要必须标记所有指令;仅标记对重构期望次序重要的子集);和幻即使指令已经被以很细的粒度(单独指令级)分解到为多个线程,仍然重构次序。如本文所使用的,“线程次序”是线程查看其自身被分配的指令的次序,以及“程序次序”是所有指令在原始顺序流中看起来的次序。可以重构线程次序,因为每一个线程按次序取得和提交其自身指令。因此,可以通过将由线程提交的所有指令放入到FIFO队列(在图11中说明的)中来满足线程排序线程次序中最老的指令是在FIFO的头部的指令,而最年轻的指令是在尾部的指令。这里,术语“次序”、“顺序次序”和“程序次序”可交换地使用。将指令任意分配到线程在指令必须属于至少一个线程的约束下在细粒度多线程化中是可能的。在存在被删除的指令(由硬件或软件优化删除的指令)的情况下,对本文讨论方案的扩展是直接的,因为要重构的程序次序是没有这些被删除的指令的原始次序。如图11所示,可以通过具有切换件来重构程序次序,所述切换件以由POP标记指定的次序选择线程排序FIFO队列。实际上,POP标记指示切换件应当在何时选择哪个FIFO。 每一个FIFO队列具有以线程次序分配给中线程的排序指令。通过将切换件从一个FIFO队列移动到由POP标记编排的另一个队列来以程序次序更新存储器。在给定的时间点,用相应的FIFO队列的第一个排序指令来更新存储器。然后将该指令从其队列中弹出,并且读取其POP值以将切换件移动到指定的FIFO队列。
应当知道第一个排序指令在顺序程序次序中按次序所处的位置,以便提供开始点。POP指针可以描述下一个排序指令的特性,并且第一个指令不具有任何前驱排序指令。 对于至少一个实施例,该开始标记被编码在寄存器中。可替换地,将第一个排序指令分配给静态FIFO队列。本领域的技术人员将认识到,用来定义第一个标记的许多其他实现在所描述的实施例的范围内。使用本文所描述的机制的实施例,可以以顺序程序次序更新存储器。然而,可以容易地将其他实施例扩展到其中通过将标记添加到静态程序来实施具体顺序的任何并行范例。对于各种实施例,标记排序指令的实体可以是编译器、动态二进制优化器(DBO) 或硬件块。对于一些实施例,用于将由POP标记指定的线程的逻辑标识符映射到物理线程 (OS线程、硬件线程……)的实体可以是OS或硬件块。如果在用户级或OS级定义标记,那么它们将通过指令编码的一部分为可见,或在对用户可见的一块硬件(存储器、特定的用户可见缓冲器等)中为可见。如果标记是由硬件定义的,那么假设该硬件知道程序的静态控制流。因此,对于在硬件中定义标记的至少一些实施例,使用硬件/软件混合方法来使用软件向硬件通知控制流。在没有控制流的代码段中(例如,基本块),可以确定存储指令的次序。在程序次序中在分配给线程1的下一个存储指令Sw之前的被分配给线程0的存储指令Si将具有为1的POP,表示下一个排序指令已经被分配给线程1。这些POP标记针对任何类型的代码 (集合工作、循环……)标记合适的次序。用两个POP标记分支指令,一个指示当采取分支指令时包含程序次序中下一个排序指令的线程,以及另一个指示当没有采取分支指令时包含程序次序中下一个排序指令的线程。最后,不是所有的存储指令和所有的分支指令都需要由POP标记,这取决于指令到线程的分配。通常,如果POP标记是指示从一个FIFO队列到另一个FIFO队列的改变的标记,那么只标记一些存储指令和一些分支指令一如果不存在附在排序指令的POP值,那么这意味着下一个排序指令位于相同的FIFO队列中(其已经被分配给相同线程)。然而,对于期望对指令进行同类标记的一个或多个实施例,可以标记所有的排序指令。对于本文描述的示例性实施例,假设不需要标记所有的排序指令。这是标记所有排序指令的实施例的超集, 因为该示例性实施例需要更复杂的逻辑。应当注意,“伪”(fake)排序指令可以被设计为没有架构副作用。可替换地,实施例可以使用确实有架构副作用的“伪”排序指令,只要这些副作用在控制之中。例如,如果 rax不是对应基本块中的存活期并且其在基本块中被重定义,那么“伪”排序指令可以是像 "and rax, rax,,的指令。分配给多个线程的指令是如上文所讨论的“被复制的指令”。可以以直接的方式处理对被复制的指令的管理。相同指令的单独实例之间的次序是不相关的,只要相对于剩余排序指令维持该次序即可。因此,可以选择这些实例间任何的任意次序。如果所需POP 标记的数量的确是个问题,则可以使用使所需POP标记的数量最小化的次序。例如,如果将指令I分配给线程0、1、2,那么这三个实例的有效次序是Ic^ Ip I2 (其中数字表示线程标识符)或12、I0,11,或任何其他次序,只要POP指针对于先前和即将到来的排序指令是正确的即可。
在优化区的代码生成期间,生成程序次序指针(POP)并且将其插入到优化代码中。在细粒度推测多线程化中,标记对重构期望的顺序次序有用的指令的相对次序。这些指令是“排序指令”。因为本发明的实施例尝试重构存储器排序以正确地更新存储器,所以存储指令和分支指令是排序指令的示例。可以用N比特(其中,N=「k^2M],M是线程的数量)标记排序指令,所述N比特对线程ID进行编码,以包含顺序程序次序中的下一排序指令。POP标记可以作为指令提示与指令编码在一起,或位于任何位置,只要系统知道如何将POP标记与指令进行映射即可。图12说明了用于确定优化区的POP标记的方法的实施例。在1201,解析该区的指令。该指令可以是优化区的第一个指令或在该第一个指令之后出现的某个指令。在1203,确定该指令是否是排序指令。如果该指令不是排序指令,那么它将不接收 POP标记,并且确定这是否是优化区的最后的指令。在一些实施例中,为所有指令创建POP 标记。如果指令不是最后的指令,那么在1209解析所述区的下一个指令。如果指令是排序指令,那么在1211,解析所述区,以获得该排序指令在顺序次序中的下一个排序指令。在1213,确定该后续排序指令是否属于不同线程。如果该后续排序指令的确属于不同线程,那么在1217产生指示线程切换的POP标记,并且在1205确定该指令是否是线程的最后的指令。如果该后续排序指令不属于另一线程,那么在1203找到的该先前的排序指令被标记为属于相同线程。在一些实施例中,该标记为“X”,而在其他实施例中,该POP标记保持与先前排序指令相同。在一些实施例中,存在关于何时分配不同POP值的预置规则。例如,在一些实施例中,给定分配给线程Ti的存储指令Si :1)如果在Si之后存在分配给线程L的存储指令I, 其中二者之间没有分支指令,Ti与L不同,那么将用POP值L标记Si ;2)如果在Si和分配给线程L的下一个分支指令B之间没有其他存储指令S,Ti与L不同,那么将用POP值Tj 标记Si ;以及3)其他情况,不需要标记存储指令Si。在一些实施例中,给定分配给线程Ti的条件分支指令Bi 1)如果下一个排序指令 (其可以是分支指令或存储指令)在该分支指令被采取时被分配给Tp Ti与L不同,那么用其采取的POP标记中的POP值Tj标记Bi,否则,不需要将采取的POP标记分配给Bi ;2)如果下一个排序指令(其可以是分支指令或存储指令)在该分支指令没有被采取时被分配给 Tj, Ti与Tj不同,那么用其的穿过(fallthru)POP标记中的POP值Tj标记Bi,否则,不需要将穿过POP标记分配给B”在一些实施例中,给定分配给线程Ti的无条件分支指令Bi,应用与条件分支指令相同的算法,但是只进行对采取的POP值的计算。在一些实施例中,给定Ti中的排序指令,其后是具有N条可能路径P1……Pn且在其间没有任何排序指令的间接分支指令,其中下一个排序指令属于不同于Ti的线程L的路径Pk将执行Ti中具有POP值L的“伪”排序指令。伪排序指令是其唯一目的是保持排序一致性的指令。它可以是专门指令或一般操作码,只要其不具有架构副作用即可。图13说明了使用具有集合活动的循环的示例。在该实施例中,可以重构程序次序并且排序指令是存储指令和分支指令。为了简单,仅示出了排序指令,但是本领域的技术人员将认识到存在其他指令。图13中说明的排序指令被标记以指示它们是被分配给线程0还是1。条件分支指令具有两个POP标记,而存储指令和无条件分支指令仅具有一个POP标记。POP标记“X”意味着该标记是不需要的。POP标记“? ”意味着未知,因为没有示出完整的控制流。在右下部分,示出了在执行循环两次时如何重构程序次序,每一个迭代沿着集合活动的不同路径。为了简单,假设代码被分解为两个线程,但是此机制意图以任意数量线程工作,为POP标记提供了足够的比特。此外,仅描述了排序指令。存储指令S5被分配给两个线程并且具有两个POP标记。所有其他存储指令具有一个POP标记。无条件分支指令也具有一个POP标记(采取的标记T)。条件分支指令具有两个POP标记一个是采取的(T)以及一个是未采取的(NT)。第一个指令(存储指令Si) 被分配给线程0并且具有为1的POP值,因为顺序程序中下一个排序指令S2被分配给线程 1。存储指令S3不需要POP值(因此为“X”),因为顺序次序中的下一个排序指令被分配给相同线程0。因此,不需要编码指示从一个FIFO队列到另一个FIFO队列的改变的标记。条件分支指令Bl不需要采取的POP值,因为在采取分支指令时下一个排序指令被分配给相同线程0。然而,Bl需要未采取的POP值,因为在不采取分支指令时下一个排序指令S6被分配给其他线程。在该情况下,标记是1。作为另一特定情况,存储指令S5被分配给两个线程 (它已经被复制)。在该情况下,其两个实例之间的次序是不相关的。在附图中,通过不将 POP指针分配给线程0中的存储指令S4和分别地将POP指针1和0分配给线程0和1中的 S5实例,线程0中的S5实例在线程1中的S5实例之前进行。然而,可以存在其他方式,但是POP值会不相同。图13的右下部分说明了假设程序沿着由{基本块A、B、C、E、B、D、E……}构成的执行流进行的情况下,如何通过使用POP指针将排序指令进行相关。在附图的该部分,从框 X的中间离开的线表示“在执行X中的指令之后”,而到达框X的开头的箭头线表示“在执行 X中的指令之前”。该程序流包括运行循环两次,其中经过循环的每一次迭代沿着集合活动的不同路径。因此,全局次序是 Si、S2、S3、Bi、S4、S5。、S5” B2、S7、S8、B4、S2、Bi、S6......。上文描述了标记已经任意地分配给线程的存储指令和分支指令以便按照合适顺序程序次序更新存储器的实施例。对于至少一个实施例,在指令级构建分解后的线程,耦合核心的执行以提高多核心设计中的单线程性能。下文详细讨论了支持在编译时生成的线程的执行的硬件机构的实施例。这些线程产生于对原始应用程序的细粒度推测分解,并且它们在修改的多核心系统下执行,所述修改的多核心系统包括(1)用于检测线程间违反的机构;(2)用于重构原始顺序次序的机构;以及(3)用于处理误推测的检查点和恢复机构。实施例通过以细粒度方式分解单线程应用程序来加速在多核心系统中的所述单线程应用程序。编译器负责将来自单线程应用程序或并行应用程序的顺序区的指令分布到可以在支持推测多线程化的多核心系统中并行执行的线程中。本领域的技术人员将认识到,这可以扩展到重构任何类型的次序给定的并行代码。一些替代实施例包括但不限于1) 重构控制流(排序指令仅有分支指令);2)重构整个程序流(所有指令都是排序指令并且应当具有分配的POP标记);幻重构存储器流(分支指令、加载指令和存储指令是排序指令);4)对并行程序的指令强制实施特定次序,以便对其进行验证、调试、测试或调整(从已经并行化的代码开始,用户/编译器/分析工具将POP标记分配给指令,以在指令间强制实施特定次序并在每一点查看程序的该顺序视图的情况)。在图14中说明了使用POP标记重构流的方法的实施例。如上文所详述的,用来重构程序流的排序指令是存储指令和分支指令。在1401,使用多个核心来推测地执行程序。在该执行期间,每一个线程的指令在其被分配到的线程中被本地引退,并且由MLC经由ICMC 被全局引退。在1403,发现要求恢复或重构流(程序、控制、存储器等)的条件。例如,发现执行优化区的核心之间有不一致的存储器值。当然,可以由于其他原因重构流,例如不是在执行期间发现的条件的微调。在1405,从合适的FIFO (这些FIFO在下文中称为memFIFO或存储器FIFO队列,并且随着程序的执行而被填充)中获取第一个(最老的)排序指令。可以由上文描述的一种方式来指示该指令的位置。使用前面讨论的具有集合工作的循环作为例子,第一个指令是存储指令si并且它属于线程0。因为指令被引退,所以包括其POP值的指令被存储在合适的FIFO中,或存储在可由重构流的机构识别的另一位置。在1407,读取该指令的POP值。再次参考图4,存储指令si的POP标记值是“1”。在1409,确定这是否是最后的排序指令。如果是,则流已经被确定。如果不是,则在1411确定是否切换FIFO。如果POP值与先前获取的指令的线程不同,那么进行切换。在前面的例子中,读取值“1”指示下一个程序流指令属于线程1,与存储指令si所属的线程0 不同。如果值是X,则它指示下一个程序流指令属于相同的线程并且将没有FIFO切换。在先前的例子中,这在存储指令s3之后获取分支指令而发生。如果要进行切换,那么选择由POP值指示的FIFO,并且在1413读取该FIFO中的最老的指令和其POP值。如果不进行切换,那么不切换FIFO并且在1415从FIFO中读取下一个最老的指令。读取指令和基于所读取的POP值切换FIFO的过程继续进行,直到重新创建了程序流或FIFO被耗完为止。在实施例中,如果FIFO被耗完,则从另一存储位置(例如主存储器)补充FIFO。在实施例中,通过使用流来确定重新开始执行程序的位置来继续程序的执行。在一个实施例中,下文描述的ICMC执行上面的方法。在另一实施例中,软件例程执行上面的方法。多核心推测多线程化处理器和系统的实施例图15是说明在其上可以使用线程排序重构机制的实施例的多核心系统的实施例的框图。为了便于参考而进行了简化,图15的系统可以具有额外的元件,但是这些元件没有在图15中明确地说明。如上文所讨论的,在细粒度SpMT生态系统中,程序被划分为在一个或多个处理核心上执行的一个或多个线程。这些处理核心分别处理一线程,并且合并该处理的结果以创建与如同该程序作为单个线程在单个核心上运行一样的结果(但是所述划分和/或并行执行应当更快)。在由不同核心进行的这种处理期间,执行的状态是可推测的。当线程到达其最后的指令时,它们同步退出优化区,推测状态变成非推测状态,并且执行继续以一个单线程继续进行,区块恢复为针对该程序的单核心模式。下文结合图15更详细地描述了本文使用的“区块”。一般地说,区块是工作来并发地执行一组原本为顺序指令的一组指令的不同部分的两个或更多核心的组(其中,“不同”部分还可以包括被复制的指令)。图15说明了逻辑地划分为两个区块1530、巧40的多核心系统。对于至少一个实施例,系统的处理核心1520基于x86架构。然而,处理核心1520可以是任何架构,例如PowerPC等。对于至少一个实施例,系统的处理核心1520执行无序指令。然而,这种实施例不应当作为限制。本文讨论的机制可以等同地应用到执行有序指令的核心。对于至少一个实施例,区块1530、巧40的一个或多个实现具有专用第一级写透过数据(write-through) 高速缓存(“DCU,,)和指令高速缓存(“IC”)的两个核心1520。这些高速缓存,IC和DCU, 可以通过拆分事务总线1560耦合到共享拷贝回(copy-back)L2高速缓存1550。最后L2高速缓存1550经由另外的互连网络1570耦合到主存储器1580和其他区块1530、巧40。L2高速缓存1550称为MLC( “合并级高速缓存” (Merging Level Cache))并且是区块的核心之间的共享高速缓存。对于图15中说明的实施例,第一级共享高速缓存是二级高速缓存。在该合并级高速缓存处执行处理核心(线程)之间的合并。然而对于其他实施例,L2高速缓存不需要必须是区块的核心之间的合并级高速缓存。对于其他实施例,MLC可以是位于存储器层级的任何级的共享高速缓存。对于至少一个实施例,图15中说明的区块1530、1540具有两个不同的操作模式 单核心(正常)模式和协作模式。区块中的处理核心1520在区块处于单核心模式时执行常规线程,并且在区块处于协作模式时它们执行来自同一分解后的应用程序的推测线程(每一个核心中一个线程)。应当注意,应当在具有所述线程的区块的协作模式中执行优化代码。因此,当这两个线程开始运行优化代码时,孵化指令触发核心从单核心模式到协作模式的转换。当两个推测线程在协作模式激活的区块(例如,1530或1540)上运行时,它们之间的同步在必须通过显式通信来满足线程间依赖时发生。然而,通信可能暗示仅在使用者方进行同步。常规存储器或专用逻辑可以用于这些通信。正常执行模式或正常模式(或单模式)是指当一个处理核心正在执行非推测多线程化代码的同时,区块中的另一处理核心处于空闲或在执行另外的应用程序。例如,区块 1530的处理核心0在执行非推测多线程化代码而核心1处于空闲。推测执行模式或推测模式是指两个核心协作来执行推测多线程化代码。在正常和推测模式中,每一个核心独立地取得、执行和引退指令。在推测模式中,以规则间隔采取检查点(后面讨论),以使得如果发现存储器违反可以回滚到先前的一致状态。在一个核心引退孵化指令(假设其他核心处于空闲,否则执行恢复到正常状态) 后,处理核心从正常模式转换到推测模式。另一方面,在应用程序跳到还没有分解为多个线程的代码区或当检测到存储器违反时,处理核心从推测模式转换到正常模式。当在一个核心中执行的加载指令需要在另一核心中执行的存储指令生成的数据时发生存储器违反。这发生的原因是系统不能保证分配给不同线程的指令的执行间的次序。在出现存储器违反时,由ICMC生成的消耗信号被传播到所有的核心和高速缓存,状态回滚到先前的一致状态并且执行恢复到正常模式。为了更新架构存储器状态和检查原始顺序程序次序中可能的存储器违反,进行原始程序次序的重构。在实施例中,这通过下述方式来实现将每一个处理核心的所有在本地引退的存储器指令放到对应的FIFO结构中(这在下文更详细地讨论),并借助于一些指令标记以原始顺序程序次序访问和移除这些队列中的头指令。当指令在处理核心中引退时, 这意味着其是该处理核心中最老的指令并且将其放到其对应的FIFO的尾部(称为本地引退)。存储器层级不断地获取系统中最老的指令(位于任何一个FIFO的头部)并且以顺序
20程序次序访问MLC和其相关联的比特(称为指令的全局引退)。图16说明了在协作模式中操作的区块的示例。在该附图中,指令3和4正分别地在核心1和0中本地引退。ICMC已经按程序次序全局地提交了指令0、1和2并且将相应地更新MLC。ICMC还将检查存储器违反。核心间存储器一致性模块(ICMC)支持分解后的线程,并且可以控制以下中的一个或多个1)分类存储器操作以使得由分解后的应用程序进行的改变对其他区块可见,如同其被顺序地执行一样;幻识别在该区块的核心上运行的线程之间的存储器依赖违反;3) 管理存储器和寄存器检查点;和/或4)在发生误推测、异常或中断的情况下,触发核心中的回滚机制。 对于至少一个实施例,ICMC对处理核心的干涉极少。因此,在处理协作模式中,核心大部分时间以去耦合方式从推测线程中取得、执行和引退指令。然后,在指令引退之后将指令的子集发送到ICMC,以便进行对执行的验证。对于至少一个实施例,由ICMC考虑的指令集被限制为存储器和控制指令。当在协作模式中执行时,ICMC重构已经被任意地分配给推测线程的存储器指令的原始顺序次序,以便检测存储器违反和正确地更新存储器。这种次序是由ICMC使用称为程序次序指针(POP)比特的标记进行重构的。POP比特由编译器包括在存储器指令和某些无条件分支指令中。用于推测多线程化的示例性存储器层级图17是说明根据本发明的至少一个实施例的支持推测多线程化的示例性存储器层级的框图。在操作的正常模式下(非推测),存储器层级充当常规层级(即,传统的存储器层级协议(MESI或任何其他))、进行传播以及根据需要使高速缓存行无效。图17的层级包括一个或多个处理核心(核心1701和170 。层级的每一个处理核心具有在附图中标示为“Li”的专用第一级数据高速缓存单元(DCU) 1705。处理核心还共享至少一个更高级的高速缓存。在所说明的实施例中,处理核心1701和1703共享第二级数据高速缓存1709和末级高速缓存“L3” 1711。层级还包括诸如主存储器1713的存储器和诸如硬盘、光学驱动器等的其他存储设备。附加地,层级包括称为核心间存储器一致性模块(ICMC) 1715的部件,其负责控制当区块内的核心在协作模式下执行时这些核心的活动。 该模块可以是电路、软件或其组合。下面详细地讨论存储器层级的这些示例性部件的每一个。数据高速缓存单元(D⑶)当在正常模式操作时,DCU是写透过的并且作为常规Ll数据高速缓存进行操作。 在推测模式中,它们既不是写透过的也不是写回的,并且被取代的脏行被抛弃。此外,不传播修改的值。这些从正常模式的改变允许版本化(versioning),因为合并和最终正确的值将会位于稍后将讨论的合并级高速缓存(“MLC”)中。在实施例中,通过包括每行版本化比特(“V”)来扩展DOT,所述版本化比特仅在推测模式和在模式间转换时使用。该比特标识在执行当前推测多线程化代码区时已经被更新的行。取决于实现,在推测模式中,当行被修改时,将其版本化比特设置为1以指示改变。 当然,在其他实现中,版本化比特值0可以用来指示与指示没有改变的值1 一样的情况。当从正常模式转换到推测模式时,V比特被重置为指示没有进行改变的值。当从推测模式转换为正常模式时,将具有设置为指示改变的行的版本化比特的所有行修改为无效并且重置版本化比特。这种转换在标记区的结束的指令全局地引退时或在由ICMC生成销毁信号(下文讨论销毁信号)时发生。在推测模式中,每一个D⑶独立地工作,并且因此每一个具有每段数据的可能版本。因此,不将修改的值传播到更高级的高速缓存。MLC是在不同DCU高速缓存行值之间执行合并所在的级,并且这遵循原始顺序程序语义来进行,如前面部分所解释的。当从推测模式转换为正常模式时,有效行仅位于MLC。因此,在DCU中清理了推测行。将存储操作发送到ICMC,ICMC负责当存储操作全局地提交时以原始次序更新L2高速缓存。合并级高速缓存在实施例中,L2高速缓存1709充当作为处理核心之间的共享高速缓存的MLC。然而,对于其他实施例,L2高速缓存不需要必须是处理核心之间的合并级高速缓存。对于其他实施例,MLC是位于存储器层级的其他级的共享高速缓存。如所说明的,通过包括每高速缓存行的推测(“S”)比特和每块的两个最后版本 (“LV”)比特(当然,对于更多处理核心将有更多LV比特)来从传统的高速缓存扩展MLC。 块是检测两个推测线程之间的存储器歧义消除(并且因此,存储器违反)的粒度。其范围可以介于字节和行的大小之间,并且是精确度和区之间的权衡。S比特指示高速缓存行包括推测状态。当执行检查点时其被清理并且如下文所讨论的存储器又安全了。另一方面,LV比特指示哪个核心执行了对每一个块的最后改变。例如,在一个实施例中,行的第一块的LV值“01”指示核心1是对该块执行改变的最后核心。 当存储指令全局地引退时设置这些比特,并且不清理它们直到转换回正常模式为止(与在检查点之间被清理的S比特相反)。按照原始程序次序执行全局引退。此外,存储指令被标记以识别它们是否被复制。这有助于确保系统能够捕获存储器违反。缺省设置所有行的 LV比特为指示从任何核心进行的读取都是正确的。图18中说明了当存储指令在优化模式中全局地引退时要进行的动作的方法的实施例。在1801,确定存储指令是否在MLC中未命中(即,为L2高速缓存未命中)。如果存储指令是未命中,则在1803停止全局引退直到该行存在于MLC中行为止。如果存储指令已存在于MLC中(或当该行到达MLC时),则在1805确定该行是否是脏的。如果它是具有非推测数据的脏的行(例如,S比特未设置),则在1807将行写回到存储器层级中的下一级。 否则,在1809修改数据并且将S比特设置为1。在1811确定存储指令是否被复制。如果存储指令未被复制,那么在1813,针对执行存储指令的核心将对应于每一个修改的块的LV比特设置为1,并且针对其他核心将LV比特设置为0。如果存储指令被复制,则在1815作出另一个确定。即,确定存储指令是否是第一个拷贝。如果存储指令被复制并且其是第一个拷贝,那么在1813,针对执行存储指令的核心将对应于每一个修改的块的LV比特设置为1,并且针对其他核心将LV比特设置为0。如果存储指令被复制并且其不是第一个拷贝,那么在1817,针对执行存储指令的核心将对应于每一个修改的块的LV比特设置为1,并且其他核心保持不变。图19中说明了当加载指令将在优化模式中全局地引退时要进行的动作的方法的实施例。在1901,确定加载指令是否在MLC中未命中。如果它是未命中,那么在1903将填充请求发送到存储器层级的下一级并且正确地全局引退加载指令。
如果它是命中,那么在1905确定是否有任何对应块的LV比特是0。如果对于对应核心的这些LV比特中任意一个具有为0的值,那么这意味着该特定核心没有生成数据的最后版本。因此,在1907生成销毁信号,回滚状态,并且将系统从推测模式转换为正常模式。 否则,在1909正确地全局引退加载指令。此外,在一些实施例中,在存在其他事件时MLC的行为如下1)当满意地完成当前检查点(检查点的最后指令正确地全局引退)时,将所有行的推测( 比特设置为0,注意, 不清理LV比特直到执行从推测模式转换为正常模式为止;2)当从MLC中取代具有设置的 S比特的行时,生成销毁信号。这意味着当前高速缓存配置不能保持自从上一检查点后完整推测存储器状态。因为规则地采取检查点,所以从我们的仿真中来观察,这很少发生。然而,如果关注于此,那么可以使用改善替换算法(其中给予推测行低优先级)或牺牲高速缓存来减少销毁量;幻当从推测模式转换为正常模式时,除了清理所有的S比特之外,还清理 LV比特(设置为1);以及4)当产生销毁信号时,具有被设置为1的推测比特的所有行被设置为无效(和所有D⑶中发生的一样)并且S比特被重置。此外,LV比特被清理(设置为 1)。核心间存储器一致性模块(ICMC)除了通常的高速缓存级别,存在下文更详细讨论的其他结构。这些额外的结构构成核心间存储器一致性模块(“ICMC”)。ICMC和附于D⑶和MLC的行的比特不在正常模式中使用。ICMC接收排序指令并且通过三种结构处理它们1)存储器FIFO ;2)更新描述表 (UDT);以及3)寄存器检查点逻辑(见图20)。ICMC对排序指令进行分类以使得由多线程化的应用程序进行的改变对其他区块可见,如同它是顺序地执行一样,并且检测在区块的核心上运行的线程之间的存储器依赖违反。区块中的ICMC和存储器层级允许在协作模式中运行的每一个核心更新其自身存储器状态,同时仍然提交相同状态和避免推测更新在区块外部传播,所述相同状态为将通过允许多个Ll高速缓存中的相同行的不同版本生成原始顺序执行。附加地,寄存器检查点允许回滚到先前的状态以纠正误推测。ICMC实现称为存储器FIFO(memFIFO)的每核心一个FIFO队列。当核心引退排序指令时,该指令存储在与核心相关联的memFIFO中。ICMC基于POP比特处理和从memFIFO 移除指令。最后提交的指令的POP比特的值识别要提交的下一个指令位于的memFIFO的头部。注意,当指令成为系统中原始顺序次序中最老的指令时,ICMC提交这些指令。因此,这是存储操作可以更新共享高速缓存级别并且在区块外部可见的次序。在下文讨论期间,当指令成为核心中最老的指令并且引退发生时该指令引退。相反,当因为指令是区块中最老的指令而由ICMC处理该指令时,指令全局地提交(或简称提交)。MemFIFO条目可以包括1)标识指令类型(加载指令、存储指令、分支指令、检查点)的类型比特;2)POP值;3)存储器地址;4)描述存储器地址的大小的比特;5)用于存储值的比特;以及6)用于标记被复制(r印)的指令的比特。标记被复制的指令以避免使ICMC 检查依赖违反。MemFIFO允许每一个核心独立地取得、执行和引退指令。仅在核心阻止其他核心引退指令时发生同步。核心可以最终填满其memFIFO,然后停止直到其引退的指令的一个或多个离开memFIFO为止。这在要提交的下一个指令必须由不同核心执行且该指令还没有引退时发生。
高速缓存一致性协议和区块中的高速缓存模块被稍微地修改以便允许多个第一高速缓存级别中相同行的不同版本。此外,还需要一些改变来避免推测更新在区块外部传播。当更新行并且因此每一个Ll高速缓存可以具有相同数据的不同版本时,Ll数据高速缓存不会使处于协作模式的其他Ll高速缓存无效。如上文所讨论的,在存储指令在一个核心中执行并类似于Iref}更新该行时设置该核心中该行的V比特。不将针对Ll的这些推测更新传播(写透过)到共享L2高速缓存。存储操作被发送到ICMC并且将在它们提交时更新L2高速缓存。因此,当从Ll取代其V比特被设置的行时,抛弃其内容。最终,当核心从协作模式转换为单核心模式时,使V比特被设置的所有Ll行无效,因为正确的数据位于 L2 禾口 ICMC 中。当存储指令提交时,其更新对应的L2行并且将其S比特设置为1。这种S比特描述行在上一检查点之后已被修改。一旦采取新的检查点,清理S比特。如果发生误推测,那么线程回滚并且使S比特被设置的行无效。因此,当推测存储指令要更新非推测脏行时, 必须将该行写回到下一存储器级别,以便在存储器层级的某位置具有行的有效的非推测版本。因为推测状态不能超出L2高速缓存,所以从L2逐出标记为推测(S)的行意味着回滚到先前的检查点以恢复执行原始的应用程序。另一方面,LV比特指示什么样的核心具有特定块的最后版本。当存储指令提交时, 它将属于该核心的修改的块的LV比特设置为1并且重置其余的LV比特。如果存储指令被标记为被复制(由两个核心执行),那么两个核心将都具有最新的拷贝。在该情况中,将LV 比特设置为11。当全局提交加载指令时,检查这些比特以查看执行该加载指令的核心是否是具有数据的最后版本的核心。如果表示执行了加载指令的核心的LV比特是0并且其他核心的该比特是1,那么检测到违反并且销毁这些线程。这是因为每一个核心独立地取得、 执行和引退指令并且Ll高速缓存也彼此去耦合地工作,系统只能够保证如果正确值已在相同核心中生成则加载指令将读取正确值。UDT是描述由位于memFIFO队列中的存储指令(还没有全局地引退的存储指令) 更新的L2行的表。对于至少一个实施例,UDT被构造为高速缓存(全相关的,例如,32个条目),其中每一个条目识别一行并且具有每个线程的以下字段有效比特(V)和FIFO条目 id,其是指向该线程的FIFO条目的指针。只要仍然有等待更新该行的一些存储指令,UDT就延迟从共享L2高速缓存到Ll高速缓存的填充。这帮助避免用来自L2的失效行填充Ll。特别地,延迟对给定核心的Ll的填充直到在memFIFO中不再有等待的针对该特定核心的存储指令(UDT中没有针对行标记的任何条目)为止。因此,如果UDT中存在针对请求的行(其具有对应于该核心的、被设置为1的有效比特)的条目,DCU填充位于延迟请求缓冲器中。 一旦该有效比特被复位,那么将处理这种填充。不需要等待由其他核心对该相同行的存储, 因为如果存在存储器依赖,那么LV比特将已经检测到它,并且如果两个核心访问相同行的不同部分,那么ICMC将在L2适当地合并更新。在推测模式中,当存储指令在本地引退并且添加到FIFO队列时,更新UDT。让我们现在假设条目是可获得的。如果不存在针对该行的条目,那么将创建一个新的条目,并且填充标签,设置该线程的有效比特,用其中放置存储指令的FIFO条目的ID更新对应的FIFO 条目id,并且复位对应于其他核心的有效比特。如果已经存在针对该行的条目,那么设置该线程的有效比特并且用在其中放置存储指令的FIFO条目的id更新对应的FIFO条目id。
当存储指令全局地引退时,它在UDT中找到其对应的条目(它总是命中)。如果该核心的FIFO条目id与正在引退的存储指令的UDT中的条目相匹配,那么将对应的有效比特设置为0。如果条目的两个有效比特都是0,那么释放UDT条目并且其可以再用于即将来临的请求。当从推测模式转换为正常模式时,清理UDT。为了避免溢出,实现了 UDT “停止和进行”机制。当UDT中可用条目的数量少并且存在溢出的风险时,向核心发送信号以阻止它们在本地引退新的存储指令。注意,不能实现基于信用的控制,因为UDT是可以从若干核心进行写入的共享的结构。此外,为了避免死锁和确保向前进行,核心不能使用多于N-I个UDT条目,其中N是条目的总数。在这种情况中, 阻止该核心在本地引退新存储指令。如果其他线程是执行系统中最老的指令的线程,则这给该其他线程的进行留下了空间,。UDT中的条目具有以下字段标识L2高速缓存行的标签,和针对每一个核心的附于memFIFO条目id的有效比特。memFIFO条目id是更新该行的最后存储指令的该特定 memFIFO的条目号。每当将存储指令附加到memFIFO时更新该字段。如果存储指令对在UDT 中没有条目的行进行写入,那么它分配新的条目。相反,如果由memFIFO条目ID指向提交的存储指令,那么将其有效比特设置为假;并且如果两个有效比特都是假,那么从UDT移除该条目。ICMC还可以包括下文详细描述的寄存器检查点逻辑。对于在其中上移或下移核心间专用/共享接口的实施例,上文讨论的结构(例如,ICMC和S、V、和LV比特)可以位于存储器层级中的其他位置。因此,可以在任何特定的存储器子系统配置中使用本文描述的实施例。计算推测地并行化代码的架构寄存器状态本文讨论的重构方案的实施例包括用于在特定推测是错误时将状态回滚到正确状态的寄存器检查点。检查点的频率与性能具有重要的关系。检查点越频繁,由于误推测产生的开销越低,但是用于创建检查点的开销越高。在该部分中描述的方案能够针对其计算被拆分并且分布到多个核心的单线程代码采取架构寄存器状态的频繁检查点,而具有极低的开销。用于寄存器检查点的机制的至少一个实施例允许核心引退指令、回收执行资源并即使在其他核心停止时仍然保持继续向前进行。该部分中描述的寄存器检查点允许安全的早期寄存器回收,以使得它允许向前进行而对寄存器文件增加极少的压力。对于本发明的至少一个实施例,非常频繁地采取检查点(每几百条指令),以使得当由于中断或数据误推测导致需要回滚时浪费的工作量非常少。因此,所公开的机制的实施例使得有可能执行更积极的优化,因为降低了数据误推测的开销。与之前的推测多线程化方案相比,本发明的实施例不需要生成完整架构状态;替代地可以由多个核心部分地计算架构状态。这允许更灵活的线程化,其中以比在传统推测多线程化方案中更细的粒度将指令分布在核心中。根据本发明的至少一个实施例,核心不必同步来在特定点获取架构状态。本技术虚拟地无缝合并和构造架构状态。本发明的实施例创建R0B(重排序缓冲器),其中以它们应当提交的次序存储由核心引退的指令,以具有与执行原始单线程应用程序相同的结果。然而,因为线程异步地执行,所以该ROB中的条目不是顺序分配的。替代地,存在这样的区,其中既不知道分配到该区的指令的数量也不知道分配到该区的指令的类型。如果例如核心0在执行应当在从核心 1执行了指令之后提交的代码区,则这种情形可能发生。在该情况中,在该概念性ROB中,在已经由核心1引退的指令和由核心0引退的属于核心1还没有执行/引退的那些指令的指令之间存在间隙。图21说明了检查点机制的ROB的至少一个实施例。在该ROB中,GRetireJ)指向由核心0引退的最后指令,GRetire_l指向由核心1引退的最后指令。如能够看到的,核心 0在核心1之前,从而ROB中GRetire_0和GRetire_l之间存在间隙(示出为阴影区)。在给定时间,完整检查点具有指向针对每一个逻辑寄存器的值位于其中的寄存器文件中的物理寄存器(在核心0或核心1中)的指针。在每次每一个核心引退预定量的指令时由该核心采取检查点(ckp)。注意,由引退系统中最年轻的指令的核心采取的检查点是部分检查点。它不能够确保该核心实际生成用于该执行点的架构状态,直到其他核心引退了比所采取检查点更老的所有指令为止。相反,由不引退系统中最年轻的指令的核心采取的检查点是完整检查点,因为它知道比其他核心已经执行的检查点更老的指令。因此,它知道架构值的每一个此时的位置。 该例子中核心0在特定数量的指令之后还采取周期性的检查点(尽管他们是部分的)的原因是,这些部分检查点未指向的所有物理寄存器被回收。该特征允许核心向前进行,而对其寄存器文件增加极少的压力。此外,核心1 一到达该检查点,它就确保包括由核心0产生的属于架构状态的值的寄存器此时被回收,以使得可以与来自核心1的信息一起构建完整的检查点。此外,在核心0中分配的不属于该检查点的那些寄存器因为被核心1覆写所以也可以被释放。只要引退不是系统中最年轻的指令的核心(例子中的核心1)采取更年轻的完整检查点,那么就可以释放检查点并且回收其物理寄存器。然而,可能发生线程化方案要求在指令成为系统中最老的指令时执行的一些验证。因此,比该指令老的检查点用于在验证失败的情况下回滚到那里。在该情形中,在具有相关联的完整检查点的另一指令成为系统中最老的指令并且被适当地验证之后,释放完整检查点。由线程执行的每一个指令具有相关联的IP_orig以在恢复该指令相关联的检查点时进行跳转,其中所述IP_orig是原始代码中指令的指令指针(“IP”)。执行的指令的 IP和其IP_orig之间的转变存储在存储器中(在实施例中,编译器或动态优化器负责创建该转变表)。因此,只有由于数据误推测或中断而导致恢复检查点时,执行将在与恢复的检查点相关联的原始单线程应用程序的IP_orig处继续。应当注意,前面的核心和后面的核心不总是相同的,并且该角色可以取决于原始应用程序被调整成线程的方式而随着时间变化。在给定时间,完整检查点具有指向针对每一个逻辑寄存器的值位于其中的寄存器文件中的物理寄存器(在核心0或1中)的指针。当已经全局地提交所有的指令并且更年轻的检查点成为完整的检查点时,可以释放检查点并回收其物理寄存器。当发现由编译器插入的CKP指令并且自从最后检查点(CKP_DIST_CTE)之后已经全局地提交至少最少数量的动态指令时,采取检查点。图15中示出了该逻辑。该CKP指令具有与检查点一起存储的恢复代码的IP,以使得当中断或数据误推测发生时,将由先前的检查点指向的值拷贝到将恢复应用程序的执行的核心。图22是说明寄存器检查点硬件的至少一个实施例的框图。对于至少一个实施例, 所说明的寄存器检查点硬件的一部分位于区块的核心之间/之中。例如,在实施例中,逻辑门在区块的外边并且LREG_FIF0是ICMC的一部分。在实施例中,ICMC包括以下的一个或多个1)每核心的FIFO队列(LREG_FIF0) ;2)每LREG_FIF0的指针集合;以及3)每LREG_ FIFO的检查点表的池。例如可以使用诸如多路复用器(MUX)的其他逻辑替代NOR门。写入逻辑寄存器的引退的指令分配并进入LREG_FIF0。图22说明了条目的构成 1)名称为ckp的字段,其中,如果存在与该条目相关联的架构状态检查点,则所述字段被设置为1 ;幻存储指令覆写的逻辑寄存器的标识符的LDest字段;以及幻用于标识包括程序次序中下一个指令的线程的POP字段。POP指针是用于识别来自不同线程的指令应当引退的次序以获得与顺序地执行单线程应用程序相同的结果的机制。然而,本发明能够与可以用来识别从单线程应用程序生成的不同线程的指令之间的次序的任何其他机制一起工作。指针集合包括1)指向在其中新引退的指令分配由该寄存器指向的条目的LREG_ FIFO的第一个未使用的条目的每核心RetireP指针;2)指向用来按次序解除分配LREG_ FIFO条目的LREG_FIF0中的最老分配的条目的每核心CommitP指针;以及幻指向按次序经过LREG_FIF0时的最后条目以构造完整检查点的每核心Gretire指针。还说明了 CHKP_ Dist_CTE寄存器或常量值。该寄存器定义LREG_FIF0中两个检查点之间多个条目的距离。 还说明了在最后检查点之后计数LREG_FIF0中分配的条目的数量的每LREG_FIF0的Inst_ CNT寄存器。每LREG_FIF0的检查点表的池定义正在处理的检查点的最大数量。每检查点的每一个池作为按次序分配和回收检查点的FIFO队列进行工作。检查点包括在其中创建检查点的指令的IP、回滚代码的IP和用于架构中每一个逻辑寄存器的条目。这些条目的每一个具有针对该特定逻辑寄存器在检查点之前生成的最后值所位于的物理寄存器 (“PDest”);如果PDest标识符与先前检查点中的PDest不同则被设置为1的覆写比特 (“0”);以及如果架构状态为逻辑寄存器位于另一核心则被设置为1的远程比特(“R”)。 下文详细地描述了这些比特。图22还说明了位于应用程序存储空间中的数据结构,所述应用程序存储空间由 IP和来自多个线程中的一个的指令的线程id索引并且将其映射到原始单线程应用程序的 IP中,以在恢复该线程的特定IP中的架构状态时进行跳转。每当核心引退产生新的架构寄存器值的指令时,该指令分配在对应的LREG_FIF0 中的新的条目。然后,针对它覆写的逻辑寄存器读取激活检查点中的条目。当0比特被设置时,回收存储在条目中的PDest标识符。然后,0比特被设置并且R比特被复位。最后, 将PDest字段更新为引退的指令分配的物理寄存器的标识符。一旦已经更新了激活检查点,那么^istCNT计数器减少,并且当其是0时,将当前检查点拷贝到下一个检查点,以使得该下一个检查点成为激活检查点并且重置该新的激活检查点中的所有0比特并且再次将 InstCNT 寄存器设置为 CKHP_Dist_CTE。如果GRetire指针与RetireP指针匹配,那么这意味着该指令不是系统中最年轻的指令,所以它应当像图14的示例中的核心1 一样运作。因此,检查POP比特并且当它指向其他核心时,使用其他核心的GRetire指针来经过其他核心的LREG_FIF0直到找到具有
27POP指针指向的条目为止。对于经过的每一个条目,读取LDest的值并且更新激活检查点如下当0比特被设置时,回收PDest中写入的物理寄存器标识符。然后,重置0比特,设置R 比特,并且更新PDest。如果条目具有被设置为1的ckp比特,那么用激活检查点的信息来完成部分检查点。该合并涉及回收在其中设置部分检查点的0比特和重置激活检查点的R 比特的部分检查点中的所有PDest。然后,通过重置这些条目的0比特来更新激活检查点。 另一方面,如果GRetire指针与RetireP不匹配,那么不进行其他任何操作,因为系统中最年轻的指令是已知的。最后,当确定不需要回滚到检查点时可以释放该检查点。如果确保所有引退的指令都是正确的并且将不会引起任何异常,那么只要更年轻的检查点成为完整检查点,就可以释放检查点。相反,引退的指令有可能需要进一步的验证,如在线程化方案中发生的一样。该验证在当指令成为系统中最老的指令时发生。在该情况中,只要具有相关联的检查点的更年轻的指令成为系统中最老的指令并且验证是正确的,那么就可以释放检查点。只要当发生中断或数据误推测时,就应当将由先前检查点指向的值拷贝到将恢复应用程序执行的核心中。该拷贝可以由硬件或软件作为将显式地拷贝这些值的服务例程的开始而进行。一旦拷贝了架构状态,那么将采取检查点的指令的IP(该IP在采取检查点时进行存储)加入到用于从线程的IP转变到原始IP的表中,以获取原始单线程应用程序的 IP。然后,执行恢复跳转到所获取的原始IP,并且将执行原始单线程应用程序直到在其中可以再次生成线程的应用程序中的另一个点被找到为止。图23中示出了上文的详细说明。示例性SpMT系统图M说明了使用线程级重构的微处理器的实施例,特别地,图M说明了具有一个或多个处理器核心M05和MlO的微处理器M00,每一个所述处理器核心分别具有与其相关联的本地高速缓存M07和M13。图M中还说明了可以存储在本地高速缓存M07和 2413的每一个中存储的信息的至少一些的版本的共享高速缓冲存储器对15。在一些实施例中,微处理器MOO还可以包括没有在图M中示出的其他逻辑,例如集成存储器控制器、 集成图形控制器,以及用于执行计算机系统中诸如I/O控制的其他功能的其他逻辑。在一个实施例中,多处理器系统中的每一个微处理器或多核心处理器中的每一个处理器核心可以包括或以其他方式关联逻辑对19,以根据至少一个实施例从分解后的指令流重构顺序执行。逻辑可以包括电路、软件(体现为有形介质)或二者,以使得比某些现有技术的实现更有效地在多个核心或处理器之间进行资源分配。例如,图25说明了在其中可以使用本发明的一个实施例的前端总线(FSB)计算机系统。任何处理器2501、2505、2510或2515可以访问来自处理器核心2525、2527、2533、 2537,2543,2547,2553,2557的一个中的或以其他方式与其相关联的任何本地1级(Li) 高速缓冲存储器2520、2527、2530、2535、2M0、2545、2550、2555的信息。此外,任何处理器2501、2505、2510或2515可以经由芯片组2565访问来自共享2级(U)高速缓存2503、 2507、2513、2517的任意一个或来自系统存储器2560的信息。图25中的处理器的一个或多个可以包括或以其他方式与逻辑2519相关联以根据至少一个实施例从分解后的指令流重构顺序执行。除了图25中说明的FSB计算机系统之外,其他系统配置也可以与本发明的各种实施例结合使用,包括点到点(P2P)互连系统或环互连系统。
现在参考图沈,示出了根据本发明的一个实施例的系统沈00的框图。系统沈00 可以包括耦合到图形存储器控制器中心(GMCH)沈20的一个或多个处理元件沈10、2615。图 26中用虚线标示额外处理元件沈15的可选性。每一个处理元件可以是单个核心或可以可替换地包括多个核心。处理元件除了处理核心之外还可以可选地包括其他片上元件,例如集成存储器控制器和/或集成I/O控制逻辑。此外,对于至少一个实施例,处理元件的核心可以是多线程的,因为对于每个核心它们可以包括多于一个硬件线程环境。图沈说明GMCH沈20可以耦合到例如可以是动态随机存取存储器(DRAM)的存储器沈40。对于至少一个实施例,DRAM可以与非易失性高速缓存相关联。GMCH洸20可以是芯片组或芯片组的一部分。GMCH洸20可以与处理器洸10、2615 进行通信并且控制处理器2610、2615和存储器沈40之间的交互。GMCH沈20还可以充当处理器沈10、2615和系统沈00的其他元件之间的加速总线接口。对于至少一个实施例,GMCH 2620经由诸如前端总线(FSB) 2695的多点总线与处理器沈10、2615进行通信。此外,GMCH 2620耦合到显示器洸40 (例如平板显示器)。GMCH 2620还包括集成图形加速器。GMCH沈20还耦合到可以用来将各种外围设备耦合到系统沈00的输入/输出 (I/O)控制器中心(ICH)沈50。图沈的实施例中作为示例示出了外部图形设备沈60和另一外围设备2670,其中所述外部图形设备沈60可以是耦合到ICH 2650的分立图形设备。可替换地,系统沈00中还可以有额外的或不同的处理元件。例如,额外的处理元件2615可以包括与处理器沈10相同的额外处理器、与处理器沈10异构或不对称的额外处理器、加速器(例如,图形加速器或数字信号处理(DSP)单元)、现场可编程门阵列或任何其他处理元件。依据包括架构、微架构、热量、功耗特性等的指标度量谱,物理资源沈10、2615 之间可以存在各种差别。这些差别可以有效地将自身表现为处理元件沈10、2615之间的非对称性和异构性。对于至少一个实施例,各种处理元件沈10、2615可以位于相同的管芯封装中。现在参考图27,输出了根据本发明的实施例的第二系统实施例2700的框图。如图27中所示,多处理器系统2700是点到点互连系统,并且包括经由点到点互连2750耦合的第一处理元件2770和第二处理元件2780。如图27中所示,处理元件2770和2780的每一个可以是多核心处理器,包括第一和第二处理器核心(即,处理器核心277 和2774b以及处理器核心278 和2784b)。可替换地,处理元件2770、2780的一个或多个可以是不同于处理器的元件,例如加速器或现场可编程门阵列。尽管只示出了两个处理元件2770、2780,但是应当理解,本发明的范围并不受限于此。在其他实施例中,在给定的处理器中可以有一个或多个额外的处理元件。第一处理元件2770还可以包括存储器控制器中心(MCH) 2772和点到点(P_P)接口 2776和2778。类似地,第二处理元件2780可以包括MCH2782和P-P接口 2786和2788。 处理器2770、2780可以使用PtP接口电路2778、2788经由点到点(PtP)接口 2750交换数据。如图27中所示,MCH的2772和2782将处理器耦合到各自的存储器,即存储器2742和存储器2744,其中所述存储器2742和2744可以是在本地附于各自处理器的主存储器的部分。
处理器2770、2780每一个可以使用点到点接口电路2776、2794、2786、2798经由单独PtP接口 2752、27M与芯片组2790交换数据。芯片组2790还可以经由高性能图形接口 2739与高性能图形电路2738交互数据。本发明的实施例可以位于具有任意数量的处理核心的任何处理器中,或图27的PtP总线代理的每一个中。在一个实施例中,任何处理器可以包括或以其他方式与局部高速缓冲存储器(未示出)相关联。此外,共享高速缓存(未示出)可以包括在两个处理器外部但仍经由p2p互连与这些处理器相连的任一处理器中, 以使得如果处理器处于低功率模式时可以将处理器二者或之一的本地高速缓存信息存储到共享高速缓存中。图27中的处理器或核心的一个或多个可以包括或以其他方式与逻辑 2719相关联,以根据本发明的至少一个实施例从分解后的指令流重构顺序执行。第一处理元件2770和第二处理元件2780可以分别地经由P-P互连2776、2786和 2784耦合到芯片组2790。如图27中所示,芯片组2790包括P-P接口 2794和2798。此外, 芯片组2790包括用于将芯片组2790与高性能图形引擎2748进行耦合的接口 2792。在一个实施例中,可以使用总线2749来将图形引擎2748耦合到芯片组2790。可替换地,点到点互连2749可以耦合这些部件。芯片组2790又可以经由接口 2796耦合到第一总线2716。在一个实施例中,第一总线2716可以是外围部件互连(PCI)总线,或诸如快速PCI总线的总线或另外第三代I/O 互连总线,但是本发明的范围不局限于此。如图27所示,各种I/O设备2714以及总线桥2718可以耦合到第一总线2716,其中所述总线桥2718将第一总线2716耦合到第二总线2720。在一个实施例中,第二总线2720 可以是低引脚数(LPC)总线。在一个实施例中,可以将各种设备耦合到第二总线2720,所述各种设备包括例如键盘/鼠标2722、通信设备27 和可以包括代码2730的诸如磁盘驱动器或其他大容量存储设备的数据存储单元27观。代码2730可以包括根据上文描述的一个或多个实施例的排序指令和/或程序次序指针。此外,音频I/O 27M可以耦合到第二总线 2720。注意,其他架构是可能的。例如,系统可以实现多点总线或其他这种架构而不是图27 的点到点架构。现在参考图28,示出了根据本发明的实施例的第三系统实施例观00的框图。图 27和28中相同的元件具有相同的标号,并从图28中省略了图27的某些方面以免模糊图 28的其他方面。图观说明了处理元件2770、2780可以分别地包括集成存储器和I/O控制逻辑 (“CL”)2772和2782。对于至少一个实施例,CL 2772、2782可以包括诸如上文结合图26 和27描述的存储器控制器中心逻辑(MCH)。此外,CL 2772,2782还可以包括I/O控制逻辑。图观说明不仅存储器2742、2744耦合到CL 2772、2782,而且I/O设备观14也耦合到控制逻辑2772、2782。传统的I/O设备观15耦合到芯片组2790。本文公开的机制的实施例可以实现为硬件、软件、固件或这些实现方式的组合。本发明的实施例可以实现为在可编程系统上执行的计算机程序,其中,所述可编程系统包括至少一个处理器、数据存储系统(包括易失性和非易失性存储器和/或存储元件)、至少一个输入设备和至少一个输出设备。可以应用诸如图27中所说明的代码2730的程序代码来输入数据以执行本文描述的功能和生成输出信息。例如,程序代码2730可以包括被编码来执行图25中说明的方法
302500,2550的实施例的操作系统。因此,本发明的实施例还包括机器可读介质,所述机器可读介质包含用于执行本发明的实施例的操作的指令或包含诸如HDL的设计数据的,所述设计数据定义本文描述的结构、电路、装置、处理器和/或系统特征。这些实施例还可以称为
程序产品。这种机器可读存储介质可以包括但不限于由机器或设备制造或形成的粒子有形排列,包括诸如硬盘、任何其他类型盘(包括软盘、光学盘、光盘只读存储器(CD-ROM)、可重写光盘(CD-RE)以及磁光盘)的存储介质,半导体器件(例如,只读存储器(ROM)、随机存取存储器(RAM)(例如,动态随机存取存储器(DRAM)、静态随机存取存储器(SRAM))、可擦除可编程只读存储器(EPROM)、闪速存储器、电可擦除可编程只读存储器(EEPROM)、磁卡或光卡),或适于存储电子指令的任何其他类型的介质。可以以已知的方式将输出信息应用到一个或多个输出设备。为了该应用的目的, 处理系统包括具有处理器的任何系统,其中所述处理器例如数字信号处理器(DSP)、微控制器、专用集成电路(ASIC)或微处理器。程序可以以高级的过程或面向对象编程语言来实现,以与处理系统通信。如果需要,程序还可以以汇编或机器语言来实现。实际上,本文描述的机制不受限于任何特定编程语言的范围。在任何情况下,所述语言可以是编译型或解释型语言。可以通过存储在机器可读介质上的表示处理器中的各种逻辑的表示性数据来实现至少一个实施例的一个或多个方面,其中所述表示性数据当由机器读取时使得机器构造逻辑来执行本文描述的技术。称为“IP核心”的这种表示可以存储在有形的机器可读介质中,并且可以被供应给各个使用者或制造机构以加载到实际制造逻辑或处理器的生产机器中。因此,描述了方法、装置的实施例。应当理解,以上描述意图是说明性的而非限制性的。当本领域的技术人员阅读和理解了以上描述时,许多其他实施例将会变得显而易见。 因此,参照所附权利要求以及被授予这些权利要求的等价物的全部范围来确定本发明的范围。
权利要求
1.一种装置,包括多个数据高速缓存单元(DCU),用于存储推测执行的线程的本地引退的指令,其中,所述DCU包括用来分类每一行的推测更新状态的每行版本比特;合并级高速缓存(MLC),其耦合到所述DCU以合并来自所述DCU的行的数据,其中,所述 MLC包括用于指示高速缓存行包括推测状态的每高速缓存推测比特和用于指示对块的改变的最后版本比特;以及核心间存储器一致性模块(ICMC),用于在所述MLC中全局地引退所述推测执行的线程的指令。
2.根据权利要求1所述的装置,其中,所述ICMC还包括多个存储器先进先出(FIFO)队列,用于在推测执行的线程的排序指令引退之后存储所述排序指令,其中所述存储器FIFO队列中的每一个条目包括用于标识要提交的下一个指令位于的所述存储器FIFO队列的头部的程序次序指针(POP)。
3.根据权利要求2所述的装置,其中,所述ICMC还包括切换件,用于在所述ICMC进行流重构期间在所述存储器FIFO队列之间进行改变。
4.根据权利要求2所述的装置,其中,所述ICMC还包括更新描述表(UDT),用于标识位于所述存储器FIFO队列中的存储指令要更新的所述 MLC的行。
5.根据权利要求3所述的装置,其中,所述ICMC还包括寄存器检查点逻辑,用于在所述推测执行的线程的执行期间回滚到先前状态以纠正误推测。
6.根据权利要求1所述的装置,还包括多个功能单元,用于处理所述推测执行的线程的所述指令。
7.根据权利要求1所述的装置,还包括耦合到所述MLC的L3高速缓存。
8.一种机器可读存储介质,包括当由机器执行时使得执行方法的指令,所述方法包括接收计算机程序的多个区;识别所述多个区中作为并行多线程执行的候选的区;以指令级为所识别的区生成要在多个核心上并行地执行的多个细粒度线程,其中,所述多个线程形成所识别的区的优化版本;以及从所述多个线程生成程序代码。
9.根据权利要求8所述的机器可读存储介质,其中,所述方法还包括 从所述计算机程序生成数据依赖图(DDG)和控制流图(CFG);将简档信息添加到所述DDG和CFG ;以及从具有简档信息的所述DDG和CFG创建程序依赖图(PDG)。
10.根据权利要求9所述的机器可读存储介质,其中,所述方法还包括对所述PDG执行粗化,以找到所述PDG中的指令节点的相对好的划分,并且通过以下步骤来生成多层图检测所述PDG中的不良加载,其中不良加载是在高速缓存中将很可能经常未命中的加载指令;计算所述PDG的节点的每一条边的松弛度; 计算所述PDG的节点的公共前驱。
11.根据权利要求10所述的机器可读存储介质,其中,所述方法还包括 改善所述多层图以管理线程间依赖。
12.根据权利要求8所述的机器可读存储介质,其中,所述方法还包括生成程序次序指针(POP),所述程序次序指针用于定义优化区被非推测执行情况下的相对次序,并指示应当在何时评估正执行的机器的哪个存储器先进先出(FIFO)队列以重构所识别的区的优化版本的流;将所述POP添加到所识别的区的优化版本的每一个排序指令。
13.根据权利要求8所述的机器可读存储介质,其中,所述生成POP包括 确定所述优化区的第一指令是排序指令;找到所识别的区的优化版本中的顺序次序中的下一个排序指令;以及当顺序次序中的所述下一个排序指令属于与所述第一指令不同的线程时,标记所述第一指令以指示改变。
14.根据权利要求8所述的机器可读存储介质,其中,所述方法还包括在所述优化区之前插入孵化指令,所述孵化指令当由所述机器执行时使得创建所述多个线程。
15.一种方法,包括分别在第一处理核心和第二处理核心中推测执行来自代码区的第一线程和第二线程;在所述第一处理核心和所述第二处理核心的每一个的第一级高速缓存中本地引退所述第一线程和所述第二线程的每个指令;在共享合并级高速缓存中全局地引退的所述第一线程和所述第二线程的每个指令; 将所述第一线程和所述第二线程的每一个执行的排序指令存储在与所述第一处理核心和所述第二处理核心的每一个相对应的存储器先进先出(FIFO)队列中;确定在所述第一线程和所述第二线程的执行期间发生的条件,所述条件要求重构所述代码区的流;以及使用是存储的执行的排序指令来重构所述代码区的流。
16.根据权利要求15所述的方法,还包括读取存储在所述存储器FIFO队列之一中的被推测执行的所述代码区的第一排序指令;读取与所述第一排序指令相关联的程序次序指针(POP)值;以及当所述POP值指示存储器FIFO切换时,切换到其他存储器FIFO队列并且读取其首先存储的指令。
17.根据权利要求16所述的方法,其中,所述POP值是存储在所述存储器FIFO中的1 比特值。
18.根据权利要求16所述的方法,还包括当所述POP值指示没有存储器FIFO切换时,读取所述存储器FIFO队列的下一个存储的指令。
19.根据权利要求15所述的方法,其中,软件使用所存储的执行的排序指令来执行所述代码区的流的重构。
20.根据权利要求15所述的方法,其中,硬件核心间存储器一致性模块(ICMC)使用所存储的执行的排序指令来执行所述代码区的流的重构。
全文摘要
描述了用于将顺序程序分解为多个线程、执行这些线程和重构线程的顺序执行的系统、方法和装置。多个数据高速缓存单元(DCU)存储推测执行的线程的在本地引退的指令。合并级高速缓存(MLC)合并来自DCU的行的数据。核心间存储器一致性模块(ICMC)在MLC中全局地引退推测执行的线程的指令。
文档编号G06F12/00GK102171650SQ200980139244
公开日2011年8月31日 申请日期2009年11月24日 优先权日2008年11月24日
发明者A·冈萨雷斯, A·马蒂内, C·马德里斯, E·吉贝尔, F·拉托雷, J·M·科迪纳, P·洛佩斯, R·马蒂内 申请人:英特尔公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1