跳转到内容

流水线概念#

本主题介绍图像数据如何流经从 VisualApplets 设计生成的 FPGA 硬件。阅读本主题后,您将了解设计中的模块和链接如何构成流水线结构、数据如何进出流水线、为什么大多数阶段会立即转发数据、并发 FPGA 处理如何影响吞吐量,以及哪些 link 属性会限制数据速率。

有关形式化数据流模型,请参阅《用户手册》中的 Data Flow。有关如何端到端构建和验证设计,请参阅 From Empty Design to Running Applet 教程主题。

您可以使用运算符库中的 operators 构建 VisualApplets 设计。放置的每个 operator 实例都是一个 module。Module 公开 input 和 output 端口。您可以使用 links 连接端口。图表中将每个链接显示为箭头。

VisualApplets 设计中的模块和链接共同构成了图像处理 pipeline。Build 会将该图实现为帧采集卡 FPGA 上的硬件阶段。处理顺序遵循连接顺序。分支和合并定义了图中的并行路径和汇合点。

带有分支和合并点的流水线

一旦输入数据可用,每个模块就会开始处理。当计算完成且输出未被阻塞时,它会将结果转发到其输出 link 上。在运行时,此行为由模块生成的 FPGA 逻辑实现,而不是由 VisualApplets 中的图形符号实现。因此,管道结构定义了数据在哪里拆分、在哪里汇合,以及哪些模块串行运行还是 Parallel 运行。

像素不会一步作为完整图像进入帧采集卡。相机将它们依次传输到采集路径中 — 或者 applet 内部的图像源将它们依次生成。然后,这些像素以相同的顺序流经流水线阶段:

在流水线中移动的像素

关键术语

将像素想象成道路上的汽车:它们沿着路径互不干扰地行驶。在任何时刻,不同的汽车(像素)位于道路(流水线阶段)上的不同位置。道路本身就是您在 VisualApplets 设计中布线的流水线结构。Build 完成后,该道路是帧采集卡 FPGA 上的硬件,而不是 VisualApplets 编辑器内部的路径。

在这个类比中,Parallelism 是道路上的车道数:车道越多,更多的汽车(像素)就能同时向前移动。

流水线输入和输出#

每个流水线至少包含一个将数据馈送到设计中的 source 以及一个或多个离开 FPGA 处理路径的 sinks。Source 和 sink 通常是 M 型运算符。可用的运算符取决于您的目标硬件平台。

输入#

数据可以通过以下方式进入流水线:

  • 来自相机或其他图像源:特定于平台的相机运算符将来自连接相机的连续像素流传送到采集路径中。
  • 在 Applet 内部生成:诸如 CreateBlankImage 或 CoefficientBuffer 之类的运算符无需实时相机即可创建或回放图像数据。您可以将这些源用于测试模式、从主机上传的参考数据或不从相机采集的设计。

信号路径也可以从数字输入开始(例如通过 GPI)或从小应用程序内部的信号源开始。有关在流控制下相机信号源与可停止的小应用程序内部信号源的区别,请参见 可停止与不可停止的数据流 教程主题。

输出#

处理后的结果可以通过以下方式离开流水线:

  • DMA 传输至主机: DmaToPC 算子通过直接内存访问将图像数据传输到主机 PC Memory。这是在主机软件中采集处理后图像的常规路径。
  • 通过 GPO 发送信号: GPO 算子驱动采集卡上的数字输出引脚。对于主机 PC 外部的触发、状态或其他硬件控制信号,请使用此路径。
  • 事件发送至主机: EventToHost 和 EventDataToHost 算子向主机发送软件事件。主机应用程序通过 Framegrabber API 接收这些事件,并可以对小应用程序中的条件作出反应。 EventToHost 在信号输入的上升沿触发事件,且不携带有效载荷。 EventDataToHost 触发事件并附带可配置的数据有效载荷。
  • 仅寄存器信息:某些结果作为可读值保留在采集卡上。诸如 GetStatus 之类的算子存储的值可供主机软件作为动态参数进行读取。当应用程序仅需状态或测量数值时,无需图像流或 DMA 传输。

一个设计可以组合使用其中几个输出。例如,一个分支可以通过 DmaToPC 发送图像, GPO 而另一个分支在满足条件时置位引脚或引发主机事件。

有关算子的详细信息,请参阅算子参考中的 DmaToPC、算子参考中的 GPO、算子参考中的 EventToHost、算子参考中的 EventDataToHost 以及算子参考中的 GetStatus。

无缓冲流水线流#

大多数模块不会在内部存储完整图像。它们会在计算出输出值后,一旦信息可用便立即转发。

并非所有算子都会在数据到达输入端时立即输出结果。 M 型 算子尤其会延迟输出。这些不仅是缓冲区算子(例如 LineBuffer 或 ImageFifo ),许多滤波器和同步算子也是 M 型的。延迟的大小取决于算子。有关详细信息,请参阅 算子类型与同步 教程主题和 延迟 教程主题。

缓冲区算子存储数据,直到下游模块能够接收数据为止。

这种无缓冲的行为可保持较低的latency。当同一帧的其他像素仍在相机输入端时,某个像素就已经可以到达输出端。采集、处理和 DMA 在时间上可以重叠。

关键术语

可以将生成的 FPGA 管线想象成一个带有分支和阀门的管道系统。只要有空间,水就会流过管道。缓冲区算子就像一个小水库,当排水跟不上进水时它就会积蓄液体。

有关延迟如何沿路径累积,以及带宽和延迟之间的区别,请参见 Latency 教程主题。

硬件中的并发处理#

在图像采集卡 FPGA 上,所有管线阶段都同时运行。这不同于典型的 CPU 程序(主要按顺序执行指令)。

当一个 FPGA 模块处理某个像素时,其他模块会处理路径更远处的不同像素。管线填满后,多个模块将同时处理同一幅图像。FPGA 会将您的 VisualApplets 设计实现为专用硬件,其结构与管线图相匹配。

关键术语

在从 VisualApplets 设计生成的 FPGA 硬件中,处理路径被实现为图像采集卡上的专用硬件逻辑。数据穿过这些硬件阶段,就像传送带上的物品一样。CPU 通常会加载整块数据并按顺序逐步处理。

有关构建的小程序与可编辑的 *.vad 设计之间关系的详细信息,请参见 VisualApplets Fundamentals 教程主题。

吞吐量和瓶颈#

Throughput 是指流经管线的数据持续速率。在 VisualApplets 设计中,它与生成的 FPGA 硬件链路上的 bandwidth 密切相关。

设计中的模块数量不会降低吞吐量。所有生成的 FPGA 级都可以并行运行。并行分支的数量也不会降低吞吐量。分支会增加硬件资源,但它们本身不会降低单个路径上的数据速率。正如您在以下两个设计中所看到的,两个采集路径可以使用不同数量的模块,但仍能提供相同的吞吐量:

具有相同 Throughput 的两个设计

Throughput 取决于以下因素:

  • Link capacity:连接模块之间能够传输多少数据。容量由模块和链路的参数化决定,尤其是 Parallelism、Bit Width 和最大图像尺寸,以及 Base Design Clock。有关链路 Property 和模块参数的详细信息,请参阅参数化教程主题。
  • Downstream readiness:模块是否能够持续接收数据。如果模块无法永久接收数据(例如因为缓冲区已满或后续模块阻塞),流控会停止数据流,从而导致阻塞、背压或两者兼有。
  • 运营商限制:部分运营商无法处理其输入链路提供的全部带宽。《运营商参考手册》记录了每个受影响运营商的这些限制。

链路带宽(以像素速率(像素/秒)表示)遵循以下公式:

带宽 = Parallelism × Base Design Clock

此像素速率公式不包含位宽或内核大小。更宽的位宽或更大的内核会增加每个时钟周期的数据量(位或值),这对 DRAM 访问和 FPGA 资源至关重要,但不会改变此像素速率值。有关 DRAM 数据宽度,请参阅“内存元件教程”主题。有关内核与像素速率带宽的关系,请参阅“使用内核教程”主题。

基础设计时钟取决于您的图像采集卡平台。请在设备资源中查找该值。

最大图像尺寸虽然没有出现在像素速率公式中,但它们仍然影响着设计:它们限制了流水线可以处理的图像尺寸。除了并行度和位宽之外,这些链路属性还必须与您的相机或线扫描源相匹配。

路径的瓶颈在于该路径上的最低带宽。设计的整体吞吐量始终受限于这个最窄点。一条带宽受限的链路或一个带宽受限的运营商会限制同一路径上所有上游设备的吞吐量。因此,吞吐量取决于路径上的最低带宽以及下游模块是否持续接收数据。

设计指南

并行度和链路属性的配置应仅满足相机或线扫描源所需的速率。进一步提高这些值会消耗额外的 FPGA 资源,并且如果瓶颈已在其他组件,则不会提高吞吐量。

有些算子会改变输入和输出之间的并行度。另一些算子则会减少像素数量,例如通过裁剪图像。因此,所需的输出带宽可能与输入带宽不同。在可能的情况下,算子会自动调整并行度。如果无法调整, VisualApplets 报告设计规则检查错误。

有关计算和调整并行性的信息,包括如何计算设计所需的带宽以及如何在操作员合并流时排除带宽瓶颈的示例,请参阅Parallelism教程主题和排除瓶颈教程主题。

在设计中可视化吞吐量#

您可以使用“链路信息”和“吞吐量”标志,在设计中显示并行性和数据吞吐量。使用工具栏中的以下按钮激活这些标志:

在设计中激活链路信息和吞吐量标志

因此,您的设计中会显示 Link Info 和 Throughput 标志:

Link Info 和 Throughput 标志

比较沿路径的值以找出最窄的链路。该链路即为该路径的瓶颈,除非下游的某个算子无法跟上处理速度。

信息

Throughput 标志并未显示所有性能限制。例如,当多个 DRAM 算子共享相同的内存接口时,由 Shared Memory 导致的 DRAM 带宽限制将不会反映在吞吐量显示中。其他 DRAM inefficiencies 以及阻塞和潜在的 deadlocks 也不会显示。有关 Shared Memory 使用和 DRAM 带宽规划的指导,请参阅 Memory Elements 教程主题。有关死锁的详细信息,请参阅 Operator Types and Synchronization 教程主题。

吞吐量和数据格式取决于链路 Property 和模块参数。除了上面介绍的与容量相关的 Property(Parallelism、Bit Width 和最大图像尺寸)外,其他典型 Property 还包括图像协议和 Color Format。

Link properties 会在整个管道中进行 propagate。您可以在相机输出链路上或在早期处理阶段设置许多属性。它们适用于所有下游链路,直到某个算子对其进行更改。模块参数必须与所连接链路上的 Link properties 匹配。因此,上游链路上的更改会影响所有后续算子,直到另一个算子重置属性为止。

有关 Link properties 和传播规则的完整列表,请参阅用户手册中的 Parameterization 教程主题和 Rules of Links。

image protocol 定义了链路上数据流的结构。VisualApplets 支持不同的数据类型/流格式:

协议 典型用途
VALT_IMAGE2D 带有行结束和帧结束标记的二维图像,例如来自面阵相机的图像。帧内的行可以具有不同的长度。
VALT_LINE1D 无尽的或连续的线扫描数据,例如来自线扫描相机的线扫描数据。
VALT_PIXEL0D 没有图像尺寸信息的非结构化连续像素流。
VALT_SIGNAL 在每个时钟周期都有效的单比特信号,例如在触发逻辑中。

像素以扫描顺序在管道中移动:在行内从左到右,然后在帧内从上到下。某些相机源使用不同的顺序。当您的源不符合此惯例时,请使用适当的算子来纠正顺序。

有关图像协议和像素顺序的更多信息,请参阅用户手册中的 Image Protocols, Image Dimensions and Data Structure。

源是否可以在流控制下暂停会影响您布线管道的方式。相机算子是 non-stoppable 源。您通常在它们后面直接放置一个缓冲区算子。有关详细信息,请参阅下文的 Flow Control, Blocking, and Backpressure 以及 Stoppable and Non-Stoppable Data Streams 教程主题。

流控制、阻塞和反压#

生成的 FPGA 管道在各阶段之间应用 flow control。当某个阶段未准备好接受更多数据时,它可以 block its input:它停止向上一阶段请求数据,并且上一阶段停止输出。这种阻塞会作为 backpressure 在管道中向后传播。请注意,只有 M 型算子才能阻塞输入。VisualApplets 中的图形模块描述了此硬件行为;它们本身不应用流控制。

假设 DmaToPC 无法以足够快的速度将数据传输到主计算机。它会不时地阻塞其输入。阻塞信号向上游传播到缓冲区算子。缓冲区在阻塞激活时停止转发数据。它存储传入的像素,并且其 Fill 水平会上升。当相机停止发送数据时,缓冲区再次排空。

带缓冲区和 DMA 的简单采集路径

缓冲区算子使以不同速率处理的阶段解耦。如果在不可停止的相机源之后没有缓冲区,则下游模块的阻塞将无法减慢相机流的速度。因此,该设计可能会未通过设计规则检查或在硬件上死锁。

有关算子类型以及阻塞在 O 型、M 型和 P 型模块上的表现形式,请参阅 Operator Types and Synchronization 教程主题。

关键术语

Blocking 意味着生成的 FPGA 阶段无法接受更多的输入数据,例如因为后续模块不接受数据或因为阶段内部的处理花费了更多时间。VisualApplets 中的模块图标代表该阶段;图标本身不等待或阻塞。
Backpressure 是其背后的机制:“压力”向后作用。如果一个阶段接收数据的速度不够快,上游阶段必须等待并且流被阻塞。实际上:下游阶段无法接受数据(例如,因为缓冲区已满),因此上游阶段会等待。
本主题中的 Bandwidth 是连接的像素速率:每秒有多少像素可以通过链路。Bit width 和内核大小会更改每个像素携带的数据量,这是一个不同的量。请参阅 Parallelism 教程主题。