跳到主要内容

收到了《我和LabVIEW 第二版》的样书

· 阅读需 1 分钟

这本书刚刚印刷好,今天编辑快递了样书给我。第一版发行后,读者反馈中意见最大的就是书籍纸张和印刷的质量不够好。这次的第二版在这方面改进非常大,纸张看起来又白又结实。书籍的版式也变了,第一版比价矮胖,新版改成最常见的16开书籍大小了。

查看或添加留言

《我和LabVIEW》补充内容和注释 第2版

· 阅读需 2 分钟

这是在本书第二版完稿后,我记录的一些使用LabVIEW的经验。这些文章可以作为对书中内容的补充。

<table style="border-collapse:collapse;margin-left:5.4pt;border-style:none;" width="682" border="1" cellspacing="0" cellpadding="0"><tbody><tr style="height:14.2pt;"><td style="width:92.15pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="272"><strong>针对书中章节</strong></td><td style="width:4cm;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="10"><strong>简要说明</strong></td><td style="width:205.55pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="398"><strong>详文链接</strong></td></tr><tr style="height:14.2pt;"><td style="width:92.15pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="272">4.2 可重入VI</td><td style="border-bottom:#4bacc6 1pt solid;width:4cm;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="10">可重入VI的两种分配数据空间方式</td><td style="border-bottom:#4bacc6 1pt solid;width:205.55pt;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="398"><a href="http://ruanqizhen.wordpress.com/2012/07/09/%E5%8F%AF%E9%87%8D%E5%85%A5vi%E7%9A%84%E4%B8%A4%E7%A7%8D%E6%95%B0%E6%8D%AE%E6%8E%A7%E4%BB%B6%E5%88%86%E9%85%8D%E6%96%B9%E5%BC%8F/">可重入VI的两种数据空间分配方式</a></td></tr><tr style="height:14.2pt;"><td style="width:92.15pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="272">11 代码风格与优化</td><td style="border-bottom:#4bacc6 1pt solid;width:4cm;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="10">像其他语言程序那样,把可执行代码与源代码分离开来</td><td style="border-bottom:#4bacc6 1pt solid;width:205.55pt;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="398"><a href="http://ruanqizhen.wordpress.com/2012/03/30/%E5%8F%AF%E6%89%A7%E8%A1%8C%E4%BB%A3%E7%A0%81%E4%B8%8E%E6%BA%90%E4%BB%A3%E7%A0%81%E5%88%86%E7%A6%BB/">可执行代码与源代码分离</a></td></tr><tr style="height:14.2pt;"><td style="width:92.15pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="272">11 代码风格与优化</td><td style="border-bottom:#4bacc6 1pt solid;width:4cm;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="10">内嵌子VI对程序效率的影响</td><td style="border-bottom:#4bacc6 1pt solid;width:205.55pt;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="398"><a href="http://ruanqizhen.wordpress.com/2012/05/15/%E5%86%85%E5%B5%8C%E5%AD%90vi/">内嵌子VI</a></td></tr><tr style="height:14.2pt;"><td style="width:92.15pt;height:14.2pt;padding:0 5.4pt;border:#4bacc6 1pt solid;" valign="top" width="272"></td><td style="border-bottom:#4bacc6 1pt solid;width:4cm;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="10"></td><td style="border-bottom:#4bacc6 1pt solid;width:205.55pt;border-top-style:none;height:14.2pt;border-left-style:none;border-right:#4bacc6 1pt solid;padding:0 5.4pt;" valign="top" width="398"></td></tr></tbody></table>


查看或添加留言

可重入VI的两种数据空间分配方式

· 阅读需 7 分钟

https://labview.qizhen.xyz/

新版本的LabVIEW在设置VI为可重入时,还有两个选项:“为每个实例预分配空间”和“让各个实例间共享空间”:

image

“为每个实例预分配空间”是旧版本LabVIEW(8.6之前)设置可重入VI时的唯一选项。它是指程序在运行前,编译的时候就为每个可重入VI的实例分配好各自的数据空间。比如说这个子VI被主VI在3处不同的地方调用了,那么就分配3份数据副本给它。但是,这种分配数据空间的方式有两个主要的问题。

其一,很多时候程序运行前不能预期会有几处调用到了这一个可重入子VI,比如递归算法就是如此。递归每迭代一次,就需要生成一个新的递归VI的实例。而递归的深度与输入数据有关,在程序运行时才能确定,因此无法预先得知应当分配多少个副本数据空间,也就没法设置为这种模式。

其二,这种设置方式控件效率太低。假设一个可重入VI A,它在主VI中有三处被调用,分别是实例1、2、3。假设程序总共运行3秒,第0秒运行实例1;第1秒运行实例2;第2秒运行实例3。在这个程序整个运行时间内,始终为可重入VI A开辟了三份数据空间,但是每份数据空间都只被使用了很短一段时间,其余时间都没被用到。若是能够重复利用它们,程序可以节约不少内存。

为了解决以上两点问题,LabVIEW又新添了一种为可重入VI 分配数据空间的方式:“让各个实例间共享空间”。个人觉得这个名称起的很不好,它容易让人误解为:只为可重入VI分配一份数据空间,然后它所有的实例都是用着份数据空间。实际情况当然不是这样的,否则就无法保证可重入VI功能的正确性了。

事实上,采用“让各个实例间共享空间”时,每个可重入VI 的实例让然会有它自己独立的数据空间。程序在逻辑功能上与“为每个实例预分配空间”的方式没有任何区别。唯一的不同在于,数据空间并不是程序一起动就分配好了的,而是只有当一个实例VI被运行到的时候,才为它分配数据空间,而这个实例VI运行结束后,它的数据空间就又被回收回去了。两个同时运行的实例VI是绝对不会共享同一个数据空间的;两个不同时运行的实例VI倒是可以分享同一片数据空间,这已是名称中“共享”的由来。

还是以上文的可重入VI A为例,若它被设置为“让各个实例间共享空间”,程序开始时,只需要为可重入VI A准备一份数据空间,供实例1使用;程序第1秒的时候,实例1运行结束,它的数据空间被收回,因此实例2还可以继续使用这份数据空间;第2秒时,轮到实例3继续使用者份数据空间。若我们改变一下应用程序的逻辑,把实例3在第2.5秒的时候就运行起来,由于原有的一份数据空间还在被实例2所使用,它不能再分配给实例3,这时候,LabVIEW就会为可重入VI A再开辟一份数据空间,供实例3使用。

“让各个实例间共享空间”的设置虽然提高的程序的空间效率,但它并非只有有点,因为数据空间的开辟回收都是需要时间的。因此它实际上是以牺牲时间效率为代价来换取空间效率的提高。

对于一个可重入VI,如果它在应用程序中被调用的地方并不是很多,或者它的各个实例常常会同时运行的,那么就应该把它设为“为每个实例预分配空间”;反之,这个可重入VI会被应用程序频繁的调用,而且每个实例运行的时间都很短,它们的运行时间不大可能会有重叠,就应当把它设置为“让各个实例间共享空间”。用于递归调用时,必须使用“让各个实例间共享空间”方式。

查看或添加留言

豆豆19个月

· 阅读需 16 分钟

豆豆这个月过得可开心了,豆豆爸最近比较清闲,带他外出的频率明显增高。

ColorMe

先是豆豆爸公司里组织了一次儿童节活动,在世纪公园旁边的ColorMe,一个专门组织儿童游乐的公司里举办。大约有三十来个小朋友参加了活动,可惜这些游戏活动都比较适合三岁以上的小朋友,豆豆太小了,没法参加任何集体活动。

活动原计划下午1点就开始了,但是豆豆睡醒午觉就快两点了,等我们赶到地方,已经将近三点了。大多数小朋友都已经来了,在活动场所里面的屋子里画画呢。我看见ColorMe一进门就有一处活动区域,都是软塑料积木,我又闻到他们活动场所里面的屋子都有一股装修味道,于是就直接让豆豆去积木区玩了,没有再进去。豆豆对积木毫无兴趣,但是他很快就发现积木区旁边有个小餐台,是给小朋友过家家用的。上面有各种木质的小锅、铲勺、饭碗等厨具,这些倒是挺好玩的,于是上去抓起几样就开始敲敲打打。

过了一会,里面有人喊,小朋友们做集体游戏啦。我就也把豆豆抱进去了,让他见见别的小朋友。在里面一间大屋子里,稍大一些的小朋友们都已经围坐在屋子四周了,中间空出一片活动区域,主持人正站在中央讲话。我把豆豆往地上一放,他就立刻冲到场地中间去手舞足蹈,全然不顾其它小朋友的感受。主持人发现有人抢了他的镜头,直皱眉头。我赶紧跑过去,一把抱起豆豆离开了游戏室。俺们还是单独活动吧。

嘟嘟家

从ColorMe出来,我们直接去了嘟嘟家。嘟嘟比豆豆小了四个月,虽然嘟嘟是个大美女,不过豆豆似乎对嘟嘟的玩具更感兴趣一些。

image

doudou smile

动物园

再过了两天,豆豆爸要去打疫苗,地点就在动物园旁边。于是想干脆把豆豆带去动物园玩吧。就这样,豆豆又去了一趟动物园。去动物园的路上,爷爷奶奶特地买了几个便宜水果打算喂猴子。等进了动物园,已经快到中午了,豆豆饿了,于是我们直奔动物园的餐厅而去。去餐厅的路上,路过金鱼展区。我喂了几块饼干给池塘里的鱼,豆豆也学会了,朝我要了饼干渣扔给小鱼们。小鱼张着大嘴巴在豆豆脚下抢吃的,逗得豆豆咯咯直笑。

动物园里的餐厅很一般,但价格不菲,我们吃了点家常菜也要三百多块钱。但是餐厅的环境可真好,绿荫环抱。餐厅的中庭里还有一座人造瀑布,抱着豆豆去看瀑布的时候,豆豆无比兴奋:伸着脖子,指着瀑布,小腿直踢。

吃完饭,我们就进去看猴子。先去看的是狒狒园,这是个开放式的池子,狒狒们在里面,我们在墙外。矮墙不高,但池子很深,又有水沟阻隔,所以狒狒们逃不出来。没了笼子,游人们可以方便的扔食物进去,爷爷奶奶买的便宜水果就全送给这些狒狒了。从天而降的水果引起了狒狒们一阵骚动,他们嚎叫着开始争抢食物,豆豆看的眼花缭乱。准备离开狒狒园的时候,我抱着豆豆问他:“猴子是怎么叫的?”他于是扯着嗓子“嗷……”地喊了一声。旁边一圈人本来在看狒狒的,现在全都转过头来看豆豆了。

从猴子区出来,我打疫苗的时间就快到了,于是我告别了豆豆去扎针。据说我一走,豆豆就躺在小车里睡着了。等两个小时后,我回来的时候,远远看到豆豆还在睡觉,等走到跟前,豆豆就像知道爸爸来了一样,一下子醒了过来。东张西望了一会,又伸了几个懒腰,然后就屁颠屁颠追鸽子去了。

由于这一天不是周末,人很少;天气也很好,阴天没有太阳,难得的出来玩的好时机,我决定让豆豆多玩一会。于是,我又推着豆豆去看大狮子。上次豆豆来动物园,狮子老虎都在睡觉,大熊猫前面挤满了人,豆豆玩的很不尽兴。这次好了,熊猫馆前一个人也没有,豆豆趴在玻璃窗上看大熊猫吃了一整棵竹子。大狮子也还算给面子,母狮子虽然在睡觉,但公狮子起床了,坐在地上一个人发呆,也许在回想自己在大草原上的风光往事呢吧。老虎就太懒惰了,依然在睡觉。

我们最后参观的是黑熊。黑熊也被关在一个深坑里,看到我们来了,又作揖又鞠躬。奶奶想起来我们还带了肉包子,于是掏出来喂给黑熊,它还挺爱吃的。我赶紧抢过肉包,递给豆豆喂。哪知道豆豆小气的很,每次只揪下来一小块,还要等上好半天才扔给黑熊。

棒棒家

月底,豆豆妈去北京开会,我抱着豆豆也跟去了。趁着豆豆妈开会的时候,我带豆豆去看他北京的小表弟——棒棒。棒棒家住通州,而我们的旅馆在大钟寺,过去一趟,单程两小时左右。以前经常跟同事声讨上海地铁的各种设计缺陷,这次带着豆豆长途体验了一下北京地铁,才发现,原来还有比上海烂的多的地铁系统。

首先,北京地铁是绝对不欢迎轮椅和童车的,因为别说是升降电梯,很多站台连扶梯都没有。新一点的线路虽然有升降梯,也都是摆设,全部都显示着“Out of service.”不同线路之间的换乘也都老长老长,相比之下,上海的一二号线之间换乘都显得好快捷啊。没办法,到了楼梯处,我只好把豆豆连车带人一起抱起来上上下下,幸好最近这一年半常常抱豆豆锻炼了点臂力。

豆豆倒是非常喜欢坐地铁,他逐渐掌握了地铁开关门的规律,等地铁一进站,就开始拍着小手叫:“开,开”。若是恰好对面也开来一辆的话,他还会兴奋的大喊“呜……呜……”。

棒棒的奶奶是豆豆的二姨奶。二姨奶在豆豆三个月大的时候,曾经照顾过豆豆一个月,对豆豆很有感情的。可惜豆豆不记得了,到了棒棒家,一看都是陌生人,有点紧张。稍微安静了一会,他就牵着我的手去各个屋子参观。这时候二姨奶偷摸过来换了我,领着他转。豆豆走着走着一回头,发现领着他的居然不是爸爸,哇一声就大哭起来。我赶紧去抱起他,随后二姨奶又拿出准备好的西瓜递给他,他这才破涕为笑。给了吃的就是熟人了,这回二姨奶也可以对他搂搂抱抱了。

吃饭的时候,二姨奶让豆豆叫奶奶,豆豆不肯。二姨奶夹起一块肉,递到豆豆眼前说:“叫奶奶”。豆豆立刻甜甜的说了一声“奶奶”。势利眼本性暴露无遗啊。

吃过午饭,已经下午两点了。豆豆该睡午觉了,我有一阵子没哄过豆豆睡觉了。没想到豆豆还是很给我面子的,我抱着他讲了几分钟故事,他就睡着了。

等豆豆再醒过来,可就不把自己当外人了。先是抓起拖把来拖地,然后又拿起蒲扇来跟棒棒的爷爷打打闹闹,疯得别提多开心了。

这是豆豆正在投抹布,准备擦地呢:

DSC04159

这是棒棒,刚45天大:

DSC04183

晚上从棒棒家回来,出大钟寺地铁站的时候已经9点了。这时我看看豆豆的尿不湿,已经很大了,我想出了地铁了,也不怕他乱尿了,捂着怪难受的,就解下他的尿不湿扔掉了。我还有点不放心,于是又问了他一下,你要不要嘘嘘啊。豆豆很干脆的说“啊不啊不”,豆豆已经能够清楚的判断自己是否要撒尿了。

回旅馆途中路过一个便利店,我想到我们还需要饮用水,顺路嘛,就进去买了一大桶。结帐的时候,我把豆豆往收银台上一放,付了钱。正准备走的时候,发现坏了,豆豆尿了一大泡在人家桌子上。收银员正在一边规整东西,也没看我们,我于是问他说你们这有没有抹布、纸什么的,我擦一下,这里湿了。他大概也没意识到出了什么事,没好气的说了句“没有”。我想,这可就不怪俺们了,于是夹起豆豆赶快溜。

我当时身后背着个重重的书包,装满了豆豆的换洗用品和食物,右手抱着豆豆,左手拎着水桶,眼看就撑不住了。幸好这时候接到了豆豆妈的电话,说她已经到了附近。又等了一会,豆豆妈终于出现解救了我。

天安门

豆豆妈说,豆豆来北京一趟,去看看天安门是必须的。可惜我们去的不是时候:正午时分,太阳火辣,我们拍了几张照,就草草收兵了。

DSC04228

DSC04234

DSC04249

豆豆是分时段的:晚上9点到早上7点段跟妈妈亲,我抱他一下,他都会哇哇大叫。其它时段是跟爸爸亲,这时候不让妈妈抱呢。

DSC04268

鸟巢和水立方

白天太热,只好晚上行动了。晚上我们领着豆豆去看鸟巢和水立方。

DSC04357

开始跟妈还不错

DSC04345

DSC04365

后来就开始找爸爸了

DSC04448

游乐场

由于白天太热,我们不想带豆豆去外面了。大钟寺广场有几个儿童玩乐的场所,于是我就找了一个,让豆豆进去玩。由于是工作日,里面玩的小朋友不是很多,总共四五个吧,看上去都在两三岁左右。期间,豆豆撞到了一个小男孩,那个小家伙比豆豆矮一块,但是行动非常灵活,豆豆想追他都追不到。我开始以为他比豆豆小,就问了他的爷爷,结果那个小男孩已经两岁零三个月了,比豆豆大了八个月呢,难怪已经运动的这么自如了。

豆豆18个月打完疫苗后去检查了身体,他当时身高是89厘米,体重25.5斤,都超标三个月以上。最夸张的是他的大脑壳,头围已经相当于三岁小宝了。我听到了还有点担心,不知道脑袋太大会不会有问题。

洗澡

豆豆平时就喜欢玩水,这回有了旅馆的免费洗澡水,可是玩乐个痛快。每天都要在洗澡间里带上个把小时,用喷头到处喷。他玩水的时候,我就蹲在地上扶着他,怕他摔倒。他有时回头看看我,然后就突然拿出喷头对着我的脸哗哗淋过来。我用一只手把脸上的水抹干净,然后等着他说“坏豆”,他就得意的哈哈大笑。

旅馆里地方太小,他又惦记着水龙头,有时一不注意,他就溜进去了。有一次,他跑进卫生间后,斜眼一看:“咦,这里有盆水啊”。于是把手伸进马桶里和弄了一通,豆豆妈这个气啊,心想:“我一个洁癖,怎么会生出这么个脏豆呢?”

DSC04308

查看或添加留言

豆豆18个月

· 阅读需 2 分钟

豆豆最近长速减缓了,目前身高大约86厘米,体重大约25斤,与同龄小宝平均水平差别不大。

最近六一儿童节,豆豆妈所在的生化所组织一次小朋友聚会。与会的大多是4~7岁的小宝,他们已经可以表演节目什么的了。可是豆豆啥都不懂,可是他发现舞台上似乎是个好地方,全然不顾别的小朋友正在演出,冲上去就开始捣乱。

DSC04118

DSC04124

DSC04128

DSC04135

DSC04139

豆豆可以熟练的说一些两字词了,比如:“吃奶”,“这个”。豆豆想要爬高的时候还会喊口号,一面使劲一面嘴里念念有词的喊着“一二一二”。豆豆很早就识别大小了,比如我拿两块馒头给他,他必定是挑大的那个。但是他也不算特别贪心啦,通常不会同时把大小两个吃的都拿走。

豆豆记性很好,一个月前我们带他到生化所的大院里玩,他看着一个老爷爷浇花看了半天。一个月后又来到了大院里,他立刻指着上次浇花的地方比比划划地说“哗哗”。

查看或添加留言

豆豆怕飞机

· 阅读需 2 分钟

昨天做了件蠢事,害得豆豆被吓到了,自己也半宿没睡。豆豆平时看见天上的飞机就兴奋的啊啊直叫,我想他这么喜欢飞机,要是去机场看见大飞机一定更高兴。于是昨天就带他到了虹桥机场外围,选了个可以看见跑道的开阔位置让他过过瘾。当巨大的飞机轰鸣着从头顶掠过时,豆豆并没有预想的那么兴奋,后来才意识到他可能有点害怕吧。白天还好,等晚上睡觉,豆豆就开始噩梦不断,快三点的时候更是哇哇大哭起来,要我们把灯打开才敢再睡觉了。

事后,我才回想起自己小时候也对这种轰隆巨响的机器很是害怕的,比如火车,远远看着还好,离近了就不敢了,生怕自己被卷进去。哎,当时怎么就没想起来呢,以后再也不带豆豆去看这种东西了。

查看或添加留言

内嵌子VI

· 阅读需 10 分钟

https://labview.qizhen.xyz/zheng-wen-mu-lu/optimization/optimization_inline_subvi

从提高程序的可读性、可维护性、可重用性的角度来说,在设计LabVIEW程序时,应当经可能多的使用子VI。基本上,每个相对比较独立的功能都应当被做成子VI,而子VI最大也不应到超过30个节点。

但子VI过多,可能会对程序的运行效率带来一定影响。

首先,调用子VI是有一定的开销的,比如调用子VI时需要把参数压栈等,但是这些开销是非常小的,可以忽略不计。

造成嵌入式子VI提高整个程序的性能的主要原因是在于LabVIEW编译器的优化工作。LabVIEW编译器是可以比较智能的做一些优化工作的,在不改变程序逻辑的前提下,提高生成代码的执行效率。比如下面列出了其中几种常见的编译器优化方法:

  • 去除死代码:把永远的不会被执行到的代码删除。
  • 转移循环中的不变量:若循环每次迭代都做某些相同的运算,编译器会把这个运算挪到循环之外,制作一次就可以了。
  • 相同代码合并:编译器自动发现程序中对同一数据进行的重复运算,把重复的运算去掉。
  • 常量合并:编译器会发现程序中对常量进行的运算,在编译时就计算他们的结果,把结果直接保存在程序中,这样就不需要每次程序运行都对其进行计算了。

LabVIEW编译器的优化有一个局限性,就是这些优化措施只能在一个VI上进行,不能应用于全局。当把一个子VI B的代码合并到上层VI A中去,编译器可能就会发合并后的代码有很多可以优化的地方;若VI A和B的代码分别在不同的VI中,编译器分开查看每个VI中的代码,可能就找不出太多可以优化的地方。

LabVIEW中有一个解决方案,可以兼顾可读性与运行效率,就是在编辑程序时,多划分子VI,而编译程序时,又把子VI合并起来当作一个大VI来处理,这就是嵌入式子VI。

在VI属性对话框的“执行”页面上有个选项是“在调用VI中内嵌子VI”,英文叫“Inline SubVI into calling VIs”。若读者学过C语言和它的inline函数,就会非常容易理解LabVIEW中的这个设置。

image

当这个选项被选中,这个VI就变成了嵌入式子VI。当嵌入式子VI被拖拽到其它VI上,从编辑代码的角度上看,它与其它VI没有什么区别;但是在程序编译的角度来看,它与普通VI是不同的,那就是嵌入式子VI在编译时,并不是独立存在的,它的代码被全部复制到了调用它的VI中。用一个实际的例子来讲,假如一个程序中有两个VI,A和B,A调用了B。假如B是一个普通的VI,这个程序便编辑成可执行代码后,代码中还是有两个VI,A和B;若B是嵌入式子VI,编译好的程序就只剩下一个VI了,被扩充了的A,被扩充的A中包含原A和B两个VI的代码。

需要注意的是:嵌入子VI这个选项并不是用的越多程序效率就越高。使用嵌入式子VI也会给效率带来负面影响,比如它在每处调用子VI的地方都会生成一份拷贝,使得程序体积膨胀,占用过多的内存等。因此,建议把调用不频繁,输入参数常常为常量的VI设为嵌入式子VI,而一般的子VI不需设置。

下面用一个具体的示例来看一下LabVIEW编译器是如何优化程序的:

首先,我编写了一个子VI,这个VI有三个输入;其中两个输入是数据,另一个输入表示对两个输入数据进行何种运算,是相加还是相减等;让后把运算结果输出。

image

image

这个“Inline sub VI.vi”被设置为嵌入式子VI。对于嵌入式子VI,它必须是可重入的(嵌入式子VI的代码在每个子VI被调用的地方都会有一个副本,就更不要说是数据空间了)。LabVIEW暂时不支持嵌入式子VI的调试和自动错误处理。所以,在VI属性对话框中设置嵌入式子VI时,要把其它的设置做相应改动,否则LabVIEW会在其它设置项上打个叹号,提示这里的设置有问题。

image

接下来我在下面的程序中调用的这个子VI:

image

下面咱们要看一下,LabVIEW的编译器是如何对这个程序进行优化的。为了更直观的展示这些优化,我会画一些示意程序框图。这些用于示意的程序框图并不是LabVIEW优化出来的,而是我手工制作的,LabVIEW的优化只针对编译好的可执行代码,它并不会修改VI的源代码(程序框图)。但是经过LabVIEW的优化,main.vi生成的可执行代码,与我制作的示意程序框图编译成的可执行代码是完全相同的。

因为“Inline sub VI.vi”是嵌入式子VI,对于编译器来说,它的代码是被拷贝到main.vi上来的,所以对于编译器来说,它看到的代码是这样的:

image

在这段代码中,条件结构分支选择器的输入是一个常量“Add”,这就意味着程序每次都只会进入“Add”这一分支,而其它分支永远不会被执行到。编译器会把那些执行不到的分支移除,因此,优化后的程序代码等效如下:

image

程序中循环内所作的运算,在每次迭代中都是相同的,因此它可以被挪到循环之外,只运行一次。优化后代码等效如下:

image

程序中的平方运算的输入值是一个常量,因此这一运算会在编译时就完成这一计算,等效优化后代码如下:

image

程序中,对data这个输入数据进行两次完全相同的运算,这是没有必要的,编译器也会将其合并,于是优化后的代码最终等效与如下的代码:

image

可见,一个看似复杂的程序,经过LabVIEW编译器的优化,它的运行效率可以媲美一段极其简单的程序。但是这并不是说程序员可以不关心代码的效率了。编译器毕竟还是能力有限,它只能做简单的优化,程序效率的决定因素还是在于程序员本身的。

查看或添加留言

豆豆17个月

· 阅读需 2 分钟

上个月新搬了一个地方住,新地方干净一些,可以让豆豆下地自由活动了。为了给豆豆创造更清洁的环境,我还特意弄了一个吸尘器,用于打扫卫生。豆豆平时若是看到地上有脏东西,就会指着它说“嗯,嗯”,然后大声叫“爷爷”,让爷爷把它收走。吸尘器以来,豆豆就被这个神奇的东西吸引住了,所有的脏东西,呼一下就被吸进了它的管子,都不需要爷爷来捡了。每次我干活,他都要在一旁指挥,告诉我脏东西在哪。不过豆豆还是有一点害怕这个嗡嗡作响的家伙的,每次我一说:“爸爸开始吸了”,他就急忙往后退,最好躲到妈妈身后再来观察我工作。也许是因为吸尘器噪音太大,也或者豆豆怕自己也被它吸进去吧。一旦我停下开关,豆豆就又立刻冲上来,拿起吸尘器的进气管,一边在地上比划着,一边嘴里还要发出“呜呜”的声音,干的有模有样。

DSC04046

DSC04095

查看或添加留言

豆豆16个月

· 阅读需 3 分钟

昨晚豆豆妈加班,很晚才回来。豆豆9点就困了,看不见妈妈,豆豆就找爸爸。我想让他躺床上给他讲故事,但是他不干,一定要让我抱。于是我抱起他,对他说:趴到爸爸肩膀上。豆豆就往我肩上一趴,我抱着他在屋子里边走边讲故事,走了两圈豆豆就睡着了。这是近来豆豆头一次晚上不吃奶睡觉。豆豆现在跟妈妈可粘糊了,看他每晚在妈妈怀里的赖叽样,让人觉得他离开奶就过不了了呢。以至于我常常担心他将来断奶的时候会不会太过难过。现在看来,豆豆是相当现实的一个小宝:有奶吃就吃,没有奶也不影响睡觉。这让我放心了很多。

最近上海天气转暖,于是我们又把豆豆头发剃光了。

DSC03917

豆豆每天要在外面草地上待三四个小时,走路的水平大有长进,摔跤次数越来越少了。这天,豆豆在草地上遇到了三只小兔。

20120403499

豆豆对陌生动物倒是一点也不害怕,上去一把就抓起了兔子耳朵。

20120403501

月初的时候,豆豆的姥姥姥爷来看他,而爷爷奶奶则回无锡去了。豆豆是个势利眼,只要有给他做饭、陪玩就行,根本不管是谁。姥姥姥爷一来,他就适应了,丝毫看不出有想念爷爷奶奶的意思。这几天我们一直在训练豆豆喊“姥姥”,豆豆三天就学会了,不过发音还不太准,现在见了姥姥就喊“欧欧”。

有一天白天,豆豆妈不在家,姥姥姥爷喂豆豆吃饭。豆豆贪玩,把饭往外掘。姥爷板着脸,对他一瞪眼,他立刻识趣得乖乖吃饭了。晚上又到了吃饭时间,还是姥姥姥爷在外屋喂豆豆吃饭。豆豆顽皮劲又来了,姥爷故技重施,又一瞪眼。这次豆豆知道妈妈在家,可就没那么乖乖就犯了,他立刻跑到妈妈面前满含热泪的哼唧,一副受了委屈的面孔。豆豆还挺有做演员的天赋呢。

查看或添加留言

可执行代码与源代码分离

· 阅读需 4 分钟

https://labview.qizhen.xyz/

我在书中和之前的文章中介绍到了LabVIEW的一个与其它语言不同之处:它把程序源代码和编译好的可执行代码存储在了同一个文件中。我一直觉得这并不是一个好的方法。对于普通LabVIEW用户,这也许不是一个严重问题,甚至很多人都不需要关心LabVIEW是怎么保存文件的,只要他的程序能正确运行就万事大吉。

但是,源代码与可执行代码混合存储的弊病还是给我的开发带来了一定影响。我开发的项目较大,有多个人同时参与开发,这样一来,同一个VI文件就会在不同的开发者之间传来传去。每个开发者有自己的喜好,有人有64-bit的LabVIEW进行开发,有人用32-bit的LabVIEW,有人用Windows,有人用Linux。这本来不应该是一个问题,LabVIEW支持跨平台,相同的源代码不加修改就可以在任何平台下运行。

问题在于不同平台下编译出来的可执行代码是不同的,我的程序复制到同事的电脑上,即便代码不做任何修改,VI也会被修改,因为VI中包含的可执行代码变了。这样,我就没法简单的判断一个VI是否被同事做了修改,还是仅仅编译后的代码变了,非常不利于程序源代码管理。

这个问题可以通过分离VI的源代码与可执行代码来解决,这是LabVIEW2010开始出现的功能。在VI的属性对话框中,有一个选项是“分离编译后代码与源代码”。若这一选项被选中,则VI中只保留程序的源代码,而编译生成的代码则被移出VI之外。

image

被分离出来的编译好的可执行代码又LabVIEW统一管理,在我的Windows 7 系统中,文件夹C:\Users\[user name]\Documents\LabVIEW Data\VIObjCache\[LabVIEW version number]\ 下有一个objFileDB.vidb 文件,这就是用来存储LabVIEW 程序所有可执行代码的数据库。

若程序会在不同平台下协同开发,或者程序会被发布到不同平台下去,都可以考虑采用可执行代码与源代码分离的策略,避免不必要的VI变动。

理论上,可执行代码与源代码分离开来,可以提高程序的加载速度:程序可以各取所需,只加载源代码或只加载可执行代码。不过我并没有太明显的感觉到速度的变化。

查看或添加留言