20多年来,NI LabVIEW被数百万名工程师和科学家用来开发繁复的测试、测量和控制应用程序。尽管LabVIEW提供从交互式助手到可配置式用户自定义界面的各种特性与工具,却通过图形化通用编程语言(所知的G)以及相关的集成化编译器、连接器和调试工具,显得与众不同。
运用高级编程的简史
为更深入理解LabVIEW图形化编程的主要价值定位,不妨对首类更高级编程语言的某些背景加以了解。当20世纪50年代中期现代计算机时代的曙光来临之际,IBM的一个小组决定创建更实际方案,用底层汇编这门时下最现代的语言为巨大的IBM 704主机(当时的超级计算机)编程。结果诞生了FORTRAN这门用户更易识别的编程语言,它能够加快开发。
工程社区起初怀疑这种新方式能否胜过通过汇编手工编写的程序,但不久事实证明:FORTRAN生成的程序在运行时与那些通过汇编编写的程序几乎同样有效。同时,FORTRAN将程序中必要编程语句的数量减少了20倍,因此它也总是被当成第一门更高级的程序语言。自然,FORTRAN很快为科技圈接受并持续发挥影响。
50年后,这段奇闻仍具有重要意义。首先,50多年来,工程师一直希望更轻松快捷地通过计算机编程解决问题。其次,工程师选来诠释任务的编程语言,已趋于更高级别的抽象。此类教导有助解释G为何能在1986年出现以来获得极度推崇与广泛使用;G代表相当高级的编程语言,其目的是:在提高用户生产效率的同时,确保执行速度与层级较低的语言(如:FORTRAN、C、C++)几乎相同。
LabVIEW: 图形化、数据流编程
LabVIEW与其他大多数通用编程语言存在两点主要差异。首先,进行G编程需要将程序框图上的图标连接在一起,之后程序框图被直接编译为计算机处理器能够加以执行的机器码。采用图形而非文本代表自身的G,包含与最传统语言相同的编程概念。例如,G包含所有标准构造,如:数据类型、循环、事件处理、变量、递归、面向对象的编程。
图1. G中的While循环由图形化循环直观代表,它会一直执行到停止条件获得满足为止。
第二项主要区别在于:由LabVIEW开发的G代码,其执行时遵照的规则是数据流,而不是大多数基于文本的编程语言(如:C和C++)中更传统的过程化方式(即,被执行的命令序列)。G等数据流语言(以及Agilent VEE、Microsoft Visual Programming Language、Apple Quartz Composer)将数据作为支持各类程序的主要概念。而数据流执行模式是由数据驱动的,或者说是依赖于数据的。是程序内节点间的数据流动,而非文本的顺序行,决定着执行顺序。
这种差别起初也许不大,影响却是非凡的,因为它让程序组件间的数据路径成为开发者关注的重点。LabVIEW程序中的节点(即:函数、循环等结构、子程序……)获取输入数据、处理数据并生成输出数据。一旦所有给定节点的输入都包含有效数据,该节点就会执行其逻辑、产生输出数据并将该数据传递至数据流路径中的下一个节点。从别的节点接收数据的节点只在别的节点执行完以后才开始执行。
G编程的优势
直观的图形化编程
与大多数人一样,工程师和科学家可通过查看和处理图像来学习,根本无需有意识的冥想。许多工程师和科学家还会被描述成“视觉型思考者”,这表示他们尤其擅长通过视觉处理组织信息。换句话说,他们最擅长图像化思考。这往往在高校中得到强化,那里的学生被鼓励使用流程框图的形式来构建问题的解决方案。然而,大多数通用编程语言需要您花大量时间学习与该语言相关的特定文本语法,再将语言的结构映射至正被解决的问题。搭配G的图形化编程,提供更直观的体验。
G代码通常更易于工程师和科学家迅速理解,因为它们与显示有很大关联,甚至能以图解形式对程序框图和流程图的过程与任务进行建模(这也遵循了数据流规则)。此外,由于数据流语言须要您将数据流的程序结构作为基础,所以在思考时得关注需要解决的问题。例如,典型的G程序可能首先采集多条通道的温度数据,再将数据传送至分析函数;最后将分析后的数据写入磁盘。总体而言,数据流和涉及该程序的步骤在LabVIEW框图中易于理解。
图2. 数据从采集函数出发,继而通过连线直观地流入分析与存储函数。
交互式调试工具
由于LabVIEW图形化G代码易于理解,常见编程任务(如:调试)也就更直观。例如,LabVIEW独一无二的调试工具,既有助您在数据途经LabVIEW程序的连线交互移动时进行查看,也有助您看清数据值沿连线从一个函数向另一个函数传递时(LabVIEW在高亮显示执行时)的过程。
图3. 高亮显示执行有助直观理解G代码的执行顺序。
LabVIEW还向G提供堪比传统编程工具的调试功能。这些功能,作为面向程序框图的工具栏组件,包括:探针、断点、单步步过(Step Over)/单步进入(Step Into)/单步步出(Step Out)。
图4. 程序框图工具栏可访问标准调试工具(如:步进)。
搭配G调试工具,用户无需复杂编程,就能同时检测程序中很多部分的数据探针,并且能够轻松的暂停或者进入到子程序当中。尽管这在其他编程语言中也是可能的,可视化显示程序的状态和代码并行部分间的关系(鉴于G的图形化特性,这不稀奇)却显得更容易。
图5. LabVIEW中的探针能够有效查看数值沿连线在整个应用中运行的情况,即便在代码的并行部分亦如此。
图6. 在探针监测窗口中查看探针数值;探针监测窗口能够显示整个应用程序(包括子程序)中各类探针对应的探针数值。
LabVIEW中一项最常用的调试功能就是常开型编译器。当您开发程序时,编译器不断检查错误并提供关于应用的语义和语法反馈。如果有误,您就无法运行程序——您只会发现工具栏中“运行”按钮是断开的。
图7. 断开的“运行(Run)”箭头可提供即时反馈,指明G代码中的语法错误。
按动断开的“运行”(Run)按钮,就开启了一列您必须解决的问题。一旦您解决了这些问题,LabVIEW编译器就能将您的程序编译为机器码。一经编译,G程序就能与传统且基于文本的语言(如:C)获得可比拟的性能。
图8. 错误列表详细解释了整体代码层次中的各类语法错误。
自动并行机制与性能
数据流语言(如:LabVIEW),实现了自动平行化。相对于顺序语言(如:C和C++),图形化程序内含代码中哪些部分应当并行执行的信息。例如,常用的G设计模型是生产者/消费者设计模式,其中2个独立的While循环独立运行:第一个循环负责生成数据;第二个循环负责处理数据。尽管并行执行(可能会按不同速度),数据在使用队列的2个循环之间传送;队列是通用编程语言中的标准数据结构。
图9. LabVIEW生产者/消费者设计模式往往被用来提高须并行执行任务的应用程序的性能。
并行机制在计算机程序中意义重大,因为由于进来计算机处理器设计的变化,它能解除纯顺序执行程序的性能限制。40多年来,计算机芯片制造商通过加快处理器的时钟速度来提高芯片性能。如今,为提高性能而加快时钟速度却因能耗与热耗限制,不再可行。最终,芯片供应商转而使用在单芯片上结合多个处理器内核的新型芯片架构。
要利用多核处理器中的性能,您必须能够在应用程序中使用多线程(即,把应用程序分解成可接受独立执行的离散部分)。如果使用传统且基于文本的语言,您必须直接创建并管理线程以实现并行——这项非专业程序员面临的主要挑战。
相反,G代码并行执行的本质令多任务和多线程易于执行。内置编译器在后台连续工作,以识别代码的并行部分。一旦G代码出现一个连线分支或是具有程序框图上节点的并行序列,编译器就试图在LabVIEW自动管理的一组线程中并行运行代码。在计算机科学术语里,这被称作“内隐的并行性”,因为用户无需为了并行运行代码专门编写代码;G语言自行确保并行性。
除了多核系统上的多线程,G还能够将图形化编程扩展至现场可编程门阵列(FPGA),以实现更强大的并行执行。FPGA是大规模并行且可重新编程的硅芯片——各自独立的处理任务被分配至芯片的特定部分——但它们不受当前处理器内核数的限制。因此,加入更多处理时,一部份的应用性能不受负面影响。
之前,惟有接受专门训练且深入理解数字硬件设计语言的专家,才负责FPGA编程。逐渐地,不具备FPGA专长的工程师希望使用基于FPGA的自定义硬件来实现:独特的定时和触发例行程序、超高速控制、数字协议连接、数字信号处理(DSP)、射频与通信以及其他许多对高速硬件可靠性、定制和高度确定性提出要求的应用程序。G尤其适合FPGA编程,因为它不但能明确地表示并行和数据流,而且迅速成为开发人员实现并行处理与确定性执行时的一款流行工具。
图10. 结合并行性的LabVIEW FPGA代码成为FPGA硅芯片上真正独立的通道。
低层任务的抽象
正如FORTRAN所展现的,抽象是更高级编程语言的一项主要优势;它比起较低层级的语言能够更直观地诠释程序。G自行解决了许多您通常在文本编程语言(好比内存使用)中必须应对的挑战。文本语言中,一旦不再需要内存,您便负责在使用和释放内存前予以分配。同时,您还必须记得:所写入数据不得超过已分配的内存容量。因此,对于使用文本编程语言的用户来说,最大问题之一是无法分配内存或分配足够的内存。内存分配不足也是很难调试的问题。
自动内存处理是用G编程的一项主要优势。使用G,您既不用分配变量,也不用为变量交互赋值。相反,像早先解释的那样,您只需创建带有连线的程序框图来表示数据的传输。LabVIEW程序框图上自动生成数据的节点,负责为该数据分配存储。当数据不再被使用,其占用的内存也将被自动释放。如果向数组或字符串添加新数据,LabVIEW将自动分配更多的内存来管理这些新数据。低层次内存管理细节的消除,让您不再关注正在试图解决的问题,而是研究程序执行中与防止运行时错误相关的复杂规则。
与此同时,如果希望对G内存的使用进行低层控制,您能够使用内置的内存管理工具来帮助监测内存;这是一类选择参加的方式,您既能在特定应用里使用,也能单单在应用的一部分里使用。如果您断定内存使用对LabVIEW程序来说是一个问题,可以通过更高级编程技巧来降低使用中的内存量。
图11. 管理LabVIEW中的内存可以选择,但高级用户能够展现内存使用情况以帮助界定哪些部分的应用程序有待优化。
当G代码出现不寻常或不可预期行为导致您无法使用之前提及的调试工具轻松解决问题时,您可采用结合LabVIEW桌面执行跟踪工具包的更高级调试功能。该工具包的设计适合希望通过动态代码分析执行以下任务的更高级用户:
· 检测内存和参考泄漏结合G与其他语言
尽管G代码能够出色地代表并行机制并让开发人员无须理解和管理计算机内存,却未必适合所有任务。特别是,数学公式和方程往往能够更简洁地被文本代表。因此,您可使用LabVIEW,将图形化编程与多种形式的文本编程相结合。搭配LabVIEW时,您能选择文本方式、图形化方式或将两者结合。
例如,LabVIEW包含公式节点的概念;它能评估程序框图上类似于C的文本数学公式和表达式。这些数学公式可并排执行并集成图形化LabVIEW代码。
图12. 公式节点使用类似C的语法,以简洁且基于文本的格式来代表数学表达式。
同样,MathScript节点将面向数学的文本编程加入通常兼容常用类.m文件语法的LabVIEW。
图13. 结合MathScript节点,您能创建或重复使用用于信号处理和数据分析的.m文件脚本。
用户解决问题的更佳方式
LabVIEW及其图形化数据流编程语言,比传统且层级更低的方式更好地解决了问题,耐用性就是证据。用G编程的重要区别在于:您能创建的直观图形化代码和由数据驱动的统管其执行的规则结合后,在编程时可比其他语言更贴切地展现用户的思维过程。尽管G属于层级较高的语言,内置LabVIEW编译器却仍能帮助您取得媲美C等语言的性能。