LabVIEW 中的泛型容器

    Google 网站里有个 Google 实验室,有不少 Google 的产品最初就是放在这个实验室里的。现在 NI 也有 NI 实验室了。NI 实验室公布出来的项目一般是 NI 工程师利用额外时间做的一些调查研究。这些项目不是公司的正式产品,但是它们的设计很有创新或者是比较有应用潜力。与其让这些项目被埋没了,不如先看看用户对这些项目的反应,如果相当一部分用户觉得某个项目非常有帮助,或许它就值得我们为其增加投资,把它作成正式产品了。
    我这里给大家介绍其中的一个项目:“LabVIEW Generic Container Map”。因为这个项目是我设计的,所以对它了解比较多一些。当时,我们打算提出这个项目的时候,主要有两个目的:第一是帮助用户编写有复杂数据结构的应用程序;第二是推进 LabVIEW 向通用编程语言方向做改进。

    C++ 的程序员基本都很喜欢 STL 这个模板库。程序中常会使用数组、队列、字符串等等数据类型和结构,如果自己设计实现这些数据结构和相关的操作,是相当耗费精力的。好在 STL 实现了这些数据结构,和它们常用的操作方法。借用 STL 提供的功能,编程时很多细节方面不需要再去考虑了,这就让工作简化了许多。尝到 STL 甜头的程序员,在编写程序的时候,已经很难离开 STL 了。
    STL 中非常重要的一个部分就是容器。容器用于存放数据,程序通过调用容器的结构函数保存数据到容器或者访问容器中的数据。容器也分为不同的类型,如链表、队列等。它们在数据的组织方式上,或存取方式上有所分别,以适用不同的需求。STL 中的容器和方法都是泛型的或者说是数据类型无关的,就是说这些容器可以保存和操作任何类型的数据。
    其它一些常用的编程语言,如 Java、C# 也都有类似的泛型容器以方便程序员使用。

    LabVIEW 的主要方针是简化工程师们编写程序的难度,以前用 LabVIEW 编写的程序大多是工业领域流程控制类型的。这种类型的程序用不到太复杂的数据结构和算法,因此,LabVIEW 中对我们在计算机课程中学到的那些经典数据结构以及算法的支持并不多。
    但是在我自己用 LabVIEW 多了之后,用它比用 C++ 要顺手,任何类型的程序都喜欢使用 LabVIEW 来编写,包括一些通常用途的程序。这时候,LabVIEW 缺乏对基本数据类型支持的缺点就格外突出了。于是我和周围几个同事就想到应该在这些方面对 LabVIEW 做一些补充,做一些比较规范的泛型容器和算法,一方面方便自己,也许还可以提供给别的用户。

    由于这不是正式项目,我们能投入的资源很有限,不可能一开始就做得很全面。作为开始,我们选择了 Map 容器和它最常用的几个方法。首先选择 Map 一是因为它比较常用,二是其它容器中,有些在概念上和 LabVIEW 中已有的一些函数比较接近,如果选则他们,可能会引起用户的误解。
    LabVIEW 中的 Array 操作与 STL 中的 vector 是非常相似的,功能齐全,不需要考虑底层操作如内存管理等。STL 中的 deque, queue, stack 等,与 LabVIEW 中的“队列”(Queue)操作比较类似。但是 LabVIEW 中的队列存在的目的不是为了作容器,而是用于在多线程程序中通讯。在“生产者/消费者”程序模式中,经常使用队列在不同的线程中传递数据或消息。因为 LabVIEW 中队列操作主要用于不同线程间的通讯,因此它的函数并没有采用 LabVIEW 的主要传参方式-传数据,而是采用了传引用的方式。

    我们实现的这个 Map(这个按字面翻译比较别扭,中文可能翻译成“字典”还比较合理)泛型容器功能与 C++ STL 中的 Map 是类似的,它主要用于程序经常需要按某一关键字查询数据的情况。
    Map 已经包括了编写查询程序时常用的操作,比如把数据放到容器中、查找一个数据、删除、清空容器等。
    我们的 LabVIEW Generic Container Map 内部的数据是按照平衡二叉树的方式组织存储的,它的查询复杂度比一般线性数据结构的要低。这样,在数据量很大的情况下,使用 Map 的程序效率明显高于使用数组的程序。
    Map 采用的是符合 LabVIEW 风格的传数据方式,把整个 Map 中的数据在不同函数间传递。

    C++ 是支持泛型编程的。简单地说,泛型编程可以这样理解,就是程序员可以实现一个方法,这个方法能够应用在任何合法的数据类型上。比如,前面提到的 STL,它有个“比较”方法,你可以用它来比较整数,也可以比较字符串,或者使用户定义的类的实例等等。
    支持泛型编程,程序员就可一抽象出与数据类型无关的算法,从而使代码具有更好的可重用性。
    目前,用户还不能在 LabVIEW 上实现泛型编程。使用 Polymorphic VI 可以使一个方法支持某几种特定的数据类型,但不是任何数据类型。真正能做到数据无关的函数,比如说“equal”函数,都是 LabVIEW 自带的,用户无法写出这样一个函数或 VI。
    我是非常想推动 LabVIEW 有朝一日也实现泛型编程的。这个 Map 容器也是在 LabVIEW 泛型编程方面做的一次探索。这个 Map 容器不是 LabVIEW 自带的东西,它是完全使用 G 代码实现的。但是它同时也是一个泛型容器,支持对任何数据类型的操作。

下图是使用 Map 编程的一个例子:

《我和 LabVIEW》

Advertisements

20 thoughts on “LabVIEW 中的泛型容器

  1. Pingback引用通告: 博客版《我和LabVIEW》目录 « 凡人琐忆

  2. 刚好想在labview中使用map,但是在空间中未能找到项目源码的下载链接。。现想实现从数据库中读出内容存入map中,这样就不用每次都去读数据库,减少时间开销。对该项目很感兴趣,能否传一份源码来参考下,谢谢~

  3. 在你开发的Map中使用到LabVIEW 8.0后才出现的*.xnode,请问我们要怎么去编辑属于自己的*.xnode?

  4. 后来更新过,主要是修改了一些bug。已经可以生成EXE了。新的版本只能在8.5下使用。哈希表,我们考虑过,但是没有尝试实现,感觉上它比二叉树要难,主要没有一个各种情况都适用的哈希算法。对于某一个特定问题,倒是可以考虑做个哈希表的。

  5. 我目前使用LabVIEW 8.5版本在測試發現問題和在之前LabVIEW 8.2版本一樣,就是當我在value type複製一個constant時將它更新名稱,以此例是複製"職工編號"將它重新名命為"Index",並且將它的order改為0,然而,在建立map out時卻出現下圖左的indicator和下圖右的cluster的constant不同,導致必須手動更改indicator的名稱,很不方便

  6.  完全不懂,这是什么?
    老大,你在过强悍了
    弄的我只有惊叹的份
    因为不懂
    不过还是谢谢你的留言喽
    呵呵
    每一篇下面该有篇日志会好一点,估计会来的人多一点
    人多有什么好处不用说你也明白的
    宣传啊,同行就夹在其间,呵呵

  7. 好久没来了。一来就看见经典,呵呵,顶一个。虽然现在不用LV,未必以后也不用,还是把你的BLOG加到我的GOOGLE RSS Reader里吧。多发文呀~~没事也上俺“家”瞅瞅

  8. 谢谢回复。
    不能编译成exe就很麻烦了。我只能自己使用,而无法发布我的产品。因为目标机器上不可能安装LV8.2。LV一个lisence还是挺贵的。不过能自己用用也挺满足了,毕竟现在还是free的。呵呵。用map还是能省不少事的,尤其是可以嵌套,这玩意好使。
    我自己在用LV写和map的功能差不多的子vi,只是可能数据类型支持的不够多,算法不够好而已。其实map里面的很多功能我都写了,只是在看了你编写的map这样一个概念之后,知道了这样的原型,加深了对程序结构、数据处理流程的理解了。很有收获。我可以在自己的机器上编程的时候,就用map,发布exe的时候,就把map相应的东西换成我自己的vi。
    曲线救国啊,呵呵。

  9. 现在这个 Map 在内存占用上并不能比以前减少,它只是利用的平衡二叉树,把搜索的时间复杂度从 O(n)降低到了 O(log n)。它是提高程序运行速度,但不能减少程序的内存消耗。如果数据量特别特别大,可能运行起来还是有问题。这不是 Map 的问题,而是LabVIEW 在这方面存在固有缺陷引起的。这个我现在也没有想到很好的解决方法。

  10. 容器里可以放数据,也可以放其它容器。所以 Map 是可以嵌套的。吧一个 Map 作为数据放到另一个 Map 中去。(今天上午我跟你讨论过这个问题,不过当时我好像说错了)

  11. secondary key 这样的参数以后是不会提供的,因为有些应用可能还需要第三、第四关键字等等,我们不能吧函数的参数越添越多。解决的方法有两个,一个是短期解决方案,你可以把你的第一关键字、第二关键字,组成一个 cluster。把新构成的 cluster 作为关键字,就可以了。长期,我有个计划,就是支持用户定义“比较”行为,你也提到这点了。对于两个同类型的数据,用户可以指定它们比较的方式,而不是像现在这样直接调用LabVIEW的大于号来比较。比如,可以定义先比较数据中的一个元素,相等,就再比较另一个元素,知道区分出大小。这样以来,用户就可以自己对数据排序了。

  12. 这个软件应该可以在任何操作系统下的 LabVIEW 8.2 中使用,这是我只对 Windows XP 进行过测试。但是如果没有 LabVIEW 8.2 就不行了。我今天试了一下把它升成可执行文件,结果出了错。以前没试过做exe,所以没意识到这个错误。这个无法升成可执行文件的问题,会争取在下个版本解决。

  13. 回答 GaoJie 的问题首先感谢你来用,像这样一个还在试验阶段的项目,能够由用户来用,就是对他的最大肯定了。

  14. 前面点了两下,发重复了。呵呵,删了一个吧。
    刚刚用了一下你的这个东东,还是挺好使的。
    能否提供一个secondary key?也就是说,你的sort key下,能不能定义下一层的key?这样应该会更容易用到复杂应用中。呵呵。其实也就是说,map是一个容器,他可以包含任何类型的数据,那么,能够包含另外一个map吗? 
    还有,你的这个实验品,基本上就是查询的功能,排序的好像没看见,是固定排序的吧?我其实非常需要compare 的功能。如果有整体key之间的比较和key包含的基本value的比较,那么会很好用。呵呵。
    从使用方法上来看,使用map,我首先需要的是把数据都放到map里面去,然后才能查询。但其实如果我已经都获得了数据,我直接比较查询就能够得出结果了。编程也不复杂,使用map能明显提高效率,还是减小内存的消耗?个人觉得,如果数据都放在map里面,数据量少没有问题,如果多了,即使map只提供的是内存的指针(我不知道你是不是这样开发的),也会比较耗内存,我现在处理的方式是查一块之后,丢掉一块,否则根本不跑不动。
    顺便说下,我download下来的manual里面好像有点小错误,你检查下,一个是erase的定义,写成了find,估计是从上面copy下来的没改,嘿嘿,俺也经常干这样的事情。还有一个,valid好像没定义。其实象这样的要是能直接加到LV的帮助里面就好了。现在好像content里面只有简单的提示,没有detail的帮助,是吧?
    最后还要问下,OS如果是2000的,是不是没法用这个啊?单位里面都是2000的系统,只有家里才是xp。要不在xp底下打包成exe或者installer到单位用?

  15. 非常好,我刚刚用LV完成一个海量测试数据查询处理的程序。包含了大量的数组操作、簇操作等等。
    去下下来看看有没有刚好可以用到的地方。
    呵呵。

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s