流水线范例 - 2023.2 简体中文

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 简体中文

流水线是您日常生活中常用的概念。造车厂生产线就是一个典型的例子,其中每一项具体任务通常都是由一个独立且唯一的工作站来完成的,如安装引擎、安装车门和安装车轮。各工作站各自对一辆不同的车并行执行自己的任务。当某一辆车执行完某一项任务后,它就会移至下一个工作站。完成各项任务的时间差可通过“缓冲”(将一辆或多辆车暂存在各工作站之间的空间内)和/或“停滞”(暂时中止上游工作站的操作)来加以调整,直至下一个工作站变为可用为止。

假设组装一辆车需要执行 3 项任务 A、B 和 C,这 3 项任务分别需要 20、10 和 30 分钟。那么,如果全部 3 项任务均由单个工作站来执行,工厂每 60 分钟才能输出一辆车。通过使用 3 个工作站组成的流水线,该工厂 60 分钟即可输出第一辆车,随后每 30 分钟再输出一辆新车。正如此示例所示,流水线并不会降低时延,即单个项穿越整个系统的总时间。但它会增加系统吞吐量,即,第一个项完成后处理新的项的速率。

由于流水线的吞吐量不可能优于其最慢的元素,因此程序员应尝试在各阶段间拆分工作和资源,以使各阶段耗用相同时间来完成自己的任务。在上述车辆组装线示例中,如果 3 项任务 A、B 和 C 各自耗时 20 分钟,而不是分别耗时 20、10 和 30 分钟,那么时延将仍为 60 分钟,但每隔 20 分钟(而不是 30 分钟)即可完成一辆新车。下图显示了承担制造 3 辆车任务的假想生产线示例。假定任务 A、B 和 C 各耗时 20 分钟,那么顺序生产线将需要 180 分钟才能生产 3 辆车。而流水线式生产线只需 100 分钟即可生产 3 辆车。

生产第一辆车所耗费的时间为 60 分钟,称为流水线的迭代时延。生产完第一辆车后,后两辆车各自只需 20 分钟,这称为流水线的启动时间间隔 (II)。生产三辆车所耗费的总时间为 100 分钟,称为流水线的总时延,例如:总时延 = 迭代时延 + II * (项数 - 1)。因此,改善 II 即可改善总时延,但不影响迭代时延。从程序员视角来看,流水线范例可适用于设计中的函数和循环。确定初始建立时间成本后,可将实现 II 为 1 设为理想的吞吐量目标,例如,初始建立时间延迟过后,在流水线的每个周期都有输出可用。在以上示例中,初始建立时间延迟 60 分钟过后,每隔 20 分钟就有一辆车可用。

图 1. 流水打拍

流水打拍是经典的微观级别架构最优化,可应用于多个抽象层。前文通过生产者使用者范例解释了任务级别流水打拍。这一概念同样适用于指令级别。这实际上是使生产者使用者流水线(和串流)保持填满并繁忙的关键。仅当每项任务都高速率生产/使用数据,故而需要指令级流水打拍 (ILP) 时,生产者使用者流水线才能保持高效。

由于流水打拍长期使用相同资源来执行相同功能,因此需要有关每项任务时延的完整信息,故而被视作为静态最优化。有鉴于此,低级指令流水打拍方法无法应用于数据流类型的网络,因为在此类网络中任务的时延是输入数据的函数,故而可能未知。下一章节中将详解如何利用介绍的这三种基本范例来对不同类型的任务并行度进行建模。