acm-header
登录

ACM通信

研究突出了

高效缓存函数算法


高效缓存函数算法,插图

信贷:狗牛奶

广泛研究的I/O和理想缓存模型被开发出来,以解释在内存层次结构的不同级别访问内存的成本的巨大差异。这两个模型都基于两级内存层次结构,具有固定大小的快速内存(缓存)以及按大小块组织的无限慢记忆B。成本度量纯粹基于主内存和辅助内存之间的块传输数量。所有其他操作都是免费的。在这些模型中已经分析了许多算法,事实上,这些模型比标准随机存取机(RAM)模型更准确地预测了算法的相对性能。然而,这些模型需要在非常低的级别指定算法,要求用户小心地将数据布局到内存中的数组中,并管理自己的内存分配。

我们提出了一个成本模型,用来分析用简单函数语言表示的算法的内存效率。我们展示了一些仅使用列表和树(没有数组)、不需要显式内存布局或内存管理的标准形式编写的算法在模型中是如何高效的。然后,我们描述了该语言的一个实现,并展示了将我们的模型中的成本映射到理想缓存模型中的成本的可证明边界。这些界限意味着基于列表和树的纯函数式程序,不特别注意内存布局的任何细节,可以渐进地与精心设计的命令式I/O高效算法一样高效。例如,我们描述一个cacm5807_j.gif该算法在理想的缓存和I/O模型下都是最优的。

回到顶部

1.简介

今天的计算机在访问内存层次结构的不同级别(无论是寄存器、缓存的多个级别之一、主存还是磁盘)的成本上存在巨大差异。例如,在目前的处理器上,访问寄存器和主存之间的时间相差超过100倍,而主存和磁盘(甚至固态驱动器(SSD))之间的时间相差100倍左右。这种成本上的差异与标准随机存取机(RAM)模型相反,该模型假设访问内存的成本是一致的。为了解释非均匀性,已经开发了几个成本模型,将不同的成本分配到内存层次的不同级别。

图1描述了广泛使用的I/O2和ideal-cache11为此目的设计的机器模型这些模型基于两个参数:内存大小还有块大小B,它们被认为是为了分析的变量,因此显示在渐近边界。为了为这些模型设计有效的算法,重要的是要考虑时间局部性(以便利用有限大小的慢内存)和空间局部性(因为内存是在连续块中传输的)。在本文中,我们将使用来自理想缓存机模型(ICMM),包括把快的内存称为缓存,把慢记忆当做主内存,块传输为缓存错过,成本为缓存成本。

在这些模型中表现良好的算法通常被称为缓存或I/O高效算法。缓存高效算法的理论现在已经发展得很好了(例如,参见调查3.612171923).这些模型确实比标准RAM模型更准确地表达了实际机器上算法的成本。例如,模型恰当地表明一个阻塞的或分层的矩阵-矩阵乘法具有代价

eq01.gif

这比naïve三元嵌套循环要高效得多,后者的成本是(n3./B).此外,尽管模型只考虑内存层次结构的两个级别,缓存高效算法在ICMM不使用参数的B在代码中,在所有内存层次结构中同时高效。以这种方式设计的算法称为缓存无关。11

作为模型中分析的一个算法示例,考虑递归归并排序(参见图2).如果输入的大小n输出在数组中,然后合并能不能利用空间局部性并有缓存成本On / B)(见图3).的分裂可以在相同的,或者更好的范围内完成。对于递归归并排序,一旦递归达到计算适合缓存的级别,所有子调用都是自由的,利用了时间局部性。图4说明了归并排序递归树,并分析了对于一个大小的输入的总代价n是:

eq02.gif

这是一个合理的成本,比假设每次内存访问都需要缓存丢失要好得多。但是,这对模型来说不是最优的。稍后,我们将概述最优的多路归并排序。它有成本

eq03.gif

这个最优成本可以大大低于归并排序的成本。例如,如果nk而且B2,这在许多情况下都是合理的假设,那么成本就降低到Onk / B).所有最快的磁盘排序确实使用了某种多路归并排序的变体或另一种基于样本排序的最佳缓存效率算法。21

*1.1.精心布局,精心配置

尽管上面给出的对mergeSort的分析看起来相对简单,但我们选择了一个简单的示例,并省略了几个重要的细节。关于内存布局,在内存中连续排序排序序列非常简单,但对于许多其他数据结构来说就不是这样了。例如,一个矩阵应该按行为主顺序,还是按列为主顺序,或者按某种层次顺序(如z顺序)排列?这些不同的顺序会产生很大的不同。基于指针的结构(如链表或树)呢?作为图5表示,遍历链表的开销将取决于链表在内存中的布局方式。

比内存布局更微妙的是内存分配。在分配后接触未使用的内存将导致缓存丢失,因此正确管理空闲内存池非常重要。再次考虑mergeSort的例子。在我们的讨论中,我们假设一旦2n这个问题适合快速内存,因此是免费的。然而,如果我们使用内存分配器来分配合并所需的临时数组,位置可能是新鲜的,访问它们将导致缓存丢失。因此,成本将不是免费的,事实上,由于递归树叶子附近的级别进行许多小的分配,在叶子附近的成本可能会明显更大。为了避免这种情况,程序员需要管理自己的内存。例如,它们可以预先分配一个临时数组,然后将它作为额外的参数传递给递归调用,从而确保所有临时空间都被重用。对于更复杂的算法,分配可能要复杂得多。

总之,为这些模型设计和编程高效缓存算法需要仔细布局平面内存中的数据,并仔细管理该内存中的空间。

*1.2.我们的目标

我们工作的目标是能够利用理想的缓存模型,从而使机器与模型相匹配,而不需要在内存中仔细布局数据,也不需要手动管理内存分配。特别是,我们希望使用递归数据结构(指针结构),如列表或树。此外,我们希望使用具有垃圾收集功能的全自动内存管理器,并且不需要(显式)说明数据在内存中的位置。这些目标似乎不可能实现,但我们证明,至少在某些情况下,它们是可以实现的。我们在纯函数式(无副作用)语言的上下文中展示了这一点。与相关的会议文件相比,这里给出的提法略为简化5为了简洁和清晰;我们建议读者参阅那篇论文以获得更全面的解释。

作为我们努力实现的一个例子,请考虑合并算法中所示图6.该算法的一些特性需要注意的是,它基于链表而不是数组。此外,因为我们是在函数设置中工作,所以每个列表元素都是新创建的(在缺点第10行和第11行中的操作)。最后,没有指定在哪里分配数据,也没有显式的内存管理。考虑到这些属性,这段代码对于缓存效率来说似乎很糟糕,因为访问每个元素可能非常昂贵,如中所指出的图5.此外,每次新分配都可能导致缓存丢失。递归中隐含有一个堆栈,不清楚这是如何影响成本的。

然而,我们证明,通过适当的实现,代码确实是缓存高效的,并且当在归并排序中使用时,给出了与公式(2)相同的边界。我们还描述了一个匹配公式(3)中给出的最佳排序边界的算法。该方法不仅限于列表,它也适用于树。例如,图11定义递归划分为树和基于树的矩阵乘法的矩阵表示。使用数组和精心的程序员布局,此乘法的代价边界与理想缓存模型(公式1)的矩阵乘法边界相匹配。

*1.3.成本模型和可证明的实现边界

实现我们目标的一种方法是,根据特定的编译策略和特定的运行时内存分配方案,分析用高级代码编写的每个算法。这将是非常繁琐的,耗时的,不可移植的,并且容易出错。它不会带来一种分析算法的实用方法。

相反,我们使用在编程语言中直接定义成本的成本语义,这样就可以在不关心实现细节(例如垃圾收集器如何工作)的情况下分析算法。我们将配备了成本语义的语言称为ICFP,因为Ideal-Cache函数式编程语言。目标是将成本关联起来ICFP到成本ICMM。我们通过描述一个模拟来做到这一点ICFPICMM在这个模拟的基础上证明了相对成本的界限。特别地,我们展示了一个运行成本的计算,参数而且B,在ICFP可以模拟上ICMMO)快速内存的位置,块大小B和成本O).该框架在图7

*1.4.分配顺序与空间局部性

因为函数式语言抽象了数据布局决策,所以我们使用时间局部性(分配时间的邻近性)作为空间局部性(内存中分配的邻近性)的代理。要做到这一点,内存模型ICFP由两个快速内存组成:一个托儿所(用于新分配)和一个读缓存。托儿所是按时间顺序排列的,以确保条目在写入主(慢)内存时连续排列。例如,对于合并,输出列表元素将一个接一个地放置在主存中。为了使这个想法形式化,我们引入了数据结构紧凑的概念。粗略地说,数据结构的大小n是否紧凑,如果它可以在模型中遍历On / B)缓存成本。通过构造,merge的输出是紧凑的。此外,如果两个要合并的输入列表都是紧凑的,我们证明合并有缓存开销On / B).这种紧凑性的概念也适用于其他数据结构,比如树。

的分配缓存的另一个特性ICFP它只包含实时数据。这很重要,因为在某些算法中,例如矩阵乘法,生成临时内存的速率渐进地大于生成输出数据的速率。因此,如果所有数据都被计算在内,它就会填满缓存,而我们希望确保重用临时数据槽。另外,我们希望确保临时内存没有被传输到慢内存,因为这样的传输会导致额外的流量。此外,临时数据最终可能出现在输出数据元素之间,导致它们在块之间被分割。在我们可证明的实现中,我们不需要对实时数据进行精确跟踪,而是使用具有大小为2的托儿所的分代收集器M。然后模拟保留所有的2在快速内存中的位置,以便所有的分配和收集(在新一代内)都是快速的。

*1.5.相关工作

使用基于成本语义和可证明的高效实现的高级成本模型的一般思想以前已经在并行成本模型的上下文中使用过。4131522尽管已经有大量的实验工作表明良好的垃圾收集如何导致缓存和磁盘的有效使用(Chilimbi和Larus)7,法院10,格伦沃尔德等人。14, Wilson等。24琼斯和林斯也有很多参考文献16),我们知道没有人试图证明函数式程序在操作递归数据类型(如列表或树)时的算法边界。Abello et al。1展示如何使用函数风格来设计缓存高效的图算法。然而,他们假设数据结构在数组中(称为列表),并且提供和实现诸如排序、映射、筛选和约简等操作的原语具有最佳渐近代价(假设使用命令代码在较低的水平上)。因此,他们的目标是通过在集合上组合这些高级操作来设计图算法。它们没有解释如何处理垃圾收集或内存管理。

回到顶部

2.成本的语义

一般来说,成本的语义因为一种语言定义了两者如何执行一个程序和成本它的执行。在函数式语言中,执行由一种确定的策略组成,该策略通过简化过程来计算表达式的值减少,类似于初级代数。但函数式语言中的程序不是处理实数,而是使用整数、归纳数据结构(如列表和树)以及作用于这些值的函数(包括其他函数)进行计算。函数语言的理论基础是丘奇的微积分。89

函数式语言中的计算成本可以用各种方式定义,包括熟悉的度量方法,如时间复杂度(定义为计算表达式所需的原语约简步骤的数量)和空间复杂度(定义为计算期间分配的基本数据对象的数量)。这些度量是根据语言本身的构造来定义的,而不是根据它在机器模型(如RAM或图灵机)上的实现来定义的。算法分析完全在语言级别进行。实现的作用是确保抽象的成本可以在具有规定边界的具体机器上实现。

*2.1.缓存成本

本文的利益成本计量方法是缓存成本,它是从考虑程序的时间和空间行为的组合而来的。缓存成本是通过指定分配和检索数据对象的时间来获得的,与ICMM由两个常数参数化,B而且,控制缓存行为。更准确地说,表达式是相对于抽象计算的商店,,其中包括主内存,,读缓存、、和托儿所,或分配区域。该店的结构如图所示图8.的主内存将抽象位置映射到原子数据对象,并且具有无限容量。原子数据对象被认为占用一个存储单元。将主存中的对象聚合为的大小B以一种稍后会描述的方式。数据对象的阻塞在执行过程中不会改变;一旦一个对象被分配给一个块,它就会在接下来的计算中保持该块的一部分。

读缓存从位置到数据对象的固定大小的映射是否最多包含对象。通常,读缓存表示主存的部分视图。对象按大小块加载到读缓存中B由主存中对象的聚合决定。对象可以通过简单地重写从读缓存中删除;在函数式语言中,数据对象不能突变,因此永远不需要写回主存。块根据(不可计算)理想的缓存模型ICMM).

分配区域,或托儿所,是从位置到数据对象的固定大小的映射,也最多包含对象。托儿所中的位置不是阻塞的,而是根据分配它们的时间线性排序的。我们说一个数据对象是如果一个的位置顺序先于另一个。托儿所的一个位置生活如果它发生在被评估的程序中。18所有数据对象都分配在托儿所中。当它的容量对象是超越,最古老的B对象形成一个迁移到主存的块,一次性确定这些对象所属的块。此策略确保时间局部性意味着空间局部性,这意味着在时间上分配在附近的对象将在空间上位于附近(即占据同一块)。特别是,当一个对象被加载到读缓存中时,它在块中的邻居也会被加载。这些将是在大约同一时间分配的对象。

成本语义的作用是在不降低到实现级别的情况下,对算法的缓存成本进行推理。为了支持证明,必须以数学上严格的方式指定语义,我们现在对此进行说明ICFP,是普罗特金语言PCF的一个简单的热切变体20.对于自然数的高阶计算。(扩展很简单ICFP考虑到更丰富的数据结构,如列表或树,以及面向硬件的概念,如单词和浮点数,我们在示例中假设了这些。)

*2.2.成本的语义

的抽象语法ICFP定义如下:

ueq01.gif

在这里x表示一个变量,该变量将始终表示在内存中分配的数据对象。的表情z而且年代()分别表示0和后续,条件测试是否ez或者不是,分支到e0如果是,则分支到e1如果不是,则用(位置)替换前任x在这样做。函数,写有趣的x, y.e),绑定一个变量x代表函数本身和一个变量y支持它的论点。(该变量x用于实现递归调用。)编写函数应用程序应用程序e1e2),它应用表达式给出的函数e1到表达式给出的实参值e2.的类型规则ICFP是标准的(见Harper15),因此为了简洁而略去。

计算的成本算进去了吗ICFP仅考虑时间复杂度,语义将由一个评估关系定义env声明表达式e计算得到的值v使用n根据指定的最外层策略减少步骤。计算一次计算的缓存开销要稍微复杂一些,因为我们必须考虑到由执行引起的内存流量。为此,我们考虑一个形式的评价关系

ueq02.gif

其中表达式的求值e相对于存储执行,并返回由修改存储中的位置表示的值。对存储的修改反映了新对象的分配、它们的迁移到主存以及它们加载到读缓存。计算关系还指定了缓存开销n这完全是由块在主内存中的移动决定的。所有其他操作都被分配为零成本。

评价关系ICFP被定义为推导规则它指定了闭合条件。评价被定义为满足这些条件的最强关系。为了说明这是如何实现的,我们将介绍图9这是函数应用程序求值规则的简化形式,应用程序e1e2).该规则有四个前提和一个结论,用水平线隔开,这可以理解为一种暗示,说明如果前提都是可推导的,那么结论也是可推导的。

其他的结构ICFP是否由类似的规则定义,这些规则共同指定了任何评估的行为和成本ICFP程序。抽象的成本语义是第1节和第3节中给出的分析的基础。对语义给出的抽象代价进行验证可证明的实现413在混凝土机器上实现这些成本。在我们的例子中,实现是由ICMM,这是一个被接受的具有分级存储器的机器的具体公式。通过将抽象语义与可证明的实现组合在一起,我们获得了写入算法的缓存复杂度的端到端边界ICFP不必在具体的机器级别上执行分析,而是在编写算法所用的语言级别上执行。

*2.4.可证明的实现

的可证明的实施ICFPICMM描述的是图10.它的主要性质对于获取缓存复杂度的端到端边界非常重要,可以由以下定理总结:

定理2.1。评价@ en@ lICFPM和B的抽象缓存参数可以实现ICMM具有具体的缓存参数+k×B和B,缓存代价是On),对于某个常数k。

定理的证明由ICFPICMM中描述的图10的约简步骤ICFPICMM在一个(小的)常数因子内证明的全部细节,以及定理的一个更严密的陈述,在相关的会议论文中给出。

回到顶部

3.缓存有效算法

我们现在分析归并排序和矩阵乘法ICFP,并给出a的边界k无-way merge最优排序。实现是完全自然的函数式程序,使用列表和树而不是数组。在相关的会议论文中,我们描述了如何处理高阶函数(例如传递一个比较函数来合并),并为此定义了继承有限值的概念,但这里我们只考虑一阶使用。

正如在介绍中提到的,访问递归数据类型的成本将取决于它在内存中的布局方式,而这取决于分配顺序。根据列表在内存中的表示方式,我们可以试着定义一个有序的列表的概念。这既麻烦又低级。我们还可以尝试根据分配数据的特定代码来定义它。这也是很麻烦的。相反,我们直接根据遍历结构的缓存开销来定义它。我们所说的遍历是指以特定的顺序遍历结构并接触(读取)结构中的所有数据。因为像树这样的类型可能有很多遍历顺序,所以定义是针对特定的遍历顺序。为此,我们定义了“契约”的概念。

定义3.1。大小为n的数据结构是紧凑的对于一个给定的遍历顺序,如果按该顺序遍历缓存开销为On / B在M的代价语义中kB对某个常数k。

我们现在可以说,某些代码将生成与特定顺序相关的紧凑数据结构。我们注意到,如果一个列表在一个方向上的遍历是紧凑的,那么它在相反的方向上也是紧凑的。

为了保持数据结构的紧凑,不仅需要按照分配的顺序访问顶层链接,而且还需要按照类似的顺序访问算法在遍历期间接触的任何内容。例如,如果我们对一个列表进行排序,除了“cons单元格”之外,还必须按列表顺序分配键(或者,我们稍后将讨论,相反的顺序也可以)。为了确保键以适当的顺序分配,在将它们放入新列表时需要复制它们。该副本必须是复制所有组件的深度副本。如果键是机器字,那么实际上编译器可能会将这些键内联到cons单元格中。但是,为了确保复制对象,我们将使用操作!表示复制一个

*3.1.归并排序

我们现在考虑在我们的成本模型中分析归并排序,特别是在中给出的代码图2而且6.我们将不讨论的定义分裂因为它类似于归并。我们首先分析合并。

定理3.2。对于契约表A和B,的评价合并(A, B)从任何缓存状态开始都有缓存开销cacm5807_k.gif其中n = |A|+|B|),将返回一个紧凑的列表。

证明。我们考虑了向下递归然后向上递归的缓存开销。因为一个而且B它们都是紧凑的,我们只需要留出恒定数量的缓存块来遍历每个缓存块(根据定义)。回想一下,在成本模式中,我们有一个托儿所v它按照创建堆栈帧的顺序维护实时分配值和占位符。在合并从一个递归调用到下一个递归调用没有分配任何东西(cons单元是在递归返回的过程中创建的),因此只有栈帧被放在托儿所中。后托儿所将填充递归调用,并且必须将块刷新到内存中(如第2节所述)On / B这样的同花顺只是因为n创建框架。在返回递归的过程中,我们将为列表生成cons单元格并复制每个键(使用).注意,复制键非常重要,这样才能保持结果紧凑。cons单元和密钥副本将在托儿所中按分配顺序交错排列,并在托儿所填满后刷新到内存。同样,这些将按块大小进行刷新B因此最多只能有On / B)这样的冲。此外,生成的列表将是紧凑的,因为列表的相邻元素将在同一个块中。

我们现在把归并排序看作一个整体。

定理3.3。对于精简列表一个的评价归并排序(A)从任意缓存状态开始,缓存代价由式(2)给出,并返回一个紧凑的列表。

证明。与数组版本一样,我们考虑两种情况:输入适合缓存和不适合缓存。归并排序例程从来不会要求超过On)实时分配数据。因此,当kn米对于某个(小)常数k所有已分配的数据都适合放在托儿所中。此外,由于输入列表是紧凑的,对于kn米输入适合读缓存(对于某些常量)k).因此,mergeSort的缓存开销最多是刷新时间On)从分配缓存中取出它可能在开始时包含的项,并使用输入加载读取缓存。这个缓存的开销是有限的On / B).当输入不适合缓存时,我们必须支付如上所分析的合并和递归调用。这给出了与数组版本相同的递归式,因此解决了声明的结果。

这里我们只是勾勒出k-way mergeSort算法,并指定最适合排序的代价边界。该排序类似于mergeSort,但它不是将每个部分递归地分成两个部分,而是分成k部分。一个k-way merge用于合并已排序的部分。的k-way merge可以使用优先级队列实现。那种在ICFP具有如式(3)所示的最优排序边界。

*3.2.矩阵相乘

最后一个例子是矩阵乘法。代码显示在图11(我们省略了匹配尺寸的支票)。这是一个块递归矩阵与树中的矩阵相乘。我们根据这个树的预先遍历定义紧性。因此,如果以这种顺序遍历可以在缓存开销的情况下完成,那么我们就说这个矩阵是紧凑的On2/B)n×n矩阵(n2树叶)。我们注意到,如果我们在一路上分配叶的预序遍历中生成一个矩阵,得到的矩阵将是紧凑的。而且,每个递归子矩阵本身是紧的。

定理3.4。对于紧凑的n × n矩阵一个而且B的评价mmult (A, B)从任意缓存状态开始,缓存代价如式(1)所示,结果将返回一个紧凑矩阵。

证明。矩阵加法有缓存开销On2/B),并生成一个紧凑的结果,因为我们以预序遍历的方式遍历两个输入矩阵,并以相同的顺序生成输出。因为实时数据永远不会大于On2),该问题将适合缓存n2M / c为一个常数c。一旦放入缓存,代价是O (n2/B)需要加载输入矩阵并写出结果。当它不能放入缓存时,我们必须进行8次递归调用和4次矩阵加法调用。这给出了一个递归式,

ueq03.gif

这解决了cacm5807_l.gif.输出是紧凑的,因为四个调用中的每一个都调用maddmmult按照它们生成的子矩阵的预定顺序分配新结果,并且四次调用是按预定顺序进行的。因此,返回的整个矩阵是预先分配的。

回到顶部

4.结论

目前的工作扩展了Blelloch和Greiner的方法413为了考虑算法的缓存复杂度,缓存块的大小和缓存块的数量这两个参数。的语义方面进行了分析ICFP,并通过一个可证明的实现(也在第2节中概述)转移到理想缓存模型。该思想的本质是,可以部署传统的复制垃圾收集来实现缓存高效算法,而不用牺牲抽象,通过手动分配和缓存数据对象。使用这种方法,我们能够以高级函数风格表达算法,使用捕捉固定大小读取和分配堆栈思想的模型分析它们,而不公开实现细节,并且仍然匹配理想缓存模型的渐近边界,使用包括显式内存管理在内的低级命令技术实现。对于排序,边界是最优的。

进一步研究的一个方向是将(确定性)并行性与现有工作相结合。基于之前的工作413我们期望这里给出的计算语义将为指定并行复杂度和顺序复杂度提供一个良好的基础。一个复杂的问题是,在这里给出的成本模型中,显式地考虑存储考虑因素必须考虑到并行线程之间的交互。摊销的论点也必须重新考虑,以说明并行性。最后,尽管我们能够生成一个最优的缓存感知排序算法,但在我们的模型中是否可能生成一个最优的缓存无关排序算法尚不清楚。

回到顶部

致谢

这项工作得到了美国国家科学基金会CCF-1018188和英特尔实验室非数值计算程序并行算法学术研究室的部分支持。

回到顶部

参考文献

1.Abello, J., Buchsbaum, a.l., Westbrook, J.外部图算法的函数方法。Algorithmica 32, 3(2002), 437458。

2.排序的输入/输出复杂度及其相关问题。Commun。ACM 31, 9(1988), 11161127。

3.阿奇,L.,本德,M.A,迪梅因,E.D,雷瑟森,C.E,梅尔霍恩,K., ed。缓存无关和缓存感知算法,18.07.23.07.2004,卷04301Dagstuhl研讨会论文集。IBFI, Schloss Dagstuhl,德国,2005。

4.顺序函数语言的并行性。在函数式编程与计算机体系结构会议(FPCA)(La Jolla, CA, 1995), 226237。

5.Blelloch, G.E, Harper, R. Cache和I/O高效函数算法。在ACM-SIAM离散算法研讨会(SODA)。R. Giacobazzi和R. Cousot,编,(罗马,意大利,2013),ACM, 3950。

6.蒋介石,Y.-J。,去odrich, M.T., Grove, E.F., Tamassia, R., Vengroff, D.E., Vitter, J.S. External-memory graph algorithms. InACM-SIAM离散算法研讨会(SODA)。K.L.克拉克森,编(旧金山,加州,1995),ACM/SIAM, 139149。

7.Chilimbi, t.m., Larus, J.R.使用分代垃圾收集实现缓存敏感的数据放置。在内存管理国际研讨会。S.L.P.琼斯和R.E.琼斯编的。(温哥华,不列颠哥伦比亚省,1998年),ACM, 3748。

8.初等数论中一个无法解决的问题。点。j .数学。582(1936年4月),345363。

9.教堂,一个。转换的微积分。数学研究年鉴。普林斯顿大学出版社,新泽西州普林斯顿,1941年。

10.提高垃圾收集内存管理系统中引用的局部性。Commun。ACM 31, 9(1988), 11281138。

11.Frigo, M., Leiserson, C.E, Prokop, H., Ramachandran, S.缓存无关算法。在foc(IEEE计算机学会,1999),285298。

12.古德里奇,M.T,崔,j。,Vengroff, D.E., Vitter, J.S. External-memory computational geometry (preliminary version). Infoc(IEEE计算机学会,1993),714723。

13.格林纳,J.布莱洛赫,G.E.充分推测的可证明的时间效率的并行实现。ACM反式。程序。朗。21系统。, 2(1999), 240285。

14.格伦沃尔德,佐恩,b.g.,亨德森,R.改进内存分配的缓存局部性。在R.卡特赖特的著作中,PLDI(ACM, 1993), 177186。

15.哈珀,R。编程语言实用基础。剑桥大学出版社,剑桥,英国,2013。

16.琼斯,R。林斯,R。垃圾收集:自动动态内存管理算法。威利,1996年。

17.梅耶,U.,桑德斯,P.,西本,j.f.,编。内存层次算法,高级讲座[Dagstuhl研究研讨会,2002年3月1014日],卷2625计算机科学课堂讲稿。(Schloss Dagstuhl,德国,2003年),施普林格。

18.莫里塞特,j.g., Felleisen, M. Harper, R.内存管理的抽象模型。在FPCA(1995), 6677。

19.图算法的I/ o复杂度。在苏打水。R.E. Tarjan和T. Warnow,编。(ACM /暹罗,1999),687694。

20.LCF被认为是一种编程语言。定理。第一版。Sci。5, 3(1977), 223255。

21.Rahn, M., Sanders, P., Singler, J.可伸缩分布式内存外部排序。在ICDE。李菲、M.M. Moro、S. Ghandeharizadeh、J.R. Haritsa、G. Weikum、M.J. Carey、F. Casati、E.Y. Chang、I. Manolescu、S. Mehrotra、U. Dayal和V.J. Tsotras著。(IEEE 2010), 685688。

22.Spoonhower, D, Blelloch, G.E, Harper, R, Gibbons, P.B.并行函数程序的空间分析。在ICFP。J.胡克和P.蒂曼,编。(ACM, 2008), 253264。

23.外部存储器的算法和数据结构。趋势理论的基础。第一版。Sci。2, 4(2006), 305474。

24.Wilson, P.R, Lam, m.s., Moher, T.G.代际垃圾收集的缓存考虑。在LISP和函数式编程, 1992, 3242。

回到顶部

作者

家伙大肠Blellochguyb@cs.cmu.edu),卡耐基梅隆大学,匹兹堡,宾夕法尼亚州

罗伯特·哈珀rwh@cs.cmu.edu),卡耐基梅隆大学,匹兹堡,宾夕法尼亚州

回到顶部

脚注

本文的原始版本题为“缓存和I/O高效函数算法”,并发表在第40届ACM SIGACTSIGPLAN编程语言原理研讨会论文集(POPL 13), 3950年。

回到顶部

数据

F1图1。的I / O模型2假设一个内存层次结构包含一个大小不一的快速内存以及无限大小的缓慢记忆。两个内存都被划分为固定大小的块B连续的记忆位置。CPU和快速内存被视为标准的随机存取机(RAM), CPU访问单个单词,而不是块。附加的指令允许人们在快内存和慢内存之间移动任何块。算法的成本是根据块传输的数量来分析的,在主存中的操作成本被忽略。的ideal-cache机模型(ICMM)11与之相似的是,程序只处理慢内存,而“理想”缓存使用最优替换策略来决定将哪些块缓存到快内存中。访问快内存(缓存)再次被视为无成本,在慢内存和快内存之间传输有单位成本。这两个模型的代价在一个常数因子内是相等的,并且在这两个模型中,两个级别的内存可以表示主内存和磁盘,或者缓存和主内存。

F2图2。递归归并排序.如果输入序列为空或单例,算法返回相同的值,否则它将输入分为两个大小近似相等的序列,l而且H,递归地对每个序列排序,并合并结果。

F3图3。合并两个排序的数组。手指沿着两个输入和输出从左向右移动。在每一点上,输入手指上较小的值被复制到输出手指上,该手指和输出手指一起递增。在合并过程中,每个输入块只需加载到快速内存一次,而每个输出块只需写入到慢速内存一次。因此,对于两个大小的数组n合并的总缓存开销为On / B).

F4图4。I/O或理想缓存模型中合并排序的成本。在从上往下有两层调用mergeSort,每个大小nn/ 2.每次呼叫都有成本kn/B为一个常数k。因此,每一层的总成本约为cacm5807_m.gif.当调用适合快速内存时,那么其余的排序是无成本的。因为归并需要2n空间(用于输入和输出),这将发生时cacm5807_n.gif.因此,有对数2(2n / M)具有非零成本的级别,每个级别都有成本kn / B

F5图5。内存中有两个列表。根据列表的布局方式,遍历列表的成本有很大不同。在图中,最上面的是随机布局的,将需要On)的步骤,而底部只需要On / B).

F6图6。代码合并两个列表。如果list为空,代码将比较列表的两个头部,并在列表的尾部重复使用较小的元素,在整个列表中重复使用较大的元素。当递归调用结束时,将创建一个新的列表元素,其中较小的元素作为头,递归调用的结果作为尾。的在第3节中讨论。

F7图7。ICFP的成本语义及其到理想缓存模型(ICMM)的映射。的值k而且k是常数。

F8图8。ICFP开销语义的内存模型。它类似于理想的缓存模型,但有两个大小相同的快速内存:一个托儿所对于新分配的数据,和读缓存对于已经迁移到主存并被程序再次读取的数据。与理想缓存模型一样,主存和读缓存被组织成块,但托儿所不被阻塞。相反,它由(实时)数据对象组成,数据对象按分配时间的顺序线性排列。语义定义了一段数据何时是活动的,但从概念上讲,它只定义了从执行程序可以访问它的时间。如果分配超出了托儿所,最老的B活动对象从缓存中作为块刷新到主存中,以便为新对象腾出空间。如果后面读取了其中的一个单词,整个块就会移动到read缓存中,可能会替换进程中的另一个块。移位的块可以被丢弃,因为函数式语言中唯一的写操作发生在分配时,而不会发生在后续的执行中。

F9图9。简化了函数应用程序的语义。该规则指定函数应用程序的成本和评估值应用程序e1e2函数的)e1一个论点e2.其他语言结构也遵循类似的规则。记住,所有的值都是由内存中的(抽象的)位置表示的。首先,表达e1是评估,用成本n1,获取位置信息l1被调用函数的。从内存中读取该位置以获得函数本身,一个自引用抽象,在成本n1.第二,表达e2是评估,用成本n2,获取其值l2.最后,l1而且l2是代入函数体,然后求值得到结果吗l以成本价n。总的结果是l总成本是构成成本的总和。唯一的非零成本来自于对象的分配和从内存中读取;所有其他操作都被认为是无成本的,就像在I/O模型中一样。

F10图10。在ICMM上模拟ICFP。模拟需要大小为4 ×的缓存+k×B为一个常数k。分配和迁移是使用分代复制垃圾收集来管理的,这需要2 ×要管理的缓存字活动对象。可以在不访问主存的情况下评估托儿所中对象的活性,因为在函数式语言中,较老的对象不能引用较新的对象。复制集合将保留对象的分配顺序,这是我们分析所需要的。因为模拟可以将同一个抽象块中的两个对象分离为相邻的块,所以每次加载两个块,需要2 ×ICMM上缓存的额外单词。一个额外的B读缓存的字需要使用一个摊销参数来说明控制堆栈所需的空间,并且需要固定数量的块来分配程序本身在内存中的位置。

季图11。矩阵相乘。

回到顶部


©2015 0001 - 0782/15/07 ACM

允许为个人或课堂使用部分或全部作品制作数字或硬拷贝,但不得为盈利或商业利益而复制或分发,且副本在首页上附有本通知和完整的引用。除ACM外,本作品的其他组件的版权必须受到尊重。允许有信用的文摘。以其他方式复制、重新发布、在服务器上发布或重新分发到列表,都需要事先获得特定的许可和/或费用。请求发布的权限permissions@acm.org传真(212)869-0481。

数字图书馆是由计算机协会出版的。版权所有©2015 ACM, Inc.


没有发现记录

登录为完全访问
»忘记密码? »创建ACM Web帐号
文章内容:
Baidu
map