LabVIEW性能和内存管理(中文)
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
元素同址操作结构
• 七种边界操作类型:
– – – – – – – 数组索引/替换 数组拆分/替换子数组 解绑/捆绑簇 解绑/捆绑波形 变体与元素转换 原位输入/输出边界节点 数据值参考读/写
休眠
• 当节点“进入休眠”时,它将自身置于等待队列上,然后返回到执行 系统 – 例如,队列,子VI调用,调试等. • 当它完成等待时,从等待队列释放并放回执行队列 • 有时VI会通过停止执行并返回队列来将执行权交给其它VI – 例如,While循环 • 队列元素跟踪进度,以便他们可以在停止的地方重新执行
自下而上
同址信息通过调用层次结构自下而上传递
Branched wire
Copy because of increment
No copies required Increments array in place
显示缓冲区分配
同址优化示例
对波形数组的每个元素进行操作
这是一个如何使用“显示缓冲区分配”工具来提高性能的示例。从层次结构的高层 开始,可以使用“显示缓冲区分配”工具查看这些波形被复制三次。为了优化这个, 我们需要深入到每个子VI并修复它们,使它们同址运行。
同址操作
• 确定何时需要进行复制
– 数组和簇的权重高于其他类型
• 算法在执行之前运行
– 不知道数组或字符串的大小
• 依赖于程序的顺序方面
– 分支机构可能需要副本
确定何时需要进行复制的算法称为“同址”操作。该算法在VI中普遍存在并尝试找 到可以减少数组和簇复制的最佳代码方式。在执行之前“同址”操作已经确定,因 此就不知道一个数组是否大于另一个数组。
Clump 2 Sleeping
LabVIEW块运算
• 上图显示的块表示程序框图的开始和结束。当两个“循环”执行时, 该块是“休眠”,同时它会被“唤醒”以结束VI(两个除法函数)。 在有一个LabVIEW执行系统情况下,VI会生成执行代码。在VI的数据空 间中,每个块有一个记录,称为Q元素。Q元素可以放在一个称为 “runQ”的队列上,LabVIEW执行系统使用它来安排相关的代码段。
首选执行系统
• 一些节点必须在UI线程中运行 • 每个VI可以指定首选的执行系统 – 默认值为“与调用者相同”
一些节点具有首选的执行系统。最常见的首选执行系统是UI线程。一些节点必 须在UI线程上运行。例如,VI中属性节点、VI 中调用节点以及VI引用节点必须 在UI线程中运行。(此限制不适用于用于DAQ采集,LV类或其他类型的属性/调 用节点。)另外,每个VI可以指定首选的执行系统。默认值为“与调用者相 同”,这意味着VI可以在任何执行系统中运行。
LabVIEW执行系统使你的代码自动并行运行。在其它编程语言中如果需要并行运 行代码必须手动管理线程,但是LabVIEW的编译器和执行系统在可能的情况下一 起并行运行代码。 大多数情况下,执行系统的细节是无关紧要的,因为系统能够在没有干预的情况 下自动优化执行程序,但有些时候了解细节有助于理解执行系统的工作方式,以 便于提高程序性能。
LabVIEW数据流编程模型的值语义意味着每条线都对其自己的数据副本进行操作。 子VI和内置函数还创建其数据的副本。制作副本的好处是两个代码分支可以独立 操作数据。无需锁定。
Hale Waihona Puke Baidu
如何优化
理论上5份成为1份复印操作
Copy
Output is “inplace” with input
我们前面的值语义示例表明可能有多达5个副本的数组。顶部分支被标记为需要一个 副本,因为它将修改数组进入+操作。底部分支被优化以使用相同的数组用于*运算和 +运算符的输出。 LabVIEW已将5个副本优化为1个副本。因为有两个分支都想写回数 组,因此理想的解决方案是需要复制一个数组,而不管何种语言。
通常LabVIEW代码中的一个节点必须等待某些事情,然后才能继续。例如,队列或子VI可 能被另一个线程使用,或者在调试时单步执行。在这些情况下,该队列元素的VI代码将被 放入正在等待处理的等待队列中。在将其放入等待队列之后,VI代码返回到它正在运行的 执行系统线程,以便另一段代码可以运行。这被称为协作多任务。当等待队列上的代码片 段准备好再次运行时,它就从等待队列中取出,然后放回到执行系统队列。最终(可能立 即)该队列元素将被再次从执行队列中取出并运行。 有时VI会自动停止执行,以允许其他代码运行。这是为了防止长的循环占用所有的执行时 间。当这种情况发生时,VI代码简单地返回到执行系统,根据需要立即将其放回队列。在 其他代码有机会运行之后,这段VI代码将再次从队列中取出并运行。 每当一段VI代码由于某种原因必须进入休眠状态时,该代码的队列元素会跟踪它停止的地 方,以便下次调度时它可以在同一个地方开始。
LabVIEW的执行系统
• 系统工作就像一个线程池 – 程序工作就是一个队列 – 一系列线程从队列中提取程序执行代码 • 工作(队列元素)就是执行代码片段 • 每一个队列就是一个执行系统 – 用户界面I – 标准 LabVIEW执行系统就像一个线程池。线程池是线程 – 仪器I/O 的集合,共同完成从共享队列中提取的一系列工作。 在LabVIEW中,工作被称为“队列元素”,每一个元 – 数据采集 素都代表一段需要被执行的VI代码。 – 其它1 在LabVIEW中,实际上有6个执行系统,每一个系统 – 其它2 都有自己独立的队列。此外每一个定时循环都有自 己独立的执行系统。 – 与调用方相同 – 定时循环
第一个子VI“同址”操作
changes into…
这里我们可以使用元素同址操作结构使子VI“同址”执行。如果LabVIEW版本没有 元素同址操作结构,那么可以通过将输入波形连接到右侧束波形节点(所谓的“魔 术模式”)的顶部端子来获得相同的效果。这给LabVIEW的同址操作一个提示,希 望这两个波形同址操作。
•
•
•
优先级
• 子VI优先级影响执行系统中该VI的队列元素的优先级。 • 优先级较高的队列元素首先被执行 • 优先级设置不影响执行系统线程本身的优先级: – 执行系统可能会抢占整个线程来运行线程相对于另一 个执行系统(或其它进程) – 使用定时循环更可靠地控制优先级。
子程序优先级
• 子程序优先级设置不是实际的优先级。它不是改变队列元素 的优先级,子程序优先级使整个VI是一个单独的块,它保证 在开始执行时不会进入休眠。这意味着您不能调用任何可能 导致VI在子程序VI中进入休眠的功能,并且不能在VI中切换执 行系统。您只能调用也标记为子程序优先级的其他子VI。在 子程序VI中运行的所有代码都是串行的:在子程序VI中没有 并行性。 • 子程序还有另外一个有助于最高优先级应用程序的功能,右 键单击一个子VI并且从快捷菜单中选择遇忙时忽略子程序调 用,如果子程序正在另外一个线程运行时,执行系统会跳过 调用。这一功能可帮助执行系统在时间紧迫的循环中安全跳 过子程序的执行操作,避免了等待完成子VI而导致的延时。 如果跳过了子VI的执行,所有子VI在前面板上的显示控件的 输出将还原为默认值。
LabVIEW的执行系统
• 每一个执行系统有多个线程 • 例外:用户界面只有一个线程
下图显示的是执行系统如何工作的模型。模型中为每一个执行系统(3个) 创建了一个队列。放在队列里面的数据代表需要编译的VI的执行代码。当一 个VI准备运行时,LabVIEW将其放入对应执行系统的队列中。 每一个执行系统有一个或多个线程。每一个线程都有一个循环,这个循环 从队列中提取并执行队列元素代码。用户界面执行系统只有一个线程,但 是其它的执行系统都有多个线程并共享同一个队列。当VI的代码并行运行时, 代码在执行系统的不同线程中被并行处理。
LabVIEW的执行系统
LabVIEW块运算
Clump 0 Clump 1 Clump 0
Clump 2
LabVIEW块运算
• LabVIEW使用抢先式和合作式的多线程机制。在编译过程中,LabVIEW分析VI 以定位可以在所谓的块中一起执行的节点组。每个优先级和执行系统组合都 有一个运行队列数据结构,保留哪些块可以一起运行。当执行系统激活线程 时,执行系统从运行队列检索并执行块。当执行系统完成运行时,它在运行 队列上存储满足输入条件的附加块。这就允许程序框图在任何可用的执行线 程中运行。如果程序框图具有足够的并行性,则它可以在所有线程中同时执 行。LabVIEW不会将代码块永久分配给特定线程。LabVIEW可以在下次运行VI 时使用不同的线程执行程序块。 由LabVIEW安排,每个块产生一段代码。在一个块中,LabVIEW不提供并行性。 在块与块之间,LabVIEW可以使用其执行系统进行多任务。
切换执行系统
• 当节点想要运行但是在错误的执行系统中时,它使队列元素“进入睡眠”并在另一个 执行系统中唤醒。这意味着代码将停止执行,并将其放在一个运行它的执行系统队列 中。当其他执行系统有时间时,它会将元素拉回队列并执行它。此转换需要时间,因 此它可能是性能问题的原因。 为了避免这种情况,应该尽量避免不必要的UI代码(如VI属性节点等),并为子VI指定 首选执行系统选项为“与调用者相同”。有两种情况可能需要为VI使用特定的首选执行 系统: 1:如果VI有UI代码,那么该代码必须在UI线程中运行。当你使用“与调用者相同”时, 可能最终运行在一个执行系统而不是UI线程。这意味着VI必须切换执行系统以获取UI线 程。然后,VI必须返回到它在调用UI线程之前启动的相同执行系统,因此它将必须进行 执行系统切换。如果这发生在一个循环中,那么它就会显着影响性能。如果将该VI标记 为首选的UI线程,则调用者可以在调用之前切换到UI线程。这可能意味着切换仅在循环 之前和之后发生,而不是每次发生。 2:如果VI具有长时间运行的高优先级循环,用于处理类似数据采集的任务,那么您可 以将该VI标记为在其他执行系统(仪器I / O,数据采集,其他1或其他2 ),以便它不必 与其他VI竞争执行系统的时间。注意,如果你不是在实时操作系统上运行,你仍然需要 担心操作系统调度程序。使用定时循环来控制优先级将更可靠,并且在实时操作系统 上这样做是确保您的代码以正确的优先级运行的最可靠的方法。
第二个子VI“同址”操作
changes into…
第三个子VI“同址”操作
changes into…
最终结果:内存缓冲点隐藏
一旦打开这些子VI并修复了副本,然后保存它们(包括顶级VI),并再次使用显示缓 冲区分配工具,可以验证内存缓冲点是否消失。注意,必须重新编译Vis以更新缓冲 区分配显示。可以通过运行VI,保存VI或按住Ctrl键并单击运行箭头来执行此操作。
内联VI
• 优先更换子程序优先级 • 当调用者被编译时,整个程序框图被插入调用者:零调用 开销
– 零调用开销
• 仍然可以包含并行性 • 允许更多的编译器优化 • 限制:
– 无前面板访问 – 不是所有节点都允许 – 强制调用者在每次修改子VI时重新编译
连线语义
• 每根导线都是一个缓冲内存器 • 分支创建副本
LabVIEW的性能和内存管理
目标
• 理解LabVIEW的执行系统 • 学习通过以下方式提高性能:
– 减少数据备份 – 减少总的内存使用
• 理解VI执行属性
LabVIEW的执行系统
• LabVIEW的执行系统是LabVIEW中负责实际运行代码的部 分 • 支持自动并行运行 • LabVIEW的独特性 – 其它编程语言需要手动线程管理
Clump 1 Sleeping
Clump 0 Sleeping
Completion of diagram: Divide nodes, display of indicators, then VI exit.
Clump 2
Bottom For Loop Indicator is updated Clump 0 Scheduled Sleep...
•
LabVIEW块运算
Clump 1
Top For Loop Indicator is updated Clump 0 Scheduled Sleep...
Clump 0
Start of diagram: Reads controls, then schedules Clumps 1 and 2 Then sleeps...