Following the Data, Not the Function: Rethinking Function Orchestration in Serverless Computing

Following the Data, Not the Function:Rethinking Function Orchestration in Serverless Computing


2 Background and Motivation

  • 介绍了无服务器计算
  • 讨论了当前无服务器平台中功能编排的局限性
2.1 Serverless Computing
  • 允许开发人员专注于应用程序逻辑,而不必管理服务器资源
  • 高可伸缩性和操作简单性
  • 采用“按需付费”的计费模型:开发人员只有在调用其功能时才计费且功能运行时是以细粒度计量的,例如在主要的无服务器平台中为1毫秒
  • 推动了大量传统的“服务化”应用程序迁移到无服务器平台
    • 批分析
    • 视频处理
    • 流处理
    • 机器学习
    • 微服务
2.2 Limitations of Current Platforms

当前的无服务器平台采用面向函数的方法来编排和激活无服务器工作流的功能:每个函数被视为一个单独的单元,函数之间的交互在工作流中单独表达。

表达能力有限
  • 尽管当前面向函数的编排支持简单调用模式的工作流,但它变得不方便或无法表达更复杂的功能交互,如表1所总结。 这是因为当前的函数编排假定数据流的方式与在工作流中调用函数的方式相同,并且函数通过直接调用它们以立即处理而将其整个输出传递给其他函数。 这些假设不适用于许多应用程序,因此开发人员求助于创建变通方法。

  • 例如,数据分析作业中的“shuffle”操作涉及两个阶段(例如,“map”和“reduce”阶段)函数之间的细粒度、所有对所有的数据交换。 如图所示 1(左),阶段1中的函数的输出数据被洗牌,并基于输出键有选择地重新分配给阶段2中的多个函数。 然而,调用函数的方式与输出数据的流动方式不同:只有在Stage-1完成后,工作流才能并行调用Stage-2的所有函数。 在当前的无服务器平台中,开发人员必须通过外部存储手动实现如此复杂的数据洗牌调用[48,58],这既不灵活也不高效。

  • 另一个例子是批处理流分析作业,其周期性地调用函数来处理在时间窗[39,72]期间连续接收的数据,如图所示 1(右)。 无服务器工作流不能有效地表达这种调用模式,因为当数据到达时,函数不会立即触发,因此开发人员不得不依赖其他云服务(例如AWS Kinesis[7])来批量数据以进行周期性的函数调用[27-29]。 注意,即使使用最新的有状态工作流(例如,Azure持久函数[16]),可寻址函数也需要保持运行才能接收数据。 正如我们将在§6.5中所示,部署一个长时间运行的函数不仅会导致额外的资源配置成本,而且会导致不令人满意的性能。

可用性有限。
  • 当前的无服务器平台为函数之间的数据交换提供了各种选项。 函数可以通过消息代理共享存储同步异步地交换数据[6,10,23,30,48,66]。 它们还可以处理来自各种来源的数据,例如嵌套函数调用消息队列或其他云服务[22]。

  • 缺乏一种最佳的方法来在函数之间交换数据,这使得无服务器应用程序的开发和部署变得非常复杂,因为开发人员必须找到自己的方法来有效地在函数之间传递数据[52],这些方法可以是动态的和非常琐碎的; 因此,降低了无服务器平台的可用性。
    为了说明这个问题,我们比较了AWS lambda中的四种数据传递方法:

    • a)直接调用函数(lambda)
    • b)使用AWS step functions(ASF)执行双函数工作流
    • c)允许函数访问内存中的Redis存储以进行快速数据交换(ASF+Redis)
    • d)配置AWS S3在数据创建时调用函数(S3)[31]。

请添加图片描述

图 2比较了这四种方法在不同数据量下的延迟。

  • Lambda对于传输小数据很有效;
  • ASF+Redis对于大数据量的传输是高效的;
    每种方法支持的最大数据量差异很大,只有S3方法可以支持几乎无限(但速度较慢)的数据交换。 因此,没有一种方法可以适用于所有场景,开发人员必须仔细分析其应用程序和无服务器平台的数据模式,以优化交互功能之间的数据交换性能。

更糟糕的是,函数之间交换的数据量取决于工作负载,工作负载可能是不规则的或不可预测的。 因此,在交互函数之间交换数据可能没有最佳的固定方法开发人员必须编写复杂的逻辑来在运行时选择最佳方法。 开发人员还需要考虑交互成本。 以前的工作强调了在使用不同的存储共享中间数据时,I/O性能和成本之间的微妙权衡[48Pocket:Elastic ephemeral storage for serverless analytics,58Scalable analytics on serverless
infrastructure.],这进一步加剧了可用性问题。 总之,这些常见的实践为开发人员带来了真正的无服务器体验,因为他们仍然必须处理服务器和平台特性。

适用性有限。

现有的无服务器应用程序通常对延迟不敏感。 这是因为当前的无服务器平台通常有几毫秒或几十毫秒的功能交互延迟(§6.2),当更多的功能在应用程序工作流中链接在一起时,这种延迟就会累积起来。 例如,在AWS STEP函数中,每个函数交互导致的延迟超过20 ms,而6个函数链的平台引起的总延迟超过100 ms,这在许多对Latency sensive的应用程序中可能是不可接受的[45]。 此外,由于当前的无服务器平台不能有效地支持不同大小的数据在函数之间的共享(如前所述),它们不适于数据密集型应用程序[8,23,42,45,58,66]。 总之,上述特征极大地限制了当前无服务器平台的适用性。


3 Data-Centric Function Orchestration

在本节中,我们将使用一种新的数据中心方法来解决当前函数编排实践的上述限制。 我们将在后面的§4中描述如何将这种方法应用于开发新的无服务器平台。

3.1 Key Insight

正如§2.2中所讨论的,当前的函数编排实践只指定了函数之间的高级调用依赖关系,因此对这些函数如何交换数据几乎没有很好的控制。 特别是,当前的实践假设函数流和数据流之间的紧密耦合。 因此,当一个函数返回其结果时,工作流不知道该结果应该如何使用(例如,全部或部分,直接或有条件,立即或稍后)。 为了解决这些问题,一个有效的无服务器平台必须允许工作流的功能之间进行细粒度的数据交换,同时为功能调用和数据交换提供统一而高效的方法。

  • 提出了一种新的以数据为中心的功能编排方法。 我们注意到中间数据(即函数返回的结果)通常是短暂的和不可变的[48,67]:在它们生成后,它们等待被消耗,然后变得过时。

  • 因此,我们将数据消耗显式化,并使其能够触发目标函数。 因此,**开发人员可以指定何时以及如何将中间数据传递给目标函数,并触发它们的激活,**从而驱动整个工作流的执行。

  • 由于中间数据一旦生成就不会更新[48,67],因此使用它们来触发函数不会导致一致性问题。

以数据为中心的编排通过三个关键进展解决了当前实践的局限性。

  • 首先,它打破了函数流和数据流之间的紧密耦合,因为数据不必遵循函数调用的确切顺序。 它还支持对数据消耗的灵活和精细的控制,因此表达了一组丰富的工作流模式(即,丰富的表现力)。
  • 其次,以数据为中心的编排为函数调用和数据交换提供了统一的编程接口,避免了开发人员通过大量外部服务实现复杂逻辑以优化数据交换(即高可用性)的需要。
  • 第三,知道中间数据何时以及如何被消耗为无服务器平台调度器优化功能和相关数据的局部性提供了机会,从而可以有效地支持延迟敏感数据密集型应用(即广泛的适用性)。
3.2 Data Bucket and Trigger Primitives

请添加图片描述

数据桶。 为了方便以数据为中心的函数编排,我们设计了一个数据桶抽象和一个触发器原语列表。 图 3概述了如何触发函数。 无服务器应用程序创建一个或多个保存中间数据的数据桶。 开发人员可以用触发器配置每个bucket,这些触发器指定数据何时以及如何调用目标函数并由它们使用。 执行工作流时,源函数直接将其结果发送到指定的桶每个bucket检查配置的触发条件是否满足(例如,所需的数据已经完成并准备好被消费)。 如果是,则桶自动触发目标函数并将所需数据传递给它们这个过程发生在所有桶中, 这些桶共同驱动整个工作流的执行。

我们为桶设计了各种触发原语,以指定如何触发函数。 功能间的交互模式大致可分为三类:

  • 直接触发器原语(即,立即) 允许一个或多个函数直接使用关联桶中的数据。 此原语没有指定的条件,并且一旦数据准备好使用,就立即触发目标函数。 这个原语可以轻松地支持顺序执行或并行调用多个函数(扇出)。
  • 条件触发器原语 在满足开发人员指定的条件时触发目标函数。
    • ByBatchSize:当关联的bucket积累了一定数量的数据对象时,它触发函数。 它可以用于以类似于Spark流的方式启用批处理流处理[28,29]。
    • ByTime: 它设置一个计时器,并在计时器到期时触发函数。 然后将所有累积的数据对象作为输入传递给函数。 它可以用来执行常规任务[39,72]。
    • BYName:当bucket接收到指定名称的数据对象时,它触发函数。 它可用于通过Choice[12]启用条件调用。
    • BySet:当一组指定的数据对象全部完成并准备使用时,它触发函数。 它可以用来启用组装调用(扇入)。
    • Redundant(冗余):它指定存储在桶中的n个对象,当其中的任意k个可用并准备使用时触发函数。 它可用于执行冗余请求和执行延迟绑定,以缓解散乱现象并提高可靠性[49,59,68]。
  • 动态触发器原语。 与静态配置触发器的前两个类别不同,动态触发器原语允许在运行时配置数据模式。
    • DynamicJoin:当一组数据对象准备就绪时,它触发组装函数。 可以在运行时动态配置数据集。 它支持像AWS步骤函数中的“map”那样的动态并行执行[13]。
    • DynamicGroup:它允许bucket将其数据对象划分为多个组,每个组可以由一组函数使用。 基于对象的元数据(例如,对象的名称)动态地执行数据分组。 一旦一组数据对象就绪,它们就会触发相关联的函数集。

动态原语对于实现一些广泛使用的计算框架是至关重要的,例如MapReduce(在当前的无服务器平台中很难支持它,因为它需要在每个阶段触发并行函数,并优化它们之间的精细的、所有对所有的数据交换[47,48,58],参见§2.2中的讨论)。 这里,我们的DynamicGroup原语为这些问题提供了一个简单的解决方案。

请添加图片描述
如图所示 4(左),当map函数将中间数据对象发送到关联的bucket时,它还指定每个对象属于哪个数据组(即,通过指定它们的关联键)。 一旦映射函数全部完成,桶就会触发reduce函数,每个函数都消耗一组对象。

我们开发了一个新的无服务器平台,称为Pheromone信息素,它实现了前面提到的数据桶抽象和触发器原语。 信息素的设计将在§4中详细说明。 表1列出了当前信息素平台中所有支持的触发器原语。 与AWS步骤函数(ASF)相比,信息素支持更复杂的调用模式,并为复杂的工作流提供更丰富的表达能力(参见§6.5中的案例研究)。 请注意,信息素的触发器原语并不限于表1中列出的那些。 如果需要,我们为开发人员提供了一个公共接口,以便为他们的应用程序实现定制的原语。 附录A.1详细描述了如何实现这样的定制原语。

3.3 Programming Interface

我们的信息素无服务器平台目前接受用C++编写的函数,并具有支持更多语言的功能(参见§7)。 费洛蒙还提供了一个Python客户机,开发人员可以通过该客户机编写函数交互。

功能接口。 按照通常的做法,开发人员通过
handle()接口实现他们的函数(请参见图5),这类似于C++的main函数,只是它将用户库作为第一个参数。 用户库提供了一组API(参见表2),允许开发人员对中间数据对象进行操作。 这些API使开发人员能够创建中间数据对象(EpheObject),设置它们的值,并将它们发送到桶中。 还可以通过在调用send_object()时设置输出标志将数据对象持久化到持久存储中。 当bucket接收到对象并决定触发下一个函数时,它会自动将相关对象打包为函数参数(参见图5)。 函数还可以通过get_object()API访问其他对象
请添加图片描述

请添加图片描述
配置桶触发器。 开发人员通过我们的Python客户机指定中间数据如何触发工作流中的功能。 客户端使用§3.2中描述的原语创建桶并在桶上配置触发器。 然后,函数可以通过使用表2中列出的API创建、发送和获取对象来与桶进行交互。

请添加图片描述
请添加图片描述

作为一个例子,我们引用一个流处理工作流[39]如图所示 4(右)。 该工作流首先过滤传入的广告事件(即预处理),并检查每个事件属于哪个活动(即query_event_info)。 然后,它将返回的结果存储到bucket,并定期调用一个函数(即聚合)来计算每秒钟每个活动的事件。 图 6给出了配置bucket触发器的代码片段,该触发器周期性地调用聚合函数,其中使用指定目标函数和触发时间窗口的原语元数据创建Bytime触发器(第4行)开发人员可以选择指定函数失败时的重新执行规则,例如,如果bucket在100毫秒内没有收到query_event_info的输出,则重新执行query_event_info函数(第5行)。 我们将在§4.4中描述重新执行容错。 附录A.2给出了部署此工作流的完整脚本。
总之,我们的数据桶抽象触发器原语编程接口方便了以数据为中心的功能编排,使开发人员能够方便地实现他们的应用程序工作流,表达各种类型的数据模式函数调用。 此外,统一编程接口还避免了从各种外部服务(如消息代理、内存数据库和持久存储)提供的许多API中进行临时选择的需要


4 Pheromone System Design

本节介绍信息素的设计,这是一个支持以数据为中心的功能编排的新的无服务器平台。

4.1 Architecture Overview

信息素在一群机器上运行。 图 7展示了体系结构概述。 每个工作节点遵循来自本地调度器的指令,并运行多个执行器,这些执行器根据需要加载和执行用户功能代码。 工作节点还维护一个共享内存对象存储区,该存储区保存由函数生成的中间数据。 对象存储提供了一个数据桶接口,通过该接口,函数可以在一个节点内以及与其他节点有效地交换数据。 它还将必须与远程持久键值存储同步的数据,如Anna[70]。 当新数据添加到对象存储区时,本地计划程序检查关联的桶触发器。 如果满足触发条件,本地调度器将在全局协调器的帮助下本地或远程调用目标函数,全局协调器在工作节点以外的单独机器上运行。
请添加图片描述

4.2 Scalable Distributed Scheduling

我们设计了一个两层的分布式调度方案来将信息素扩展到一个大的集群中。 具体地说,外部请求首先到达全局协调器,全局协调器将请求路由到工作节点上的本地调度器。 只要有可能,本地调度器就调用后续函数在本地执行工作流,从而减少调用延迟。

请添加图片描述

节点内调度。
  • 在信息素中,本地调度程序使用bucket触发器尽可能在本地调用函数
    - 调度器启动工作流的第一个函数并跟踪其执行状态。
    - 当预期的数据对象被放入相关联的桶中并准备使用时,下游函数立即被触发。 图8(左)显示了本地调度器在本地运行工作流时如何与执行器交互。
    - 执行器将数据状态(例如,桶中本地对象的就绪状态)与本地调度器同步,然后本地调度器检查相关的桶触发器,并在满足触发条件时调用下游函数。 调度器和执行器之间的低延迟消息交换是通过节点上的共享内存对象存储来实现的。
- 本地调度器根据执行器的状态做出调度决策。 调度器只将函数请求路由到没有运行任务的空闲执行器,**避免了每个执行器中的并发调用和资源争用(类似于AWS Lambda[9]中的并发模型)。** 
- 当执行器第一次收到请求时,它会从本地对象存储中加载函数代码,并将其**保存在内存中**,以便在后续调用中重用。 
热启动
- **在多个空闲执行器的情况下,调度器优先考虑那些已经加载了功能代码的执行器,以启动热启动。**
  • 来自过载节点的延迟请求转发。
    • 如果本地调度器接收的请求超过本地执行器的容量,调度器将它们转发给全局协调器
    • 全局协调器将它们路由到其他资源充足的工作节点。
    • 调度器不是立即转发那些超过的请求,而是等待一个可配置的短时间周期:如果在此期间有任何本地执行器可用,则请求的函数启动,请求在本地得到服务。
    • 其基本原理是,由于无服务器函数的寿命很短,所以执行器变得可用通常只需要很少的时间[64],加上信息素具有微秒级的调用开销(§6.2)。 这种延迟调度已经证明对于改善数据局部性是有效的[75]。
节点间调度。
  • 全局协调器不仅将请求从重载节点转发到非重载节点,而且驱动大型工作流的执行,
  • 该工作流需要跨多个工作节点运行,这些工作节点共同承载工作流的许多功能。 如果没有全局视图,则无法由单个本地计划程序进行编排。
  • 作为图 8(右)显示,协调器从多个工作节点收集大型工作流功能的相关联的桶状态,并根据需要触发下一个功能。
  • 每个节点在任何更改时立即与协调器同步本地bucket状态,以便协调器维护一个最新的全局视图
  • 当协调器决定触发函数时,它还将此消息更新给相关工作人员,这些工作人员相应地重置本地桶状态。 这确保了函数调用既不会遗漏也不会重复。
  • 注意,一些bucket触发器(例如Bytime)只能在具有全局视图的协调器上执行; 在这里,工作节点只向协调器更新它们的本地状态,而不检查触发器条件。
  • 以数据为中心的编排自然改善了节点间调度中的数据局部性。 协调器使用本地调度器报告的节点级知识做出调度决策,这些知识包括缓存的函数、空闲执行器的数量以及与工作流相关的对象的数量。 然后,它将请求调度到一个工作节点,该节点具有足够的热执行器和最相关的数据对象。
用分叉协调器扩展分布式调度**没读懂。
  • 信息素采用无共享模型来显著降低局部调度器和全局协调器之间同时的频率,从而获得高的可扩展性。
  • 具体地说,它将工作流编排任务划分在分叉协调器之间,每个协调器管理一组不相交的工作流。 在执行工作流时,负责的协调器将相关的bucket触发器发送到选定的一组工作节点,并将调用请求路由到它们。 一个工作节点可以运行多个工作流的功能。 对于每个工作流,其数据和触发器状态仅与负责的协调器同步。 这种设计大大减少了通信和同步开销,并且可以通过运行处理协调器故障并允许客户机定位特定工作流的协调器的标准群集管理服务(例如,ZooKeeper[5,44])来实现。 然后,客户端可以与此协调器交互,以配置数据触发器并发送请求。 这个过程由提供的客户端库自动完成,并且对开发人员是透明的。
4.3 Bucket Management and Data Sharing

函数之间的数据交换,重点阅读看能不能结合到其他有状态无服务器

接下来我们将描述费洛蒙如何管理桶中的数据对象,以及如何在函数之间实现快速的数据交换。

Bucket management.
  • 费洛蒙使用节点上的SharedMemory对象存储来维护数据对象,这样函数就可以通过指针直接访问它们(即表2中的EpheObject)。
  • 当源函数通过send_object()将数据对象放入bucket时,它就被标记为就绪。 桶可以分布在其负责的协调器和多个工作节点上,
  • 其中每个Worker跟踪本地数据状态,而协调器持有全局视图(§4.2)。
  • 桶状态同步只需要在负责的协调器和workers之间进行,因为不同worker的本地状态只跟踪他们的本地对象,并且是不相交的。
Pheromone garbage-collects
  • 在相关的调用请求沿着工作流被完全服务之后,收集工作流执行的中间对象。
  • 如果工作流跨多个工作节点执行,负责的协调器会通知每个节点上的本地调度器从其对象存储区中删除相关联的对象。
  • 当工作节点的本地对象存储用完内存时,远程键值存储以增加数据访问延迟为代价来保存新生成的数据对象。以后,当有更多的内存空间可用时(例如,通过垃圾收集),节点将相关联的桶重新映射到本地对象存储。
  • 如果数据对象由于系统故障而丢失,信息素会自动重新执行源函数以使其恢复(详情见§4.4)。

缺点:回放开销。思考:可不可以通过其他方式容错?

Fast data sharing.
  • 由于中间数据是短暂且不可变的[48,67],我们用它们的持久性来换取快速的数据共享和低资源占用
  • 通过节点上的SharedMemory对象存储,Peromone可以通过将数据对象的指针传递到目标函数,实现本地函数之间的零复制数据共享,从而避免了大量的数据复制和序列化开销。

思考:那容错呢?假如SharedMemory对象存储宕机或者掉电

  • 为了有效地将数据传递给远程函数,信息素可以在节点之间直接传递数据对象。 一个函数将数据对象的**元数据(例如,定位器)**打包成发送到远程节点的函数请求。
  • 远程节点上的目标函数使用这样的元数据直接检索所需的数据对象。
  • 与使用远程存储器进行跨节点数据共享相比
    • 我们的直接数据传输避免了不必要的数据复制,从而减少了网络和存储开销。
    • 虽然远程存储方法可以确保更好的数据持久性和一致性[23,65,66],但不需要中间数据对象。

啥意思,没读懂

  • 只有当数据被指定为持久时,信息素才会将数据对象与持久的键值存储同步(请参见表2中的send_object())。
    请添加图片描述

  • 我们进一步优化,以争取更高效的跨节点数据共享。 默认情况下,数据对象以原始字节数组的形式发送,以避免与序列化相关的开销,从而显著提高传输大型对象的性能(参见§6.2中的图12)。

  • 费洛蒙还实现了在节点之间传输小数据对象的快捷方式:**它在节点间调度期间转发的函数调用请求上附带小对象(参见§4.2)。 此快捷方式节省了一次往返行程,**因为目标函数不需要从源函数中额外检索数据对象。 此外,Peromone在每个工作节点上运行I/O线程池,以提高跨节点数据共享性能。

4.4 Fault Tolerance

信息素支持各种类型的系统部件故障。

  • 1、如果执行器失败或工作节点上的数据对象丢失,信息素会重新启动失败的函数以重现丢失的数据并恢复中断的工作流。 这可以通过配置桶触发器轻松实现,
  • 2、如果在指定的超时时间内没有收到预期的输出,则桶触发器将重新执行源函数。

费洛蒙提供了API,开发人员可以在配置bucket触发器时使用这些API指定自定义的函数重新执行规则。 图 6给出了一个如何做到这一点的例子(第5行)。

re_exec_rules = ([('query_event_info ',EVERY_OBJ)], 100)

附录A.1提供了更多的实现细节。 这种以数据为中心的方法将故障处理逻辑功能调度逻辑解耦,因为调度器不需要跟踪每个功能的运行时状态。

  • 3、信息素还将调度器状态(例如,工作流状态)使用cheackpoint容错机制存储到到本地对象存储区,这样它就可以从工作节点上的调度器故障中快速恢复。

Checkpoints容错机制,Checkpoints可以将同一时间点作业/算子的状态数据全局统一快照处理,包括前面提到的算子状态和键值分区状态。当发生了故障后,Flink会将所有任务的状态恢复至最后一次Checkpoint中的状态,并从那里重新开始执行。

  • 4、如果整个worker节点崩溃,信息素会在其他worker上重新执行失败的工作流。
  • 5、费洛蒙还使用标准群集管理服务(如ZooKeeper)处理失败的协调器,如§4.2所述。

5 Implementation

  • 我们已经在CloudBurst[66]上实现了信息素,这是一个轻量级、性能良好的无服务器平台。
  • 我们重新架构了CloudBurst并用5K行C++代码实现了信息素的关键组件(图7)。
  • 为了便于部署,这些组件被打包到Docker[18]镜像中。
  • 费洛蒙的客户端是用400行Python代码实现的。
  • 与CloudBurst一样,Feromone在Kubernetes[24]集群中运行,以方便容器管理,
  • 并使用Anna[70,71]作为持久的键值存储。Anna[70,71]是一个自动伸缩键值存储。
  • 在每个worker节点上,我们在容器之间挂载一个共享的内存卷,用于快速数据交换和消息传递。
  • 执行器加载函数代码作为动态链接库,由开发人员预先编译并上传到费洛蒙。 信息素的整个代码库在[25]中是开源的。

6 Evaluation

在本节中,我们通过AWS EC2中的集群部署来评估信息素。 我们的评价回答了三个问题:

  • How does Pheromone improve the function interactions
    (§6.2) and ensure the high scalability (§6.3)?
  • Can Pheromone effectively handle failures (§6.4)?
  • Can developers easily implement real-world applications
    with Pheromone and deliver high performance (§6.5)?
6.1 Experimental Setup

**Cluster settings.**我们在EC2集群中部署信息素。

  • 协调器运行在C5.xLarge实例上,每个实例有4个VCPU8 GB内存
  • 每个工作节点都是一个C5.4xLarge实例,有16个VCPU32 GB内存。 worker节点上的执行器数量是可配置的,我们根据实验的要求对其进行调整。 我们最多部署8个协调器51个工作节点,并在同一个US-EAST-1A EC2区域中的独立实例上运行客户机。

Baselines. We compare Pheromone with four baselines.

  • 1)CloudBurst:作为一个提供快速状态共享的开源平台,CloudBurst[66]在调度上采用早期绑定:它在服务请求之前调度工作流的所有功能,并实现函数之间的直接通信。 它还使用函数并置缓存。 由于费洛蒙的集群设置类似于CloudBurst的集群设置,我们使用相同的集群配置和资源部署这两个平台。
  • 2)Knix:Knix[23]是Sand[33]的一个改进,它通过将工作流的函数执行为同一个容器中的进程来提高功能交互性能。 消息传递和数据共享可以通过本地消息总线远程持久存储来完成。
  • 3)AWS步骤函数(ASF):我们使用ASF Express Workflows[14]来编排函数实例,因为它实现了比ASF标准工作流[14]更快的函数交互。 由于ASF有传输中间数据的大小限制(参见图2),我们使用Redis[6],一种快速的内存存储服务,在函数之间共享大型数据对象。
    请添加图片描述
  • 4)Azure持久函数(DF):与ASF相比,DF为函数交互提供了更灵活的支持。 它允许开发人员用程序代码表达工作流,并提供实体函数[16],可以按照参与者模型[35,53]管理工作流状态。 我们包括DF来研究这种expressive性编排方法是否能获得令人满意的性能。

其中CloudBurst,Knix和ASF的目标是优化工作流的功能交互,而DF提供了丰富的expressive。 注意,对于两个商业平台,即ASF和DF,我们不能控制编排运行时。 为了进行公平的比较,我们配置了各自的Lambda和Azure函数,使函数实例的数量与信息素中的执行器的数量相匹配。 每个函数实例和执行器的资源分配也保持相同。 在我们的实验中,所有功能都被预热,以避免所有平台中的冷启动。

6.2 Function Interaction

各种模式下的函数调用。 我们首先评估在没有任何有效负载的情况下调用no-op函数的开销。 我们考虑三种常见的调用模式:顺序执行(例如,两个函数链)、并行调用(扇出)和组装调用(扇入)。 我们改变并行和汇编调用所涉及的函数的数量,以控制并行度。 图 9显示了在这三种模式下调用无操作函数的延迟。 每个延迟条被进一步分解为外部调用和内部调用的开销。 前者测量从请求到达到工作流完全启动之间的延迟,后者测量遵循指定模式在内部触发下游功能的延迟。 在信息素中,外部调用延迟主要是由于请求路由的开销,大约需要200μs[19]。 注意,在Feromone和CloudBurst中可以本地或远程调用函数,因此我们在图9中分别对它们进行了测量。请添加图片描述
图 9(左)比较了在五个平台上测量的双函数链的调用延迟。 信息素明显优于其他。 特别是,Feromone的基于共享内存的消息传递(§4.3)只带来不到20微秒的开销,将本地调用延迟降低到40微秒,比CloudBurst快10倍。 与其他平台相比,延迟的改善变得更加显著(例如,140×Knix,450×ASF)。 当调用远程函数时,Feromone和CloudBurst都需要网络传输,从而导致类似的内部调用延迟。 然而,由于CloudBurst需要在服务请求(早期绑定)之前调度整个工作流的功能,CloudBurst对外部调用的开销比信息素高,从而导致整体性能更差。

图 9(中间)和(右)分别显示了并行调用和汇编调用下的调用延迟。 我们还通过在每个worker上配置12个执行器来评估费洛蒙和CloudBurst中的跨节点函数调用,从而在运行16个函数时强制远程调用。 信息素不断地获得最佳性能,并且在所有情况下只产生亚毫秒级的延迟,即使对于跨节点函数调用也是如此。 相比之下,CloudBurst的早期绑定设计导致函数调用的延迟随着函数数量的增加而延长。 Knix和ASF在并行和汇编场景中都有很高的调用开销。 在基线中,DF的性能最差,我们在以后的实验中排除了它。

Data transfer.我们接下来评估在函数之间传输数据时的交互开销。 图 10显示了在信息素、CloudBurst、Knix和ASF中具有不同数据大小的两个函数链的调用延迟。 我们对信息素和CloudBurst的本地和远程数据传输进行了评估。 对于Knix和ASF,可以通过工作流或共享存储(即RIAK和Redis)进行数据传输,我们报告两种选择中的最佳选择。

对于本地数据传输,信息素能够实现零拷贝数据共享,无论数据大小,都能带来极低的管理费用,例如,100兆数据为0.1毫秒。 相比之下,CloudBurst需要数据复制和序列化,这会导致更长的延迟,特别是对于大型数据对象。 对于远程数据传输,Feromone和CloudBurst都支持跨工作节点的直接数据共享。 费洛蒙使用了一个优化的实现,没有(de)序列化,使其比CloudBurst更高效。 总体而言,与信息素相比,CloudBurst中的序列化开销在大规模数据交换下支配着本地和远程调用的延迟,这削弱了数据局部性的性能优势:节省了跨网络传输100 MB数据的成本,仅将延迟从844 ms减少到648 ms。 图 10还显示Knix和ASF引起的延迟要长得多。 虽然Knix在数据对象较小时的性能优于ASF,但ASF在传递大数据时变得更高效,因为在我们的实验中,它被配置为使用快速Redis内存存储来传输大数据。

我们进一步评估了并行调用和汇编调用下数据传输的开销。 对于并行调用,我们测量一个函数调用并行下游函数并将数据传递给所有这些函数的延迟; 对于汇编调用,我们测量汇编函数中第一个对象的传输和所有对象的接收之间的延迟。 图 11显示了这两种调用模式在不同数据大小下的延迟。 类似地,对于这两种调用模式,与所有其他平台相比,Feromone不断实现更快的数据传输。

**Improvement breakdown.**为了说明我们的每一个单独的设计是如何促进性能改进的,我们分解了信息素的函数调用性能,并描述了在图中的结果 12. 具体来说,对于本地调用,“基线”使用一个中央协调器来调用下游函数(即没有本地调度器),这是今天的常见做法[11]; “两层调度”使用我们的本地调度器在同一个工作节点(§4.2)上进行快速调用,其中中间对象缓存在调度器的内存中,并被复制到下一个函数中; “共享内存”通过零拷贝数据共享进一步优化了性能(§4.3)。 图 12(上图)表明,应用两层调度可以减少网络往返,并实现比“基线”高达3.7×的时延改善。 使用共享内存可以避免数据复制和序列化,从而进一步加快数据交换速度,特别是对于大型对象(例如,1 MB),数据交换速度提高了两个数量级。

对于远程调用,“Baseline”使用持久的键值存储(即Anna[70])在跨节点函数之间交换中间数据; “直接传输”通过允许节点之间的直接数据传递来减少通信开销(§4.3),其中节点上的原始数据对象被序列化为Protobuf[26]消息,然后发送到下游函数; “piggyback&W/O ser.”通过在转发的函数请求上piggyback小对象并消除序列化,进一步优化了数据交换(§4.3)。 如图所示 12(底部),直接数据传输避免了与远程存储的交互,与基线相比,性能提高了2.6倍。 没有序列化的背驮进一步加快了小型(10 B)和大型(1 MB)对象的远程调用速度,分别提高了2倍和2.7倍。

6.3 Scalability
6.4 Fault Tolerance
6.5 Case Studies

7 Discussion and Related Work

在信息素中分离。 费洛蒙在函数调用之间提供容器级隔离,而在同一节点上运行的函数共享内存中的数据对象(§4.3)。 基于商业容器的无服务器平台通常不会将来自不同用户的功能放在一起以增强安全性[1]。 在此设置中,可以信任同一节点上的函数。 因此,用严格的数据隔离来改善I/O性能是安全的。 我们注意到当前的无服务器平台在性能和隔离之间做出了各种权衡。 例如,AWS Lambda在MicroVMS中运行函数以实现强隔离[32]; Knix将使用流程的工作流功能隔离在同一个容器中,以获得更好的性能[33]; 最近的工作为保护隐私的无服务器应用程序提出了轻量级隔离[51]。 信息素可以探索这些不同的取舍,我们留给以后的工作。
支持的语言。 Feromone目前支持用C++编写的函数,但它可以直接支持其他编程语言。 具体地说,Feromone的执行器公开数据触发器API(Tabel2),并与其他系统组件交互,并且可以作为用不同语言编写的函数的代理。 也就是说,Feromone对通过共享内存进行快速数据交换的优化可能不适用于所有语言运行时–只有那些允许直接使用字节数组而不(去)序列化的语言运行时,例如Python CTYPE,才能从Zerocopy数据共享中受益。 不管语言运行时如何,其他信息素设计仍然有效。
无服务器中的数据共享。 数据交换是当今无服务器平台普遍存在的痛点。

  • 一种通用的方法是利用共享存储来实现和优化函数之间的数据交换[37,41,42,48,55,57,58]。
  • 另一种方法是利用数据局部性来提高性能 例如,通过将工作流函数放在一个single机器上[45,50,52,65-67]。 此外,OFC[54]和FAA$T[60]为各个应用程序提供了自动伸缩缓存。 碎纸机[78]和锡安[61]将功能代码推入存储。 Wukong[38]在应用程序级别增强了基于DAG的并行工作负载的局部性。 LambData[67]使函数的输入和输出的意图显式,以改善局部性; 然而,它没有为表达和简化的函数交互提供统一的编程接口,它的性能在很大程度上取决于OpenWhisk[3,50]。

8 Conclusion

本文重新讨论了无服务器计算中的功能编排,并提出了一种新的设计范式:

  • 1)打破函数流和数据流之间的紧密耦合,
    1. 允许工作流函数之间的细粒度数据交换,
    1. 为功能调用和数据交换提供统一而高效的方法。

在这种以数据为中心的模式下,我们设计了一个新的无服务器平台费洛蒙,该平台具有丰富的表现力、高可用性和广泛的适用性。 费洛蒙是开源的,在函数调用和数据交换的延迟方面,它比当前的商业和其他开源无服务器平台的性能高出一个数量级。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Inception 架构是一种用于计算机视觉的神经网络架构,它通过使用不同尺寸的卷积核来捕捉图像中的不同级别特征。近年来,研究者们对 Inception 架构进行了重新思考,提出了许多改进版本,如 Inception-v2 和 Inception-v3。这些改进版本通过更深层次的网络结构、更高效的卷积层、更强大的正则化方法等来增强模型的性能。 ### 回答2: "重新思考计算机视觉中的Inception架构"是指对计算机视觉中的Inception架构进行反思和重新设计的过程。 在计算机视觉中,深度学习网络被广泛应用于图像分类、物体检测和语义分割等任务。Inception架构是一种流行的深度学习架构之一,它的特点是使用了一系列不同尺寸的卷积核和Inception模块,以提取不同尺度下的图像特征。 然而,随着计算机视觉任务的不断发展和挑战的出现,人们开始重新思考和改进Inception架构。对Inception架构的重新思考主要包括以下几个方面: 首先,针对Inception架构中的参数数量过多和计算复杂度高的问题,人们提出了一些改进方法。例如,通过降低Inception模块中卷积核的维度和参数数量,可以减少计算量,提高网络的训练和推理效率。 其次,人们提出了一些新的模块和网络结构,以解决Inception架构在某些任务上的性能限制。例如,ResNet和DenseNet等网络结构通过引入残差连接和稠密连接,解决了深度网络中的梯度消失和信息丢失问题。 此外,人们还关注如何将Inception架构与其他架构进行融合,以进一步提升计算机视觉任务的性能。例如,人们将Inception架构与注意力机制相结合,以提高目标检测和图像分割的准确性。 总之,"重新思考计算机视觉中的Inception架构"是一个不断演进的过程。通过反思和优化Inception架构,人们可以提高计算机视觉任务的性能、准确性和效率,推动计算机视觉领域的发展。 ### 回答3: 重新思考计算机视觉中的初始架构(rethinking the inception architecture for computer vision)是指对计算机视觉模型中的初始网络架构进行重新思考和改进。 计算机视觉是人工智能领域中的一个重要分支,它致力于让计算机能够像人一样理解和处理图像和视频。而计算机视觉模型的架构对于模型的性能和效果具有很大的影响。 Inception架构是一种经典的计算机视觉模型架构,最早由谷歌在2014年提出。它通过使用多尺度的卷积层和并行结构来提高模型的性能和效果。然而,随着技术的发展和需求的变化,原始的Inception架构可能存在一些限制和缺陷。 重新思考Inception架构意味着我们需要针对当前的计算机视觉任务和要求,重新设计和改进Inception架构。有几个方面可以考虑: 首先,我们可以通过引入更先进的卷积技术和结构来改善模型的性能。例如,可以使用Dilated Convolution(空洞卷积)来增加感受野,或者使用Depthwise Separable Convolution(分离卷积)来减少参数量和计算量。 其次,我们可以将其他经典和有效的架构和思想与Inception架构相结合,以进一步提升性能。例如,可以引入残差连接(Residual Connection)来加快训练速度和提高模型的泛化能力。 此外,我们还可以针对具体的计算机视觉任务,对Inception架构进行特定的优化。例如,对于目标检测任务,可以加入适应性池化层(Adaptive Pooling Layer)来获得更好的位置和尺度信息。 总之,重新思考Inception架构是一个不断改进和优化计算机视觉模型的过程。通过结合新的技术、思想和任务需求,我们可以进一步提高计算机视觉模型的性能和效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值