什么是分阶段功能(概念上)?


24

在CACM的最新文章[1]中,作者提出了分阶段功能的实现。他们使用该术语好像它是众所周知的,并且所有参考文献似乎都不是显而易见的介绍。

他们给了一个简短的解释(重点是我的和参考编号已更改;原来是22)

在程序生成的上下文中,由Taha和Sheard [2]建立的多级编程(MSP,简称暂存)允许程序员显式地将程序表达式的求值延迟到较晚的阶段(因此,暂存一个表达式)。当前阶段有效地充当代码生成器,该代码生成器组成(并可能执行)下一阶段的程序。

但是,塔哈(Taha)和谢德(Sheard)写道(重点是我):

多阶段程序是一个涉及代码生成,编译和执行的程序,所有程序都在同一进程内。多阶段语言表示多阶段程序。暂存以及因此的多阶段编程可满足对通用解决方案的需求,而这些通用解决方案无需支付运行时的解释性开销。

然后,他们继续引用了一些较旧的作品,据称这些作品表明分期是有效的,这表明该概念更古老。他们没有为该术语本身提供参考。

这些陈述似乎是正交的,即使不是矛盾的。也许Rompf和Odersky写的是Taha和Sheard提出的应用,但也许是对同一件事的另一种看法。他们似乎同意,重要的一点是程序会在运行时重新编写其自身的部分,但是我不知道这是否是必要的和/或足够的能力。

那么,什么是分期分别在此背景下举办的解释?这个词从哪里来?


  1. 轻量级模块化分段: T. Rompf和M. Odersky(2012)的一种实用方法,用于生成运行时代码和编译DSL
  2. W. Taha和T.Sheard(2000)的带有显式注释MetaML和多阶段编程

您认为这两种说法之间有什么矛盾?在我看来,他们似乎在谈论同一件事,但重点不同。
吉尔(Gilles)'所以

@Gilles我不需要运行时代码生成/编译来延迟对某些内容的评估(请参见后续内容)。很有可能这只是另一个重点(我承认问题中的那个选项),但我无法真正说出。
拉斐尔

你可以检查出朱莉娅编程语言实现和元编程文档@generated functionS:julia.readthedocs.org/en/latest/manual/metaprogramming/...
SalchiPapa

Answers:


21

据我所知,Bill Scherlis首先在本文中使用了阶段计算一词。在此之前,术语“ 部分评估 ”用于几乎相同的概念,但是分阶段计算的思想却微妙地不同。两种思想都与克莱因的Smn定理有关

如果您有一个包含两个参数的函数,但是您知道一个参数,例如m,则可以使用第一个参数的知识立即执行该函数的某些计算。然后剩下的就是一个函数ϕ mn ),其计算仅取决于第二个未知参数。ϕ(ñϕñ

部分评价的想法是计算专门功能自动。给出了原始函数的代码φ,部分评价确实静态分析以确定哪个码的比特取决于,哪些位取决于Ñ,和变换到一个函数φ '其中,由于,构建体φ 。然后可以将第二个自变量n馈送到该专用函数。ϕñ ϕñϕϕñ

上演计算的想法是考虑功能第一。它被称为“分段”功能,因为它可以在多个阶段中工作。一旦我们给它的第一个参数,它构建了专门的函数的代码φϕ。这是“第一阶段”。在第二阶段,第二个参数提供给 ϕ m,其余工作完成。ϕϕ

因此,部分评估的工作是将代码转换为普通函数ϕ的上演功能。Scherlis认为,与早期的部分评估方法相比,可以通过更通用的机制来完成此转换。现在,“分段计算”主题处理以下问题:ϕ

  • 如何定义分段功能?
  • 应使用哪种编程语言和类型系统来定义分段功能?
  • 这种语言的语义是什么?
  • 我们如何确保分段功能的连贯性和正确性?
  • 哪些技术可用于自动或半自动构造阶段功能?
  • 我们如何证明这种技术的正确性?

在实践中,分阶段计算可能非常重要。实际上,每个编译器实际上都是分阶段的计算。给定一个源程序,它构造一个经过翻译和优化的目标程序,然后可以获取实际输入并计算结果。在实践中很难编写分级计算程序,因为我们必须兼顾多个阶段并确保在正确的时间完成正确的事情。每个编写过编译器的人都在为此类问题而苦苦挣扎。也很难编写编写其他程序的程序,可能是机器语言程序(编译器),SQL查询(数据库操作)或HTML / Server Pages / Javascript代码(Web应用程序)以及无数其他应用程序。


据我所看到的,这样的区别上演计算和局部评价的形式?(有些ϕ '可以从分阶段计算中获得,而不能从部分评估中获得)。ϕϕ
塔庆丁

因此,您的意思是部分评估是对多阶段编程的一种抽象,这意味着部分评估并不意味着多阶段编程,而多阶段编程则意味着部分评估。既然可以使用部分功能进行评估,因为使用功能语言编写的数据不一定涉及多个阶段并在运行时生成代码,对吧?
denis631

1
不完全是。部分评估者将普通程序编译为两阶段程序,然后运行其第一阶段。在分阶段编程中,您可以自己编写多阶段程序。
Uday Reddy '18年

9

尽管其他答案在技术上都是正确的,但我认为它们无法正确理解计算机科学家为何对分段功能感兴趣。

通过创建暂存函数,可以定义生成程序的程序。现代实用语言理论的主要目标之一是最大限度地提高潜在的重用性。我们希望使编写不仅是有用的函数和对象的库成为可能,而且还可以通过提供更高阶的体系结构来帮助程序员。

如果我们能够摆脱所有样板代码,那就太好了。我们应该能够最小化规范语言。例如,如果我们希望事件驱动的调度程序与具有给定线程设计的其他调度程序通信,则我们应该能够紧凑地指定它,并且所有IO侦听器以及队列对象和线程连接都应能够从该规范中构建。

域语言往往是我们正在寻找的紧凑表示形式。当人们在某个域中工作一段时间时,他们使用的语言往往会丢弃大多数信息重复并成为精简规范。因此,这种分期理论倾向于成为从领域语言到执行语言的翻译系统。

从技术上讲,编译器是阶段性的,但它没有实现目标。现代登台的目的是允许构建程序,以构建程序以最大程度地重用并在可能的情况下使程序构建自动化。如果某个程序的一天功能需求是该程序,那就太好了。

请参见Czarnecki和Eisenecker撰写的“生成式编程”(ISBN-13:978-0201309775)。


@Raphael:这是第三章,介绍了有关域和重用的基础知识。甚至查看您提到的优化。FFT并不是通过分阶段提高运行速度来完成的。这样做是为了使程序员不必每次都手动计算值表,将它们复制到程序中并建立一个大列表。这是为了最大程度地减少完成的工作并重复使用基本步骤。与循环展开相同。手工操作会重复信息,并且无法重复使用。
ex0du5 2012年

这种DSL的观点似乎将升级限制在一个级别(程序内部有一个DSL编译器),对吗?
拉斐尔

1
@Raphael:这确实取决于您的观点。显然,当仅将其视为源->可执行翻译时,该概念不会增加计算能力。我们只需要为DS语言构建一个编译器就可以了。它的优势来自于迭代。当构建将来将由项目使用和扩展的库时,自然阶段会出现在库边界内。您可能有一个将对象规范转换为源以进行完全序列化的库,然后是另一个库,该库构建了基于某些调度规范的传输层...
ex0du5 2012年

1
@Raphael:分阶段更自然地可以分多个阶段进行。如果一段代码的需求随时间变化很大,而其他代码要稳定得多,则由于“剪切层”将分段分成具有更稳定接口的层,这可能是合适的。然后,您可以通过更改影响较少的系统,并采用开放式-封闭式原则的过渡形式。这些是没有数学必要性的实际问题,但这全都基于实用性。我们不需要单一的编译器语言,我们希望允许演化。
ex0du5

5

在有关文章[1]的技术性观点文章中给出了答案。正在考虑的问题是通用代码和特定代码之间的紧张区域:

程序可以编写为通用或专用程序。通用代码具有可在各种情况下使用的优势,而专用代码可能以利用执行环境的独特特性的方式编写,从而以可重用性为代价来提高效率。

当然我们要解决这种紧张关系,那就是实现通用代码特定实现:

我们可以问一个问题:是否有可能编写代码以使其具有通用性,然后在执行过程中自动将其自身专用于当前情况?

这产生了让(通用)程序在运行时重新编写以适应特定情况的想法:

结果,一个重要的研究方向涉及对语言和编译器技术的搜索,该技术可以使程序员编写通用代码,然后在运行时将它们正确有效地转换为高性能的专用代码。

我猜Java的JIT是一个很好的例子。一个特定的想法是多阶段编程,Lee对此解释如下:

在这一研究领域中,核心思想之一是分期的概念。我们想象一个程序的执行过程分为几个阶段,每个阶段都会计算出供后续阶段使用的值。因此,我们寻求的是编写程序代码,以便使这些阶段变得显而易见。如果做到这一点,那么我们可以安排将后期代码编译成代码生成器,以针对早期计算的结果进行优化。

即,“分段”是一种查看合适的功能/代码的方式,该功能/代码标识了计算/执行中的阶段,通过了解先前阶段的结果可以简化该阶段。为了正确分离阶段,在问题的第一引号中进行“延迟”计算可能是必要的副作用,但这不是重点。

Rompf和Odersky以快速傅立叶变换为例,这可能是有启发性的。


  1. 狐狸和刺猬:彼得·李(Peter Lee)的技术观点(2012)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.