带有依赖性等级的多线程电子表格处理
背景
将电子表格应用程序用于数据分析已变得普及。此外,随着越来越多的企业依赖于这些应用程序来进行复杂数据计算,对这些程序的更快且更高效的处理的需求也变得十分渴求。Microsoft ExcelTM是这一电子表格应用程序的一个示例。电子表格应用程序的一个单元格中被称为“依赖”公式的公式依赖于另一单元格的内容或其中被称为“支持”公式的公式是典型的。当单元格的内容改变时,可触发重新计算(“重计算(recalc)”)操作,其中使用一程序线程来迭代通过各公式并基于这些改变来重计算需要重新计算的任何公式。当重计算程序线程面临依赖于尚未被计算的支持公式的公式时,用于计算操作的处理时间即使没有完全暂停相当长的一段时间也会在速度上减慢。即使在这些应用程序中采用多个处理器或多个程序线程的情况下,计算和重计算的执行速度在至少一个处理器不能在等待支持公式被计算的同时完成计算或重计算的情况下也不能提高。该问题随着电子表格应用程序中的依赖公式的数目增加而恶化。
虽然本背景一节中着眼于特定的问题,但本发明决不旨在限于解决那些特定问题。
概述
本发明的各实施例一般涉及在有一个以上处理器或处理引擎可用时用多个处理器或多个并发线程来处理电子表格计算和重新计算。其它实施例涉及在对输入项链重新排序时使用树结构和依赖性等级来执行重计算操作的多线程处理。此外,某些实施例涉及对重计算操作的多线程处理的同步。
如此处所讨论的,一特定实施例的一方面涉及对输入项,或称“ENT”的计算链重新排序,以创建由既不包含依赖公式也不包含支持公式的子链和ENT的子链(即,依赖公式和支持公式以树分层结构来组织)构成的统一重计算链。“ENT”指的是包含在电子表格的单元格内的公式。在另一实施例中,该统一链被划分成单独的依赖性等级,其中每一依赖性等级包含除了依赖于该依赖性等级内的子链中的支持公式之外仅依赖于先前的依赖性等级中的ENT的ENT。这一实施例中的安排允许多个线程在不必等待未计算的支持ENT被计算的情况下继续处理整个依赖性等级中的ENT。一旦到达下一依赖性等级,对位于其中的ENT和子链(如果有)的处理基于在先前的依赖性等级中已经完成的计算而高效地完成。
其它实施例涉及在系统包括一个以上处理器或处理引擎的情况下使用多个异步程序线程来对该统一重计算链中的公式求值。在一个实施例中,可使用控制线程来控制该多线程处理的同步。
提供本概述以便以简化的形式介绍将在以下详细描述中进一步描述的一些概念。本概述并不旨在标识所要求保护的主题的关键特征或必要特征,也决不旨在用于限制所要求保护的主题的范围。
附图
图1示出了根据本发明的一个实施例的在电子表格应用程序中使用的、包括“N”个重新计算引擎(“重计算引擎”)的示例性功能组件模块的逻辑表示。
图2描绘了根据本发明的一个实施例的由图1所示的系统执行的、用于加载电子表格应用程序并确定要对其使用的处理器的个数的基本操作。
图3示出了根据本发明的一个实施例的由图1所示的系统执行的、用于用图1所描绘的重计算引擎执行重计算操作的基本操作。
图4描绘了根据本发明的一个实施例的示出使用图1所示的功能组件模块的电子表格应用程序中具有值和/或多个公式的单元格输入项的示例性3x3电子表格。
图5示出了根据本发明的一个实施例的最初被加载到单计算链中的图4所示的电子表格单元格。
图6A描绘了被重新排序成子链的统一重计算链的图4和5所示的单元格。
图6B示出了根据本发明的一个实施例的被加载到两个重新计算引擎中并被分隔成依赖性等级的图6A的子链,其中单元格之一被移至第二依赖性等级。
图6C是示出根据本发明的其它实施例的用于如图6A和6B的示例性实施例中所描绘的将单元格重新排序成子链和依赖性等级的过程的操作特性的流程图。
图7示出了根据本发明的一个实施例的由两个单独的重计算引擎对图4所示的单元格的处理,以及要对每一重计算引擎重新排序的单元格队列。
图8描绘了根据本发明的一个实施例的对图7中排队的单元格的非最优重新排序的表示。
图9示出了根据本发明的一个实施例的用于同步图7所示的重计算引擎的线程的程序代码。
图10A是示出根据本发明的一个实施例的用于启动对图2所示的单元格中的值和公式的求值的过程的操作特性的流程图。
图10B是示出根据本发明的一个实施例的用于挂起或触发图7所示的重计算引擎的控制线程和/或异步线程的过程的操作特性的流程图。
图11是示出根据本发明的一个实施例的用于用图7所示的重计算引擎的控制线程和异步线程对单元格重新排序的过程的操作特性的流程图。
图12是示出根据本发明的一个实施例的用于允许控制线程对图7所示的队列的单元格重新排序以便在仅适用控制线程的公式上工作并重新显示单元格的过程的操作特性的流程图。
图13示出了根据本发明的一个实施例的将控制线程公式重新排序到下一依赖性等级的逻辑表示。
图14A示出了根据本发明的一个实施例的采用多线程处理对循环公式的处理。
图14B是示出根据本发明的其它实施例的用于如图14A的示例性实施例中所描述的对计算链重新排序以供可能的循环引用检测和求值的过程的操作特性的流程图。
图15描绘其上可以实现本发明的各实施例的示例性计算系统。
详细描述
本发明现将参考其中示出了各具体实施例的附图来更完整地描述各示例性实施例。然而,其它方面能以许多不同的形式来实现,并且在本发明中包括具体的实施例不应被解释为将这些方面限于在此所述的各实施例。相反,包括附图中描绘的各实施例是为了提供全面和完整且将预期的范围完全地传达给本领域技术人员的公开。在参考附图时,使用相同的附图标记来指示所有附图所示的相同的结构和元素。虚线可用于示出可任选组件或操作。虚线也可用于示出单元格从一个位置到另一位置的移动的逻辑表示。
用于用“N”个处理器和相应的程序线程来处理电子表格重新计算的环境100在图1中示出。在一个实施例中,系统100包括处理模块102,其包括操作系统中的“N”个可用处理器,每一处理器具有在其上操作的重新计算引擎(“重计算引擎”)104。系统100还包括数据库116、可用于从数据库106接收和发送数据以及与加载控制模块112通信的I/O或发送/接收模块114。加载控制模块进而与边界检测模块110通信,后者确定“脏”单元格的范围和域,或由于依赖于或支持另一单元格中改变的内容而需要重计算的单元格的范围和域。在一个实施例中,脏单元格在从发送/接收模块114接收到重新计算命令的情况下被重新计算。
在使用系统100的多处理器环境的电子表格应用程序中,有必要确定操作系统中可用的处理器的个数。图2描绘了由图1所示的系统执行的、用于加载或调用电子表格应用程序并确定要对其使用的处理器的个数的操作200的基本初始化序列。开始操作202在与加载控制模块112通信之后启动,其中在加载应用程序操作204中加载电子表格应用程序。在使用多个处理器,因此使用多个程序线程来对电子表格链计算中的输入项,即“ENT”求值的实施例中,有必要同步多个处理器对这些ENT的求值。因此,确定操作206确定操作系统中的处理器,以及因而重计算引擎104的个数。存储操作208将所确定处理器个数及其访问位置储存在数据库116中。在一个实施例中,所使用的处理器是单独的处理器,而在另一实施例中,它们是单个芯片上的一个或多个嵌入的协处理器。进而在分配操作209中将重计算引擎分配给每一处理器,然后过程200的控制转移到返回操作210。
现在转向图3,重计算过程300以开始操作302开始,该操作响应于处理在图1所示的系统100上运行的电子表格内的链计算的手动或自动计算或重新计算请求而启动。从开始操作302,由发送/接收模块114接收重新计算请求,并且如该请求所需从数据库116中检索数据。在一个实施例中,开始操作302是由用户做出的重新计算所显示的电子表格的手动请求来触发的。在另一实施例中,开始操作302是由来自调用例程的请求自动触发,或在用户改变ENT中的值或公式或向电子表格添加另外的ENT时自动触发的。不论具体的触发机制是什么,在操作304中标识或“解析”重新计算请求。在解析操作304之后,在操作306中确定重计算请求的域和范围。在一个实施例中,这仅涉及一个ENT。在另一实施例中,它涉及依赖于或支持改变的单元格内容,即“脏”ENT的ENT数组。从确定操作306,过程300前进到重计算操作308,该操作根据本发明的实施例来重新计算脏单元格。当重新计算完成时,控制转移到返回操作310,该操作将操作返回到调用代码或用户界面。
图4描绘了可利用以上参考图3所描述的过程来重新计算的示例电子表格400。在该3x3的电子表格的示例性表示中,行402中的单元格A1和B1被示为具有示例性值“=1”。行404中的单元格A2和B2被示为分别具有公式=A1和=B1,它们表示依赖于A1和B1的公式。类似地,行406中的单元格A3和B3被示为分别具有公式=A2和=B2,它们表示依赖于A2和B2的公式。最后,单元格C3被示为具有公式=A3+B3,这意味着其依赖于A3和B3。如上所述,单元格A1到C3的内容可包括必须被计算或重新计算的值或公式,且因此每一单元格的内容被称为输入项,即“ENT”。例如,公式“=A3+B3”是位于单元格C3中的ENT。
在用图1所示的系统100加载或调用电子表格400时,处理器通过基于对电子表格本身的输入将ENT以连贯的顺序排序成单计算链来开始。图5示出了对图4所示的电子表格400的单元格A1到C3的这一单计算链排序。仅作为示例,单元格A1到C3中的ENT按照A1、A2、A3、B1、B2、B3、最后是C3的顺序输入到电子表格400中。在如此最初将ENT排序成单链时,程序代码将第一个ENT(即,此处所指的示例性实施例中的A1)置于计算链的最右边末端。接下来的ENT按照连贯的顺序添加,从右边到左边操作并以C3结束。
在继而对单计算链500中的ENT求值时,计算代码以C3开始,并确定公式A3+B3依赖于单元格A3和B3中的公式。接着,在首先查看单元格A3(因为它是公式中的第一个命名单元格)时,确定单元格A3是“脏”的,即待决计算。在该实施例中,ENT“A3+B3”被称为“依赖”公式,而单元格A3中的公式被称为“支持”公式。在本发明的一个实施例中,单计算链500被重新排序以创建依赖和支持公式的统一链,该统一链利用其中的子链来组织成树结构。在一个实施例中,依赖公式,例如C3被确定为第一个支持公式,例如A3的子。此外,第一个支持公式可以成为其所依赖的第二个支持公式的子。
一旦C3被移为A3的子,则对单链中的下一单元格,即图5所示的示例性实施例中的B3求值。在试图对B3求值时,计算代码发现B3依赖于单元格B2,且B2为“脏”。B3因此变为B2的子。类似地,该代码试图计算下一单元格,即B2,并确定B2依赖于B1。B2因此变为B1的子,且因为B3是B2的子,因此产生了B1、B2和B3的完整子链(示为图6A中的链600中的子链602)。接着,计算代码试图对A3求值并确定A3(如上所述具有子C3)依赖于支持公式A2,而A2本身依赖于A1。因此,产生了子链A1、A2、A3和C3。该子链的一个示例性表示被示为图6A中的子链604。
尽管链604示出了子链A1、A2、A3和C3,但图6B中所描绘的本发明的另一示例性实施例示出了其中移除了C3的类似的子链610,其中C3被包括在位于根据本发明的另一实施例的单独“依赖性等级”620中的其自己的子链612中。实际上,图6B示出了两个离散的依赖性等级,即依赖性等级#1(618)和依赖性等级#2(620)。每一依赖性等级包含除了依赖于该依赖性等级内的子链中的支持公式之外仅依赖于先前的依赖性等级中的ENT的ENT。这一实施例中的安排允许一个或多个处理器在不必等待未计算的支持ENT被计算的情况下以连续的方式处理整个依赖性等级中的ENT。
分开的依赖性等级的好处可以在计算链600的示例性实施例中展示,其中C3是A3的子,而A3进而是A2和A1的子。如图400所示,C3依赖于A3和B3中的公式的和。C3因此依赖于A3和B3。如果B3在计算代码试图对子链604中的C3求值之前被计算,则当计算代码到达C3时没有延迟(即,计算代码能够立即计算C3,因为A3和B3都已被计算)。因此,这一实施例中的C3可以作为子链604的一部分保留。然而,在B3未在计算代码对C3求值之前计算的情况下,计算代码将不能够计算C3。因此,只要B3保持未计算,C3就保持未计算。由此,基于C3对B3的依赖性,对子链604的处理被暂停、或停止。这一依赖性可能会造成重计算处理中的低效。一个实施例因而将C3(612)从依赖性等级#1(618)移至依赖性等级#2(620),如图6B中的统一计算链606所示。
在其中有多个处理器可用的一个实施例中,将C3移至新依赖性等级允许第二处理器对子链610操作以完成该子链的处理并在第一处理器继续对子链608的处理的同时移至对依赖性等级#1中的另一ENT或子链的处理。这多个处理器被示为图6B中的重计算引擎#1和#2(分别为614和616),因为每一处理器包括在其上运行的一重计算引擎。尽管根据本发明的一个实施例在图6B中示出了两个重计算引擎,但是如图1中的省略号104所示,可以对计算和重计算操作采用任意数量“N”的处理器。
图6C示出了根据本发明的一个实施例的用于执行对ENT及其向下一依赖性等级的移动(如果有)的重新排序的过程622。开始操作624响应于将单元格加载到电子表格程序400中以及对重新计算的调用而启动。从开始操作624,过程622前进到排序操作626,在排序操作中,如上所述,ENT基于其输入到电子表格程序400中的顺序被排序成单计算链。接着,求值操作628试图对单计算链中的第一个公式求值。在试图对第一个公式求值之后,过程622前进到查询操作630,该操作确定第一个公式是否依赖于支持公式。如果该第一个公式依赖于一支持公式,则流程通过“是”分支到移动操作634,后者将第一个依赖公式移至支持公式的子部分。如果第一个公式不依赖于支持公式,则流程通过“否”分支到求值操作632并对第一个公式求值。
从移动操作634,过程622前进到查询操作636,后者确定第一个公式是否还依赖于第二个未计算的公式。如果查询操作636确定第一个公式依赖于第二个未计算的公式,则流程通过“是”分支到移动操作642,后者将第一个依赖公式移至下一依赖性等级。接着,查询操作644确定在该计算链中是否有任何其它公式要求值,并且如果是,则通过“是”分支到求值操作628。如果查询操作644确定没有其它公式要求值,则流程通过“否”分支到结束过程622的终止操作646。如果查询操作636确定第一个依赖公式不依赖于第二个未计算的支持公式,则流程通过“否”分支到查询操作638,后者确定第一个支持公式是否还有第二个依赖公式。如果查询操作确定第一个支持公式没有第二个依赖公式,则流程通过“否”分支到求值操作632。另一方面,如果查询操作638确定第一个支持公式还有第二个依赖公式,则流程通过“是”分支到移动操作640,在移动操作640中,将第一个和第二个依赖公式移至下一依赖性等级。从移动操作640,过程622前进到查询操作644以确定是否有任何其它公式需要求值,并且该过程如上所述地继续。
尽管图6A、6B和6C中讨论的对ENT的重新排序与一般不考虑处理器的个数(即,使用一个或多个处理器)的重新排序有关,但是图7具体地示出了通过使用多个重计算引擎和异步线程对来自电子表格400的单计算链的重新排序700。采用控制线程702来同步各线程和重计算引擎。在系统700的示例性实施例中,采用了两个重计算引擎704和712;然而,其它实施例可涉及任意数量的重计算引擎和相应的多线程处理操作。
根据图7所描绘的示例性实施例,来自重计算引擎1(704)的处理线程试图对单计算链708中的C3求值。由于C3依赖于尚未计算的A3和B3,因此C3还不能被计算。因此,重计算引擎1将C3移至其依赖和支持公式的队列706。C3作为依赖公式列出,而A3作为C3的支持公式列出。接着,重计算引擎2(712)的程序线程试图对B3求值。当无法对该依赖公式求值时,重计算引擎2将依赖B3及其支持公式B2移至其自己的依赖和支持公式队列710。该过程继续,直到重计算引擎尝试对单计算链708中的每一ENT求值为止。
一旦链708中的每一ENT被求值或试图被求值,即由控制线程702基于其依赖/支持关系将队列706和710重新排序成子链。类似于以上讨论的子链604,图8示出了具有ENT A1、A2、A3和C3的子链804。子链802示出了ENT B1、B2和B3。这些子链最初都被示为位于图8的依赖性等级#1(806)中。在一个实施例中,重计算引擎1(704)处理由B1、B2和B3构成的子链802。然后,当重计算引擎1开始处理子链802时,重计算引擎2开始处理子链804。在该示例性实施例中,假定重计算引擎1在重计算引擎2到达子链804的C3之前完成对子链802中的B3的处理。在这一情况下,C3可被求值,因为支持公式A3和B3都已被计算。在该实施例中,C3被示为位于依赖性等级#1(806)中,并且依赖性等级#2(808)在图8中被示为空。然而,在另一实施例中,(出于多种原因)有可能重计算引擎1在重计算引擎2试图对C3求值之前不能对B3求值。在这一情况下,C3将保持未计算,并且重计算引擎2保持停止,同时等待重计算引擎1完成其对B3的处理。这一停止阻止重计算引擎2处理可能存在于第一依赖性等级中的其它ENT和子链(尽管这些额外子链没有在图8的示例性实施例中示出)。停止的重计算引擎是对多处理器系统的多线程化处理能力的低效使用(即,其中重计算引擎2的所请求的重计算操作依赖于单个重计算引擎1的处理速度)。由此,图8所示的实施例并不是单元格的最优重新排序。相反,最优重新排序将表现为图6B所示并在以上参考其讨论的示例性实施例。
尽管图8示出了对ENT的非最优重新排序800,其中C3保留在依赖性等级#1(806)中,但其它实施例(其中B3在对C3求值时保持未计算)要求将C3移至依赖性等级#2(808)。在一个实施例中,支配ENT向下一依赖性等级的移动的规则为:
(1)试图使依赖公式成为支持公式的子。
(2)如果依赖公式已经是另一公式的子,则将该依赖公式对下一依赖性等级排队;或者
如果依赖公式所依赖的支持公式已经有一个子,则将该依赖公式对下一依赖性等级排队。
(3)如果一公式包含必须在控制线程上求值的函数,则该公式(称为“控制线程公式”)被移至下一依赖性等级。仅作为示例,以下函数必须在控制线程上求值:
(a)INDIRECT函数;
(b)GETPIVOTDATA函数;
(c)INFO函数;
(d)ADDRESS函数;
(e)用户定义函数(UDF)。
现在转向图9,根据本发明的一个实施例示出了用于触发和挂起图7所示的重计算引擎1和2的异步线程的程序代码900的示例性实施例。控制线程902控制异步线程的触发。最初,计数器906被设为从确定操作206确定的处理器的个数。计数器906可以是任何类型的计数器。在一个示例性实施例中,计数器906可被称为ISpinning。不论所使用的计数器的期限或类型如何,控制线程(“CT”)902中的计数器906都被设为被确定为对多线程处理可用的处理器的个数。在图9的示例性实施例中,计数器906因而对重计算引擎910和920被设为值“2”。此外,控制线程索引904,例如int ientNext被设为零(“0”),并且每一重计算引擎索引914和924,int iENT被设为“0”。这些索引如下所述控制ENT912和922的指针。索引值“0”是对单计算链918的左边的第一个单元格,即C3的索引。
图10A和10B示出了触发和挂起重计算引擎1(910)和2(920)的异步线程操作以对单计算链918求值的操作步骤1000。图10A的开始计算操作1002响应于对如图4所示的电子表格400等电子表格求值的加载或调用而启动。在设置操作1004中,将计数器906设为重计算引擎的个数。接着,在分配操作1006中,控制线程902将重计算引擎1和2的索引914和924分别设为“0”,使得每一线程被分配为在第一个ENT处开始求值。控制线程902然后在触发操作1009中触发每一重计算引擎上的事件916和926以唤醒用于处理的线程。应用程序的调用或加载是其中控制线程902可触发重计算引擎事件的事件的一个示例。在被触发之后,每一重计算引擎执行线程安全互锁递增操作1010。例如,重计算引擎910通过对控制线程索引904加“1”并作为返回从控制线程902接收先前一索引值904,即本实施例中的“0”来开始该互锁递增操作1010。第一个重计算引擎的索引值914和从控制线程902返回的控制线程索引904的值之差是重计算引擎1应沿着单计算链918向下迭代的值。在该示例性实施例中,重计算引擎1(910)将控制线程索引904的值从值“0”递增到值“1”。由于“0”是控制线程索引904的前一值,因此重计算引擎1(910)接收值“0”,将其与其自己的索引914的值,即根据该示例性实施例的“0”进行比较,以确定这两个值之差,即“0”减“0”等于“0”,并接收值“0”。值“0”要求重计算引擎1(910)对计算链918中的第一个ENT(即,C3)求值。
类似地,重计算引擎2(920)执行线程安全互锁递增操作,其中它将控制线程索引904从“1”递增到“2”,并作为返回接收控制线程索引904的先前值,即该示例性实施例中的“1”。重计算引擎2(920)然后将该从控制线程索引904返回的值“1”与其自己的索引值,即本示例性实施例中的“0”进行比较,并计算两个值之差“1”。值“1”由此要求重计算引擎2(920)对计算链918中的第二个ENT(即,B3)求值。
在一个实施例中,该线程安全互锁递增继续,直到依赖性链的末尾。在执行了互锁递增操作1010之后,每一重计算引擎在操作1012中开始对所分配的ENT的求值。在触发了异步线程以对链918求值之后,控制线程902在步骤1014挂起其自己的操作并等待其自己的事件908被触发。过程1000然后转移到返回操作1016。
在一个实施例中,重计算引擎的操作可以由重计算引擎本身单独挂起。在另一实施例中,重计算引擎可要求所有异步线程都被挂起。在第一个实施例中,当到达依赖性等级的末尾时异步线程挂起其自身。在另一实施例中,异步线程可在该线程的队列或缓冲区因依赖和支持公式变满时挂起。其它实施例可涉及挂起异步线程的其它原因。此处给出的示例旨在仅用作示例性实施例。在另一实施例中,异步线程可要求所有线程被暂停(例如,在异步线程检测到控制线程公式的情况下)。
在如以上图10A所述地触发了线程操作之后,根据一个示例性实施例在图10B中描述了用于挂起或暂停个别异步线程操作的“挂起”过程1018。根据本发明的一个实施例,图10B所描绘的流程图示出了两个线程之间的操作的发生。在另一实施例中,线程可同时操作。图10B所描绘的流程图旨在仅用作示例性实施例,并且决不应被解释为限制线程的操作。转向图10B,如上所述,线程可在其检测到其达到了依赖性等级的末尾时挂起其操作。在另一实施例中,线程可在其检测到其队列或缓冲区满时暂停其操作。因此,从开始操作1020,流程前进到查询操作1024,该操作确定是否达到了依赖性等级的末尾,或者重计算引擎#1的缓冲区是否满。如果查询操作1024确定尚未达到依赖性等级额末尾并且该线程的缓冲区未满,则流程通过“NO”到继续操作1026,在该操作中,线程继续对ENT求值并沿着计算链向下迭代。另一方面,如果查询操作1024确定已经到达依赖性等级的末尾或者线程的缓冲区满,则流程通过“是”到递减计数器操作1028。递减计数器操作递减控制线程的计数器906。在挂起其操作时,重计算引擎将特别地递减控制线程906的计数器。如果计数器906具有大于“0”的值,则线程必定在操作或仍苏醒。然而,当计数器的值为“0”时,所有线程被挂起并且触发控制线程902的事件908。在递减了控制线程计数器906之后,在睡眠操作1030中挂起重计算引擎#1,换言之,将其置于睡眠模式。接着,查询操作1032确定控制线程计数器906是否等于“0”。如果计数器906的值为“0”,则流程通过“是”分支到操作1034处的触发控制线程事件操作908,因为值“0”指示所有异步线程被挂起。如果计数器的值不为“0”,则流程通过“否”分支到传递操作1036,在该操作中控制被传递到重计算引擎#2。重计算引擎#2通过步骤1038到1048继续,这些步骤类似于以上对重计算引擎#1所讨论的步骤。
根据本发明的一个实施例示出了用于迭代通过计算链来确定必要的重新排序并检测控制线程公式(如果有)的过程1100。如上所述,图11所示的本发明的示例性实施例示出了两个线程之间的操作的发生。在另一实施例中,线程可同时操作。图11所描绘的流程图旨在仅用作示例性实施例,并且决不应被解释为限制线程的操作。转向图11,开始操作1102在触发了每一重计算引擎的事件1008之后启动。从开始操作1102,操作流程前进到重计算引擎#1的互锁递增操作1104。接着,重计算引擎#1在迭代操作1106中沿着计算链向下迭代到通过线程安全递增操作1104分配的所计算的ENT值。在到达了所分配的ENT之后,流程传递到查询操作1112,后者确定是否到达依赖性等级的末尾,或者异步线程的队列(或缓冲区)是否满。如果检测到依赖性等级的末尾,或者如果异步线程的队列被确定为满,则异步线程在暂停操作1116中暂停其自己的操作。如果要求暂停的这些项中没有一个存在,则过程1100前进到确定公式是否为控制线程公式的查询操作1114。如果检测到控制线程公式,则流程通过“是”分支到排队操作1115,后者将控制线程公式排队成仅由这些公式构成的单独的缓冲区或队列。如果查询操作114确定公式不是控制线程公式,则流程通过“否”分支到查询操作1120,后者确定所分配的ENT中的公式是否依赖于未计算的ENT。如果查询操作1120确定该公式依赖于未计算的ENT,则流程在操作1122中通过“是”分支到队列1,其中将依赖和支持公式置于适当的队列中。如果查询操作1120确定公式不依赖于未计算的ENT,则流程通过“否”分支在操作1118处对该公式求值,这返回一值。
在求值和排队操作1118和/或1122之后,过程1100前进到操作1124,在该操作中操作被传递到重计算引擎#2。第二个重计算引擎执行步骤1126到1142,这些步骤类似于以上参考重计算引擎#1的操作1104到1124所描述的步骤。
现在转向图12,根据本发明的一个实施例示出了涉及用于将计算链重新排序成统一的、经重新排序的链的控制线程操作的过程1200。开始操作1202响应于对控制线程事件的触发而启动。从开始操作1202,流程前进到重新显示电子表格400的单元格的重新显示操作1203。在重新显示操作1203之后,过程1200前进到查询操作1204,该操作确定在重计算引擎的队列中是否有任何输入项。如果查询操作1204确定这些输入项存在,则流程通过“是”分支到重新排序操作1210。重新排序操作1210将依赖和支持公式重新排序成统一链中的子链。一旦完成了这一重新排序,查询操作1218即确定是否形成任何子。如果形成了子,则重计算操作必须再次通过包含这些新的子链的依赖性等级。由此,如果形成了一个或多个子,则流程通过“是”分支到重置操作1224,该操作重置重计算引擎的索引和指针以再次从该依赖性等级的开头开始。从那里,过程1200前进到触发异步线程的事件的唤醒操作1230。这些线程执行经重新排序的链上的重计算操作。在触发了重计算引擎之后,控制线程在睡眠操作1232中挂起其自己的操作。
如果查询操作1218确定在重新排序中没有形成子,则队列中的一个或多个输入项必定已被如操作1220所示地移至下一依赖性等级。如果没有形成子,则不必重计算当前依赖性等级中的ENT。相反,对下一依赖性等级,在重置操作1222中重置异步线程的索引和指针以及异步线程的控制索引。流程然后前进到查询操作1226以确定在下一依赖性等级中是否有任何控制线程公式。如果查询操作1226确定在下一依赖性等级中有控制线程公式,则流程通过“是”分支到允许控制线程对这些公式操作的执行操作1228。一旦对这些公式求值,流程即前进到触发异步线程的事件的唤醒异步线程操作1230,并且如上所述处理步骤1230和1232。如果查询操作1226确定没有这些公式,则流程通过“否”分支到唤醒操作1230,并且过程1200如上所述前进通过步骤1230和1232。
如果查询操作1204确定在重计算队列中没有输入项,则流程通过“否”分支到查询操作1206,后者确定在控制线程902的链表中是否有控制线程公式。如上所述,控制线程公式是必须由控制线程而非由异步线程之一来求值的公式。如果控制线程公式已被排队,则流程通过“是”分支到移动操作1212,在移动操作1212中,将控制线程公式移至统一链中的下一依赖性等级。通过将控制线程公式移至紧接在当前依赖性等级之后的新依赖性等级,多线程处理可在尽管存在对控制线程公式求值的需求的情况下继续。从移动操作1212,流程前进到确定是否有任何其它控制线程公式的查询操作1216。如果有其它排队的控制线程公式,则流程通过“是”分支到查询操作1206并且重复以上步骤。如果查询操作1216确定没有其它控制线程公式,则流程通过“否”分支到重置操作1222,该操作将异步线程的索引和指针(以及相应的控制线程的控制索引)重置为下一依赖性等级。
在控制线程挂起其操作之前,它首先在查询操作1226中确定在下一依赖性等级中是否有任何控制线程公式,并且过程1200然后如上所述前进通过步骤1226到1232。
如果查询操作1206确定没有控制线程公式,则流程通过“否”分支到对下一依赖性等级重置索引和指针的重置操作1222,并且过程1200如上所述前进通过步骤1222到1232。
尽管图12中的步骤1206和1212涉及将控制线程公式移至紧接在当前依赖性等级之后的新依赖性等级,但是图13示出了该移动的逻辑表示1300。图13示出了依赖性等级#1(1302)和依赖性等级#2(1310),其中C3(1312)位于依赖性等级#2中。此外,控制线程公式“CT”(1308)被示为在依赖性等级#1中(还容纳链1304和链1306)。如所讨论的,为允许控制线程执行仅适用控制线程的公式,本发明的一个实施例将控制线程公式1308移至控制线程队列的链表。然后,当控制线程被触发并承担了对操作和重新排序的控制时,控制线程将控制线程公式移至紧接在当前依赖性等级之后的新依赖性等级。图13的示例性实施例因此示出控制线程公式1308被移动(1320)到依赖性等级#2(1316),并且容纳C3的依赖性等级现在变为单独的依赖性等级#3(1318)。该实施例中仅示出了一个控制线程公式。在另一实施例中,多个控制线程公式可被移至新依赖性等级1316。或者,每一控制线程公式可被移至依赖性等级#1(1314)之后并且位于依赖性等级#3(1318)之前的其自己的新依赖性等级。
在各实施例中,控制线程公式被移至下一依赖性等级,因为该控制线程将是在该依赖性等级末尾工作的线程。在触发异步线程以开始下一依赖性等级中的求值之前,控制线程可在触发异步线程之前首先确定是否有需要被执行的任何控制线程公式。将控制线程公式移至单独的依赖性等级允许多线程处理在同时允许仅适用控制线程的操作的同时继续。尽管图13示出了三个依赖性等级,但是可以存在任何数量的此类等级,并且此处所示的实施例的示例性本质并不旨在以任何方式限制这些可能的依赖性等级的数量。
如图14A中逻辑地表示的本发明的一个实施例还允许具有多处理能力的电子表格应用程序在统一计算链的多线程处理中执行循环引用计算(即,依赖于彼此的计算)。电子表格1402示出了具有循环引用可能性的单元格A1到A3。换言之,单元格A1中的公式依赖于A3,A3依赖于公式A2,而A2进而依赖于A1本身。为解决这一循环引用问题,本发明的一个实施例允许循环引用单元格从统一链中取出或从其断开,并置于单个链计算,即没有子链或依赖性等级的计算链中,以使用单个线程来计算。采用单链计算而非涉及子关系和/或依赖性等级的统一链,迭代函数可对该链执行迭代计算以在最终值上收敛。IterativeCalc 1410是这一函数的一个示例;然而,根据本发明的各实施例可以使用任何类型的用于计算循环依赖性的迭代函数。
为创建用于迭代循环计算的单链计算,单元格首先如上所述(即,基于其向电子表格1402的输入)置于单计算链1404中。在该示例性实施例中,B1首先被求值并被确定为不依赖于任何其它公式。接着,沿着链向下操作,A3被确定为依赖于A2并被标记为“进行中”,且从计算链移除以称为支持公式A2的子。沿着链1404向下到ENT A2,发现A2依赖于A1。A2因此被标记为“进行中”,并从计算链1404移除到支持公式A1的子位置。在将A2移至A1的子位置时,A2将A3带上。接着,沿着链1404向下到A1,试图对A1求值。然而,发现A1依赖于A3,使得在1406处标识一循环依赖性。A1被标记为“进行中”并从计算链1404中移除。结果,A1、A2和A3现在如经重新排序的链1406所示完全从计算链1404断开。因此,在迭代通过链的过程中,A1、A2和A3将不被处理。因此,在完成通过链的迭代时,A1、A2和A3将仍被标记为“进行中”或脏。为了处理这些项,系统跟踪在当前重新计算过程期间成为另一公式的子的每一公式。接着,检查在该过程中成为子的所有公式来查看其中的任何公式是否被标记为脏。如果是,则该公式及其所有子被移至扁平计算链1408,即没有子链或依赖性等级的计算链。图14A的1408处所示的该扁平计算链然后使用单个线程来计算。如果在单线程化计算期间,检测到真正的循环引用,则该计算可迭代地,例如通过迭代计算函数1410来完成。
现在转向图14B,根据本发明的一个实施例示出了用于将计算链重新排序成扁平计算链以便进行可能的循环引用检测和求值的过程1411。开始操作1412在创建单计算链1404时启动。从开始操作1412,流程前进到获得计算链1404中的第一个公式的获得操作1414。求值操作1416然后对该公式求值。查询操作1418确定该公式是否是支持公式的子。如果该公式是一支持公式的子,则流程通过“是”分支到跟踪操作1420,并且该子公式被标记为“进行中”且被系统跟踪。如果该公式不是支持公式的子,则流程通过“否”分支到确定在计算链1404中是否有任何其它公式要处理的查询操作1422。如果有更多公式,则流程通过“是”分支到移至计算链1404中的下一公式来求值的获得操作1414。如果有其它公式,则流程通过“否”分支到获得被跟踪公式操作1424,该操作检索从跟踪操作1402跟踪的第一个(或下一个)公式。接着,查询操作1426确定所检索的被跟踪公式是否仍被标记为脏。如果该公式仍被标记为脏,则流程通过“是”分支到扁平计算链操作1428,该操作根据本发明的一个示例性实施例将该公式及其所有子添加到如扁平计算链1408所示的扁平计算链。如果查询操作1426确定被跟踪公式不为脏,则流程通过“否”分支到查询操作1430,该操作确定是否有被跟踪(或标记为“进行中”)的任何其它公式。如果有其它被跟踪公式,则流程通过“是”分支到获得第一个/下一个被跟踪公式操作1424,并且重复步骤1426到1430。如果查询操作1430确定没有其它被跟踪公式,则流程通过“否”分支到返回操作1432。一旦通过过程1411创建了扁平计算链,该扁平计算链(如在步骤1428中创建并示为扁平计算链1408)可使用单个线程来计算。如果在单线程计算期间检测到真正的循环引用,则该公式可被迭代地计算。尽管在该示例性实施例中(并在描述图14A时)使用了“进行中”的跟踪语言,但是根据本发明的各实施例可以使用任何标记或跟踪机制。
图15示出了其上可以实现本发明的示例性计算系统1500。图2中示出了具有至少一个处理器1502和在其上操作的至少一个重计算引擎1518的计算机系统1500。系统1500具有电子表格应用程序1520位于其中的存储器1504。在其最基本的配置中,计算系统1500在图15中由虚线1506示出。另外,系统1500还可包括另外的存储(可移动和/或不可移动),其中包括但不限于磁盘、光盘或磁带。这样的另外的存储在图15中由可移动存储1508和不可移动存储1510示出。计算机存储介质包括以用于存储诸如计算机可读指令、数据结构、程序模块或其它数据等信息的任何方法或技术来实现的易失性和非易失性、可移动和不可移动介质。存储器1504、可移动存储1508和不可移动存储1510都是计算机存储介质的示例。计算机存储介质包括,但不限于,RAM、ROM、EEPROM、闪存或其它存储器技术、CD-ROM、数字多功能盘(DVD)或其它光盘存储、磁带盒、磁带、磁盘存储或其它磁性存储设备、或能用于存储例如所需电子表格计算信息且可以由系统1500访问的任何其它介质。任何这样的计算机存储介质都可以是系统1500的一部分。取决于计算设备的配置和类型,存储器1504可以是易失性的、非易失性的或两者的某一组合。通信介质通常以诸如载波或其它传输机制等已调制数据信号来体现计算机可读指令、数据结构、程序模块或其它数据,并包括任意信息传送介质。术语“已调制数据信号”指的是其一个或多个特征以在信号中编码信息的方式被设定或更改的信号。作为示例而非限制,通信介质包括有线介质,诸如有线网络或直接线连接,以及无线介质,诸如声学、RF、红外线和其它无线介质。以上的任何组合也应包括在计算机可读介质的范围内。
系统1500还可包含允许该设备与其它设备通信的通信连接1512。另外,为将内容输入到根据本发明的一个实施例的电子表格400的单元格中,系统1500可具有输入设备1514,诸如键盘、鼠标、笔、语音输入设备、触摸输入设备等等。也可包括诸如显示器、扬声器、打印机等输出设备1516,其中这些设备可用于向用户显示根据本发明的各实施例的电子表格400。所有这些设备在本领域中是公知的并且不必在此详细讨论。
以上参考附图描述了本发明的各实施例,可以理解,可以对本发明做出本领域技术人员易于想到且被包含在所公开并如所附权利要求书所定义的本发明的精神和范围内的众多修改。实际上,尽管出于公开的目的描述了目前优选的实施例,但可以做出落入本发明的范围的各种改变和修改。
同样地,虽然本发明使用了对结构特征、方法动作和含有这些动作的计算机可读介质专用的语言,但是应该理解,在所附权利要求书中定义的本发明不必限于此处描述的具体结构、动作、特征或介质。相反,上述具体特征和动作是作为实现权利要求的示例形式公开的。例如,尽管在某些示例性实施例中示出并讨论了两个重计算引擎,但是可使用任意数量“N”的处理器以及重计算引擎。本领域技术人员将认识到本发明精神和范围中的其它实施例或改进。因此,这些具体结构、动作、或介质是作为实现所要求保护的本发明的示例性实施例而公开的。本发明由所附权利要求书来定义。