同步语言于20世纪80年代创立,用于建模、设计和实现实时关键反应系统。随着被控制系统的复杂性不断增加,执行速度成为一个重要标准。与此同时,处理器在核心数量上的增长超过了速度的提升。因此,我们正在寻求一种并行执行方式,兼顾效率和安全性。
同步语言始终将并行性纳入其建模的表达能力中。它们的编译主要针对电路或顺序代码的生成。所有这些语言都具有形式语义,使得代码的正确分布成为可能。然而,保留这种语义可能会成为生成代码效率的障碍,特别是在需要保留系统全局时间概念的情况下。
我们感兴趣的语义模型是Kahn网络的功能性数据流模型。这些网络模拟了通过无界队列进行通信的分布式计算器。在这种框架下,分布不需要任何同步或外部信息。通过考虑通信队列的历史,Kahn语义允许抽象出实际执行过程,同时保证计算的功能确定性。
在最初的三种同步语言中,只有Esterel是命令式的,而非数据流。Signal语言以建模为导向,是关系式的。Lustre是第一个功能性数据流同步语言。它的第一个指称语义已经类似于Kahn语义。Caspi和Pouzet关于同步Kahn网络的研究最终将Lustre与Kahn语义联系起来,用merge替换了current原语。这导致了高阶同步功能性语言Lucio Synchrone的诞生。
从这一脉络中诞生了Heptagon,其第一个版本名为MiniLustre,旨在通过一个极简语言进行自动机的源到源编译。Heptagon是一种一阶功能性语言,其编译器是一个学术原型,与工业工具Scade相关。后者广泛应用于设计关键嵌入式系统的行业。
得益于其Kahn语义,Heptagon程序可以类比为Kahn网络。通常,Heptagon中的每个函数调用都可以理解为一个独立的进程,通过队列与程序的其他部分进行通信。在一般模型中,队列的大小无法限制。同步语言通过时钟标记逻辑时刻的数据流存在,确保所有生成的值在同一时刻被消费。因此,Heptagon程序具有同步Kahn语义,确保网络中的队列在时刻之间为空。在这种情况下,即使网络不同步,也可以保证使用单槽队列执行。因此,一旦程序被分割,分布本身就不再是问题,其效率则更为关键。
确保效率涉及两个相互依赖的方面。首先,计算之间需要有足够的解耦:计算之间的依赖关系存在延迟。其次,计算的粒度需要足够大:计算时间与通信频率的比率要高。然而,同步语义和Heptagon程序的时钟恰恰反映了相反的情况。它们允许程序员满足于一个时刻的解耦,并且在每个时刻最多计算一个值。此外,时刻通常很短,以确保系统能够快速反应。
为了获得性能提升,工具Ocrep采用静态数据流分析来优化生成代码的控制和通信。在这种框架下,程序员决定计算的位置,但计算器之间的解耦和同步是自动的。某些SIGNAL程序的分布可以通过通用工具SYNDEx或Polychrony实现。
从这些工作中,我们得出了两个结论。
首先,我们希望程序员能够直接在源代码中控制并行性。他们必须能够掌握在哪些时刻进行通信或同步。我们提出的解决方案是在Heptagon中使用futures。它们为程序员提供了这种能力,同时仍然是可以在不改变程序指称语义的情况下删除的注解。
第二个结论是,计算的粒度是一个深刻的问题,特别是涉及数据依赖性、时钟选择和模块化编译的问题。Heptagon与其前辈一样,限制了可以编写的Kahn网络,使得这三个问题可以分别处理。为了更好地理解这些元素之间的联系,我们回到了Kahn网络。我们的主要成果是定义了有序反应网络的子类。这些网络是唯一可以通过时钟模块化描述其行为的网络,而不限制调用上下文。这些网络具有一种最大粒度的时钟签名。为了表达这一点,我们引入了整数时钟,描述在单个时刻内通信的多个值。随后,我们应用这些成果,重新审视Heptagon、SIGNAL、LUCID SYNCHRONE的策略,并提出对LUCY-n的完全模块化分析,这是最忠实于Kahn网络的同步语言。