Plasticine: 面向并行模式的可重配架构(上)

简介: Plasticine: 面向并行模式的可重配架构(上)

摘要


近年来,由于可重配架构有助于设计高能效加速器,迅速得到普及。由于位级(bit-level)的可重配抽象,细粒度结构(如 FPGA)传统上存在着性能和能效低下的问题。细粒度和粗粒度架构(如 CGRA)传统上都需要低级编程,并忍受漫长的编译时间。我们用 Plasticine 来解决这两个挑战,这是一个新的空间可重配架构,旨在有效执行由并行模式组成的应用程序。并行模式已经从最近的并行编程研究中脱颖而出,成为强大的高级抽象,可以优雅捕捉数据位置、内存访问模式和跨越广泛的密集和稀疏应用的并行性。


首先,我们通过观察关键应用的并行模式特征,发现这些特征适合于硬件加速,如分层并行、数据局部性、内存访问模式和控制流,从而激发我们构思了 Plasticine。基于这些观察,我们将 Plasticine 架构为模式计算单元(Pattern Compute Units)模式存储单元(Pattern Memory Units) 的集合。模式计算单元是可重配的 SIMD 功能单元的多级流水线,可以有效执行嵌套模式。模式存储单元使用分组暂存器(banked scratchpad memories)和可配置的地址解码器实现数据定位。多个片上地址生成器和 scatter-gather 引擎通过支持大量未完成的内存请求、内存合并和密集访问的突发模式,有效利用了 DRAM 带宽。Plasticine 基于 28 纳米工艺实现的芯片面积为 113 mm2,在 1GHz 时钟下的最大功耗为 49 瓦。通过使用周期精确的模拟器,证明 Plasticine 在广泛的密集和稀疏应用中比传统的 FPGA 提供了高达 76.9 倍的每瓦性能改进。


1. 简介


为了寻求更高的性能和能源效率,计算系统正越来越多的使用专门的加速器[7, 9-11, 19, 33, 44]。加速器实现了定制的数据和控制路径,以适应某一领域的应用,从而避免通用处理器中的大量灵活性开销。然而,由于设计和制造的一次性工程(NRE, non-recurring engineering)成本高,以及部署和迭代时间长,以专用 ASIC 的形式进行专业化很昂贵,因此 ASIC 加速器只适合最普遍的应用。


像 FPGA 这样的可重配架构(reconfigurable architectures) 通过在静态可编程网络互连中提供灵活的逻辑块来实现自定义数据路径,从而抵消高额的 NRE 制造成本。通过 FPGA,可以在位级(bit-level)定制数据通路,允许用户对任意数字逻辑进行原型化,并利用架构支持任意精度的计算,这种灵活性已经吸引了一些数据中心成功部署了基于 FPGA 的商业加速器[28, 29, 37]。然而,灵活性是以架构的低效为代价的。计算和网络资源的位级(bit-level)可重配带来了巨大的芯片面积和功耗开销。例如,FPGA 中超过 60%的芯片面积和功耗是用在可编程网络上[4, 5, 22, 35]。通过多个逻辑元件的长组合路径限制了加速器设计可以运行的最大时钟频率。低效率促使了粗粒度可重配架构(CGRA, Coarse-Grain Reconfigurable Architecture)的发展,其字级(word-level)功能单元符合大多数加速器应用的计算需求。CGRAs 提供密集的计算资源、电源效率以及比 FPGA 高一个数量级的时钟频率。现代商业 FPGA 架构,如英特尔的 Arria 10 和 Stratix 10 器件系列,已经发展到包括越来越多的粗粒度块,包括整数乘积器("DSP")、浮点单元、流水线互连和 DRAM 存储控制器。然而,FPGA 中的互连仍然是细粒度的,以使这些器件能够发挥其作为任意数字逻辑原型验证结构的最初目的。


image.png

表 1. 编程模型中的并行模式。


不幸的是,FPGA 和以前提出的 CGRA 都很难用。加速器设计通常造成低级编程模型和长编译时间[3, 21, 22]。大多数 CGRA 和带有粗粒度块的 FPGA 中资源的异质性进一步增加了复杂度。简化加速器开发的一个有希望的方法是用特定领域语言,这些语言可以捕捉到高级别的并行模式,如 map、reduce、filter 和 flatmap[38, 41]。并行模式已经成功用于简化并行编程和代码生成,适用于各种并行架构,包括多核芯片[27, 34, 40]和 GPU[8, 23]。最近的工作表明,并行模式也可用于从高级语言中为 FPGA 生成优化的加速器[15, 36]。在这项工作中,我们专注于开发粗粒度、可重配的架构,对并行模式有直接的架构支持,在面积、功耗和性能方面都很高效,在编程和编译的复杂性方面也很容易使用。


为此我们引入了 Plasticine,作为新的空间可重配加速器架构,为高效执行并行模式进行了优化。Plasticine 是由两种粗粒度的可重配单元组成的二维阵列: 模式计算单元(PCU, Pattern Compute Unit)模式存储单元(PMU, Pattern Memory Unit) 。每个 PCU 由一个可重配流水线组成,具有多级 SIMD 功能单元,并支持跨 SIMD 通道的转移和简化。PMU 由一个分组暂存器(banked scratchpad memory )和专用寻址逻辑及地址解码器组成。这些单元通过流水线静态混合互连(static hybrid interconnect) 相互通信,具有独立的总线级(bus-level)和字级(word-level)数据,以及位级(bit-level)控制网络。Plasticine 架构中的层次结构简化了编译器映射,提高了执行效率。编译器可以将内循环计算映射到一个 PCU 上,这样大多数操作数就可以直接在功能单元之间传输,而不需要使用 scratchpad 存储器或 PCU 之间的通信。片上 scratchpad 存储器可配置为支持流式和双缓冲访问,片外存储控制器支持流式(突发)模式和 scatter/gather 访问。最后,片上控制逻辑可配置为支持嵌套模式。


我们用基于 Scala 的硬件定义语言 Chisel[2]实现 Plasticine,使用 Synopsys Design Compiler 综合设计后得到面积估算,通过模拟轨迹和 PrimeTime 得到功率数。使用 VCS 和 DRAM-Sim2 进行精确周期模拟,在线性代数、机器学习、数据分析和图分析等领域大量密集、稀疏计算基准测试的基础上对 Plasticine 架构进行详细评估。


本文的其余部分组织如下: 第 2 节回顾并行模式中的关键概念及其硬件实现。第 3 节介绍了 Plasticine 架构并探讨了关键的设计权衡。第 4 节介绍了与 FPGA 相比,Plasticine 的电源和性能效率。第 5 节讨论相关工作。


2. 并行模式


2.1. 并行模式编程


并行模式是对传统函数式编程的扩展,包括密集和稀疏数据集合上的可并行计算,以及相应的内存访问模式。并行模式为常见计算任务提供了简单、自动的程序并行化规则,同时也通过更高层次的抽象来提升程序员的生产力。并行化带来的性能优势,加上程序员生产力的提高,使得并行模式在各种领域越来越受欢迎,包括机器学习、图形处理和数据库分析[38, 41]。以前的工作以及证明,并行模式可以在函数式编程模型中应用,为 CPU 生成可与手工优化代码相媲美的多线程 C++[40]以及为 FPGA 生成高效的加速器设计[1, 15, 36]。与 FPGA 和多核 CPU 一样,在针对 CGRA 时,数据并行性的知识对于实现良好的性能至关重要。这种隐含的知识使得并行模式成为驱动 CGRA 设计的自然编程模型。


和以前并行模式的硬件生成工作一样[15, 36],我们的编程模型基于并行模式 MapFlatMapFold HashReduce,选择这些模式是因为它们最适合硬件加速。表 1 介绍了每种模式的概念性例子,显示了同时在四个索引上进行的计算。每个模式都有一个或多个函数和一个描述该模式操作的数值范围的索引域(index domain) 作为输入。每个模式都有一个输出,并能够读取任意数量的输入集合。


Map 使用函数f为每个索引创建输出元素,f的每次执行都被保证是独立的。Map 的输出元素的数量与输入迭代域的大小相同。基于f读取的集合数量和每次读取的访问模式,Map 可以获取集合、标准元素级映射、压缩包、窗口过滤器或其任何组合的行为。


image.png

图 1. 基于 Scala 使用 Map 和 Fold 通过内积计算无约束矩阵乘法示例。


image.png

图 2. 基于 Scala 使用 FlatMap 和 HashReduce 的例子,灵感来自 TPC-H 查询 1。


FlatMap 使用函数g为每个索引产生任意数量的元素,其中函数的执行也是独立的。产生的元素被串联成一个扁平输出。有条件数据查询(例如 SQL 中的 WHERE,Haskell 或 Scala 中的 filter)是 FlatMap 的特例,其中g产生零个或一个元素。


Fold 首先充当 Map,使用函数f为每个索引生成单个元素,然后使用关联组合函数r对这些元素进行约简。


HashReduce 使用函数kv分别为每个索引生成哈希键和值。具有相同对应键的值在执行中被放到单个累加器中,使用同一个关联的组合函数r。HashReduce 可以是密集型的,即键的空间是提前知道的,所有累加器都可以静态分配,也可以是稀疏型的,即模式可以在运行时产生任意数量的键。直方图创建是一个常见的、简单的 HashReduce 的例子,其中key函数给出了直方图的堆,value函数被定义为总是"1",而combine函数是整数加。


图 1 显示了用明确的并行模式语法编写无约束矩阵(untiled matrix)乘法的例子。在这种情况下,Map 创建大小为M×P的输出矩阵,Fold 使用 N 个元素的点乘法产生这个矩阵的每个元素。Fold 的 map 函数(f2)访问矩阵 a 和矩阵 b 中的元素,并将它们相乘。Fold 的组合函数(r)定义了如何组合由f2产生的任意元素,在示例中使用求和。


图 2 给出了基于 Scala 语言中使用并行模式的示例,在并行模式实例对应的集合上定义了中缀操作符。注意,本例第 3 行的filter创建了一个 FlatMap,其索引域等于lineItems集合的大小。第 5 行的hashReduce创建了一个 HashReduce,其索引域的大小为before集合的大小。


2.2. 硬件实现需求


image.png

表 2. 编程模型组件及其对应的硬件实现需求。


并行模式提供了一组简洁的并行抽象,可以简洁表达各种机器学习和数据分析算法[8,36,38,41]。通过创建专门支持这些模式的体系架构,可以有效执行这些算法。这种并行模式体系架构需要几个关键硬件特性,下面将逐一介绍,表 2 进行了总结。


首先,所有四种模式都可以实现并行数据计算,每个索引上的操作都完全独立,一个流水线计算架构被构建成 SIMD 通道,利用数据并行性实现每周期多元素的吞吐量。此外,除了无法在循环中维持依赖,表 1 中的函数fgkv在其他方面不受限制,这意味着该架构的流水线计算必须是可编程的,以便实现这些函数。


其次,为了利用流水线 SIMD 通道提供的高吞吐量,该架构必须能够提供高片上内存带宽。在我们的编程模型中,函数中间值通常是具有静态已知位宽的标量,这些标量值可以存储在小型分布式流水线寄存器中。


集合被用来在并行模式之间进行数据通信,对集合架构的支持取决于相关内存访问模式,并通过分析用于计算内存地址的函数来确定。为了简单起见,我们将访问模式分为静态可预测线性函数模式或不可预测随机访问模式。此外,我们将访问要么标记为流式(即在静态可确定的函数执行数量中不发生数据重用),要么 tiled(即可能发生重用)。我们使用领域知识和编译器启发式方法来确定随机访问是否可能表现出重用。以前的工作显示了如何将并行模式平铺(tile)从而使用静态大小的重用窗口,并有可能提升数据的局部性[36]。


支持 tiled 访问的集合可以被存储在 scratchpad 中。为了驱动 SIMD 计算,这些 scratchpad 存储器应该尽可能支持多个并行地址流。在线性访问情况下,地址流可以通过堆叠(banking)来创建。并发随机读取可以通过本地内存的复制来支持,而随机写入命令必须顺序化并且尽量合并操作。


虽然流访问不可避免需要访问主存,但通过合并内存命令和线性访问预取数据,可以将主存读写成本降至最低,架构中的本地 FIFO 为这两种优化提供了备份存储。


本地存储器使我们能够利用应用程序的局部性,尽量减少对昂贵的主存储器的加载或数量要求[32]。本地存储器中的可重配支持增加了这些片上存储器的可用带宽,从而使计算得到更好的利用。在 scratchpad 存储器中支持双重缓冲,一般称为 N-缓冲(N-buffering),可以实现不完全嵌套模式的粗粒度流水线执行。


该架构还需要高效的内存控制器来填充本地内存并提交计算结果。与片上存储器一样,存储控制器应该专门用于不同的访问模式。线性访问对应于 DRAM 突发命令,而并行模式下的随机读写分别对应于 gather 和 scatter。


Fold 和 FlatMap 也暗示了细粒度的跨 SIMD 通道通信。Fold 需要跨通道的简化树,而 FlatMap 中的拼接最好由有效的跨通道字合并(word coalescing)硬件来支持。


最后,所有并行模式都有一个或多个相关的循环索引。这些索引可以在硬件中实现为并行、可编程的计数器链。由于并行模式可以任意嵌套,因此体系架构必须具有可编程控制逻辑,以确定每个模式何时允许执行。


虽然已经提出了许多粗粒度硬件加速器,但以前的工作所描述的单一加速器都不具备所有这些硬件特征。这意味着虽然这些加速器中的一部分可以成为并行模式的目标,但没有一个可以完全利用这些模式的特性来实现性能的最大化。传统 FPGA 也可以被配置来实现这些模式,但正如我们在第 4 节中所展示的那样,能效要差得多。我们将在第 5 节进一步讨论相关工作。


3. Plasticine 架构


Plasticine 是一个由可重配模式计算单元(PCU)模式存储单元(PMU) 组成的 tiled 结构,我们将其统称为"单元"。单元与三种静态互连进行通信: 字级标量(word-level scalar)、多字级矢量(multiple-wordlevel vector)和位级控制互连(bit-level control interconnects)。Plasticine 的单元阵列通过多个 DDR 通道与 DRAM 连接,每个通道都有相关的地址管理单元,在多个地址流之间进行仲裁,并由缓冲器支持多个未完成的内存请求和地址聚合,以尽量减少 DRAM 的访问。每个 Plasticine 组件用于映射应用程序的特定部分: 本地地址计算在 PMU 中完成,DRAM 地址计算发生在 DRAM 地址管理单元中,其余的数据计算发生在 PCU 中。请注意,Plasticine 架构是参数化的,我们将在第 3.7 节讨论这些参数的取值。


3.1. 模式计算单元(Pattern Compute Unit)


PCU 被设计为在应用程序中执行内部单个并行模式。如图 3 所示,PCU 数据路径被组织为多阶段、可重配的 SIMD 管道。这种设计使每个 PCU 实现了高计算密度,并利用了跨通道的循环级并行和跨阶段的流水线并行。


SIMD 通道的每个阶段由一个功能单元(FU, functional unit) 和相关流水线寄存器(PR, pipeline register)组成。功能单元执行 32 位字级算术运算和二进制操作,包括对浮点数和整数操作的支持。由于单个流水线阶段的功能单元以 SIMD 方式操作,每个阶段只需要一个配置寄存器,每个 FU 的结果都被写入其相关的寄存器中。每个通道中的 PR 是跨流水线阶段链在一起的,允许在同一通道内的阶段之间传播实时值。FU 之间的跨道通信通过两种类型的 PCU 内部网络实现: 一种是还原树网络,允许将多个通道的值还原成一个标量; 另一种是移位网络,允许将 PR 作为跨阶段滑动窗口从而在模版应用中复用。这两个网络都在 PR 内使用专用寄存器,以尽量减少硬件开销。


PCU 使用三种输入输出(IO)作为全局互连接口: 标量(scalar)、矢量(vector)和控制(control)。标量 IO 用于单字数据的通信,如 Fold 的结果等。每个矢量 IO 允许在 PCU 中的每个通道上通信一个字,并用于诸如读写 PMU 中的 scratchpad 存储器和在多个 PCU 之间的长管道上传输中间数据。每个矢量和标量输入都使用一个小型 FIFO 进行缓冲。通过输入端 FIFO 解耦数据生产者和消费者,并通过增强鲁棒性减少输入延迟从而简化 PCU 间的控制逻辑。控制 IO 用于通信控制信号,如 PCU 执行的开始或结束,或指示背压。


一个可重配计数器链产生模式迭代指数和控制信号以协调执行。当控制块启用其中一个计数器时,PCU 开始执行。根据应用的控制和数据依赖性,控制块可以被配置为结合来自本地 FIFO 和全局控制输入的多个控制信号来触发 PCU 的执行。控制块使用可重配组合逻辑和用于状态机的可编程计数器来实现。


3.2. 模式存储单元(Pattern Memory Unit)

image.png


图 3. 模式计算单元(PCU)架构。只展示了 4 个阶段和 4 条 SIMD 通道,并省略了一些控制信号。


image.png

图 4. 模式内存单元(PMU)架构:可配置 scratchpad、地址计算数据路径和控制。


image.png

图 5. Plasticine 芯片级架构(实际 16x8)。三个网络具有相同的结构。PCU:模式计算单元,PMU:模式存储单元,AG:地址生成器,S:交换机。


image.png

图 6. 有序、粗粒度流水线和流控制方案。


图 4 显示了 PMU 架构。每个 PMU 包含一个由程序员管理的 scratchpad 存储器,加上一个用于地址计算的可重配标量数据通路。如图 5 所示,PMU 被用来在整个 Plasticine 架构中分配片上存储器。Plasticine 对参与内存地址计算的操作和应用基础的核心计算进行了区分。地址计算在 PMU 数据通路上进行,而核心计算则在 PCU 内进行。一些观察结果促使采用了这种设计选择:(i)地址计算涉及简单的标量数学,这需要比 PCU 中的 FU 更简单的 ALU;(ii)对大多数片上访问模式来说,使用多个通道进行地址计算通常并不必要;(iii)在 PCU 内执行地址计算需要将地址从 PCU 路由到 PMU,这占用了 PCU 阶段和输出链接,并可能导致 PCU 利用率不足。


scratchpad 上有多个 SRAM 堆叠,与 PCU 通道的数量相匹配。scratchpad 周围的地址解码逻辑可以被配置为在几种堆叠模式下运行,以支持各种访问模式。Strided banking 模式支持密集数据结构上经常出现的线性访问模式。FIFO 模式支持流式访问。行缓冲(Line buffer) 模式支持类似于滑动窗口的访问模式。复制(Duplication) 模式,即内容在所有存储器中复制,提供多个读取地址通道,以支持并行的片上 gather 操作。


正如堆叠对于支持多个 SIMD 单元以维持计算吞吐量很重要,N-缓冲(N-buffering) 或广义上的双缓冲对于支持粗粒度管道也同样重要。PMU scratchpad 可以被配置成 N-buffer,并采用上述任何一种堆叠模式进行操作。N-buffer 是通过将每个 SRAM 的地址空间划分为 N 个不相连的区域来实现的。利用写和读的状态信息,在每个存储器的本地地址上增加适当偏移量,以访问正确的数据。


类似于 PCU,一个可编程的计数器链和控制块触发 PMU 执行。每个 PMU 通常包含来自生产者模式的写地址计算逻辑,以及来自消费者模式的读地址计算逻辑。根据本地 FIFO 和外部控制输入的状态,可以配置控制块,通过启用适当的计数器来分别或者同时触发写地址计算和读地址计算。


3.3. 互联(Interconnect)


Plasticine 支持通过三种方式实现 PMU、PCU 和外围元件之间的通信: 标量、矢量和控制。这些网络在传输数据的粒度上有所不同: 标量网络以字级粒度运行,矢量网络以多字级粒度运行,而控制网络以位级粒度运行。所有三个网络的拓扑结构都是相同的,如图 5 所示。所有网络都是静态配置的。网络交换机中的链接包括寄存器,以避免长线延迟。


应用程序通常包含嵌套流水线,其中外围流水线层只需要计数器和一些可重配控制。此外,由于外部流水线逻辑通常涉及某种程度的控制信号同步,因此是控制热点,需要大量控制和标量输入输出。为了有效处理外部流水线逻辑,标量和控制交换机共享同一个可重配控制块和计数器。将控制逻辑纳入交换机内,可以减少对热点的路由,以提高 PCU 利用率。


3.4. 片外存储访问(Off-chip Memory Access)


Plasticine 通过 4 个 DDR 内存通道访问片外 DRAM,每个 DRAM 通道基于芯片两侧的若干个地址生成器(AG, address generator) 访问,如图 5 所示。每个 AG 包含一个可重配标量数据路径生成 DRAM 请求,其架构与图 4 所示的 PMU 数据路径类似。此外,每个 AG 包含 FIFO 缓冲从 DRAM 发出的指令、数据和传入的响应。多个 AG 连接到一个地址聚合单元(coalescing unit) ,地址聚合单元负责 AG 之间的仲裁并处理内存请求。


AG 可以产生或密集(dense)稀疏(sparse) 的内存指令。密集请求用于批量传输连续的 DRAM 区域,通常用于读取或写入数据块。密集请求被聚合单元转换为多个 DRAM 突发请求。稀疏请求将地址流输入聚合单元,聚合单元通过聚合缓存维护已发出的 DRAM 请求元数据,并合并属于同一 DRAM 请求的稀疏地址,以尽量减少发出的 DRAM 请求数量。换句话说,稀疏内存的加载触发了聚合单元的 gather 操作,而稀疏内存的存储则触发了 scatter 操作。


3.5. 控制流(Control Flow)


Plasticine 使用分布式、分层的控制方案,尽量减少单元之间的同步,以适应网络中有限的位数连接。我们支持从高级语言结构推断出三种类型的控制器协议: (a) 顺序(sequential) 执行,(b) 粗粒度流水线(coarse-grained pipelining) ,和(c) 流式(streaming) (图 6)。这些控制方案对应于输入程序中的外循环,并决定单个单元的执行如何相对于其他单元进行调度。单元被分组为 层次分明的控制器集,同级控制器的控制方案基于其直属父控制器的方案。


在顺序执行父控制器中,任何时候都只有一个数据依赖的子节点处于活动状态,这通常应用在有循环依赖的时候。我们通过令牌(token) 强制执行数据依赖,其实现是通过控制网络路由的前馈脉冲信号。当父控制器被启用时,一个令牌被发送给所有对其兄弟节点没有数据依赖的头部(head) 子程序。在完成执行后,每个子节点会将令牌传递给其输出数据的消费者。每个控制器只有在所有依赖数据源的令牌被收集后才会被启用。来自最后一组控制器的令牌,其数据不被同级别的任何兄弟控制器所消耗,被送回给父控制器。父控制器将令牌收集起来,要么将令牌送回给头部进行下一次迭代,要么在其所有迭代完成后在自己的层次结构中传递令牌。


在粗粒度流水线中,子控制器以流水线方式执行。为了允许并发,父控制器向头部发送 N 个令牌,其中 N 是关键路径中的数据依赖子节点数量,从而允许所有子节点在稳定状态下处于活动状态。为了允许生产者和消费者在不同的迭代中对相同数据进行处理,每个中间存储器都有 M 个缓冲区,其中 M 是在其数据依赖路径上相应的生产者和消费者之间的距离。为了防止生产者溢出下行缓冲区,每个子控制器通过使用点数(credit) 跟踪可用的下行缓冲区大小来处理背压。每个生产者在生产完父代"当前"迭代的所有数据后,递减其点数。同样,消费者在消费完父代"当前"迭代的所有数据后,通过网络送回一个点数。在粗粒度流水线方案中,当每个子节点至少有一个令牌和一个点数可用时,就会被启用。


最后,流式父控制器的子控制器以细粒度流水线方式执行。这使得编译器可以通过串联多个单元形成一个大流水线来适应大型内部模式体。在流式模式中,子节点通过 FIFO 进行通信。当某个控制器的所有读 FIFO 都不为空,且所有写 FIFO 都不满时,该控制器被启用。FIFO 在消费者控制器本地,所以入队以及非空信号是通过控制网络从消费者发送到生产者的。


为了执行这些控制协议,我们使用静态可编程计数器、状态机和组合查询表来实现专门的可重配控制块,架构中的每个 PCU、PMU、交换机和存储控制器都有一个控制块。一般来说,没有任何子节点的控制器被映射到 PCU,而外部控制器被映射到交换机的控制逻辑。由于外部控制器通常有许多子节点需要同步,这种映射为外部控制器提供了较高的通信基数。Plasticine 控制方案中的层次架构和分布式通信使编译器能够利用嵌套并行模式中的多层次并行性,而只需最小的位级可重配开销。


3.6. 应用映射(Application Mapping)


我们从一个被表示为并行数据流流水线层次结构的应用开始,该应用是用一种基于并行模式的语言--Delite 硬件定义语言(DHDL, Delite Hardware Definition Language)[20]编写的。之前的工作[36]显示了以第 2 节所述的并行模式表达的应用程序如何能够自动分解为 DHDL 中的流水线,这些流水线要么只包含其他流水线的外部控制器,要么是不包含其他控制器(只包含计算和存储操作的数据流图)的内部控制器。


为了将 DHDL 映射到 Plasticine,我们首先基于用户指定的或自动调整的并行化系数展开外部流水线。然后,基于展开的结果分配和安排虚拟 PMU 和 PCU。这些虚拟单元是对 Plasticine 单元的抽象表示,有无限多的可用输入、输出、寄存器、计算阶段和计数器链。由于外部控制器不包含计算,只包含控制逻辑,它们被映射到虚拟 PCU,没有计算阶段,只有控制逻辑和计数器链。内部控制器中的计算是通过线性化数据流图和将产生的操作列表映射到虚拟阶段和寄存器来实现的。每个本地存储器映射到一个虚拟 PMU,用于计算该存储器读写地址的阶段被复制到虚拟 PMU 上。


然后,通过划分阶段将每个虚拟单元映射为一组物理单元。虚拟 PCU 被划分为多个 PCU,而 PMU 则成为一个具有零个或多个支持 PCU 的 PMU。虽然一般来说图分区(graph partitioning )是 NP-hard 问题,但每个虚拟单元的计算阶段往往远少于 200 个,而且循环依赖性非常小。这意味着,带有简单启发式的贪婪算法可以实现接近完美的物理单元分区。在我们的分区算法中,使用一个成本指标计算物理阶段的数量,每阶段的活跃变量,以及给定分区所需的标量和矢量输入/输出总线。请注意,由于我们从应用程序的完整数据流表示开始,这些通信和计算成本总是可以静态预测的。使用启发式方法,编译器会选择一个建议分区,其中所有 PCU 和 PMU 在物理上都是可实现的,并给定一些选定的 Plasticine 架构参数(PCU、PMU、阶段、流水线、总线等的数量),并使 ALU 和本地内存利用率最大化。


在分区之后,按照第 3.5 节所述,生成与控制器层次结构相对应的控制逻辑。然后,我们将虚拟硬件节点与物理硬件资源进行分层绑定,包括数据通路和控制通路的放置和路由,SIMD 单元的寄存器分配,包括将阶段映射到物理 ALU,并分配 scratchpad 和控制资源。Plasticine 的分层性质使得每层映射的节点少于 1000 个,从而极大减少了搜索空间。


给定配置和路由信息,然后生成类似于汇编语言的 Plasticine 配置描述,用于为架构生成静态配置"位流(bitstream)"。由于分层体系架构,以及计算单元之间的粗总线粒度,使得整个编译过程只需几分钟就可以完成(或失败),而生成 FPGA 配置则需要数小时。

目录
相关文章
|
13天前
|
分布式计算 Kubernetes Hadoop
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
大数据-82 Spark 集群模式启动、集群架构、集群管理器 Spark的HelloWorld + Hadoop + HDFS
78 6
|
12天前
|
缓存 监控 API
探索微服务架构中的API网关模式
【10月更文挑战第5天】随着微服务架构的兴起,企业纷纷采用这一模式构建复杂应用。在这种架构下,应用被拆分成若干小型、独立的服务,每个服务围绕特定业务功能构建并通过HTTP协议协作。随着服务数量增加,统一管理这些服务间的交互变得至关重要。API网关作为微服务架构的关键组件,承担起路由请求、聚合数据、处理认证与授权等功能。本文通过一个在线零售平台的具体案例,探讨API网关的优势及其实现细节,展示其在简化客户端集成、提升安全性和性能方面的关键作用。
45 2
|
13天前
|
分布式计算 资源调度 Hadoop
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
大数据-80 Spark 简要概述 系统架构 部署模式 与Hadoop MapReduce对比
42 2
|
16天前
|
存储 缓存 监控
探索微服务架构中的API网关模式
【10月更文挑战第1天】探索微服务架构中的API网关模式
48 2
|
1月前
|
JSON 监控 安全
探索微服务架构中的API网关模式
【9月更文挑战第22天】在微服务架构的海洋中,API网关如同一位智慧的守门人,不仅管理着服务的进出,还维护着整个系统的秩序。本文将带你一探究竟,看看这位守门人是如何工作的,以及它为何成为现代云原生应用不可或缺的一部分。从流量控制到安全防护,再到服务聚合,我们将一起解锁API网关的秘密。
|
2月前
|
C# 微服务 Windows
模块化革命:揭秘WPF与微服务架构的完美融合——从单一职责原则到事件聚合器模式,构建高度解耦与可扩展的应用程序
【8月更文挑战第31天】本文探讨了如何在Windows Presentation Foundation(WPF)应用中借鉴微服务架构思想,实现模块化设计。通过将WPF应用分解为独立的功能模块,并利用事件聚合器实现模块间解耦通信,可以有效提升开发效率和系统可维护性。文中还提供了具体示例代码,展示了如何使用事件聚合器进行模块间通信,以及如何利用依赖注入进一步提高模块解耦程度。此方法不仅有助于简化复杂度,还能使应用更加灵活易扩展。
82 0
|
2月前
|
前端开发 开发者 C#
WPF开发者必读:MVVM模式实战,轻松实现现代桌面应用架构,让你的代码更上一层楼!
【8月更文挑战第31天】在WPF应用程序开发中,MVVM(Model-View-ViewModel)模式通过分离应用程序的逻辑和界面,提高了代码的可维护性和可扩展性。本文介绍了MVVM模式的三个核心组件:Model(数据模型)、View(用户界面)和ViewModel(处理数据绑定和逻辑),并通过示例代码展示了如何在WPF项目中实现MVVM模式。通过这种方式,开发者可以构建更加高效和可扩展的桌面应用程序。
106 0
|
1月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
1月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
2天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型加速的今天,云原生技术以其高效、灵活、可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生环境下微服务治理的策略与实践路径,旨在为读者提供一个系统性的微服务治理框架,涵盖从服务设计、部署、监控到运维的全生命周期管理,助力企业在云端构建更加稳定、高效的业务系统。 ####