跳到主要内容

普陀山游记

· 阅读需 3 分钟

周末公司组织去普陀山旅游。周五晚上从吴淞码头出发,第二天一早驶达普陀山。我们很不幸,因为周六正赶上台风袭击,整天都在下雨,而我们只能穿着雨衣打着伞游玩了。

DSC01759

不过台风也带来了意外的好处:由于短途的渡船都已停航,来参观的游客比较稀少,不会因为太过拥挤而影响旅游的心情。

DSC01784

普陀山这里自然风光很有限,所谓旅游就是看庙。我对烧香拜佛不感兴趣,所以我很少进入室内,每到一处就在庙外面练练摄影。

DSC01816

有些庙宇藏在深山里,安闲宁静。

DSC01814

有些寺庙临海而建,惊涛拍岸,颇有气势。

DSC01832

岛上最显眼的还是这尊铜制观音像,还没去参观她的时候,远远的就看到了。

DSC01843

台风只持续了一天就过去了,天气突然就从狂风暴雨转为风和日丽。

第二天的行程还是以看庙为主,首先去的是岛上规格最高的那座寺庙(庙太多,名字都没记住)。果然富丽堂皇,远远看去,和宫殿也可媲美。

image

除去寺庙,我们玩的唯一一处景点是千步沙,景色不错,唯一缺憾是海不够蓝。

DSC01906

我借用大家看庙的时间,脱离队伍去周围走了走,岛上颇有点幽静的田园气息,要是能生活在这里就爽了。

image

行程的最后一站是岛上最高的那座寺庙。寺庙都是大同小异的,然而登山途中的风光还是值得一看的。

DSC01943

DSC01950

查看或添加留言

关于相对论没搞明白的问题

· 阅读需 5 分钟

最近我在准备公司每周的技术讲座,主题是相对论。狭义相对论相对直观,大学物理课上就学得差不多了。但一提到广义相对论,我就有些犯难,毕竟我不是物理专业出身,面对那些弯曲的高维时空,总感觉像是在雾里看花。

广义相对论告诉我们,所谓的万有引力其实并不存在,它只是时空弯曲的一种表象。质量使时空弯曲,而物体在这种弯曲的高维时空中沿着“直线”运动 - 只不过,这种“直线”在四维时空中看起来是弯曲的,于是我们误以为有某种力在作用。乍一听,这是一个很有趣的解释,但越琢磨,越觉得其中的细节让人困惑。

广义相对论的核心是,物体在弯曲的时空中沿“最短路径”运动。然而,这并没有很好地解释原本“相对静止”的两个物体如何会开始运动起来。比如,树上的苹果和地球在我们看来是相对静止的,那么苹果为何会掉落到地面上呢?

我能想到两种可能的解释:

其一是,还有一种隐形的“力”依然存在。即便万有引力本身被否定,但质量可能引发了某种类似于力的效果,导致物体间的相对加速度。尽管广义相对论否认了这类“力”的存在。

另一种可能是高维空间中的绝对运动。假设苹果和地球在更高维的空间中本身就处于运动状态,而它们在四维时空中的投影呈现出相互趋近的结果。这意味着四维时空里的“静止”只是一种表象,而在更高维度中,运动是绝对的。按照这种解释,四维时空中的相对运动与高维空间中的绝对静止存在某种对偶关系。这种解释违背了我们的直觉,因为它强行引入了一个难以验证的高维世界。

广义相对论强调质量会扭曲周围的时空,但没有进一步解释为何会扭曲。这似乎跳过了一个重要问题:既然质量能够弯曲时空,为何不能将这种现象看作某种力的作用?换句话说,是否可以重新定义“力”,将其视为质量对时空的某种直接影响?

根据广义相对论,运动中的质量会导致时空弯曲的变化,这种变化以光速传播,称为引力波。引力波携带能量,因此物质在运动过程中,即使未受外力,也会因辐射引力波而损失能量。这种现象让我想到一个有趣的推论:

如果物质的能量可以通过引力波传递给时空,那么时空本身是否也具有能量,甚至“质量”?如果时空具备能量,那么它是否依然只是一个“背景”?或者说,时空本身就是物质的一种表现形式,物质与时空的界限是否从根本上就不存在?

如果时空是无限的,所有运动的物体都会因引力波辐射逐渐损耗能量,动能趋于零,最终达到一种“绝对静止”的状态。这样的结局听起来颇具宿命感:运动本身终究会熄灭,万物归于静寂。如果宇宙是有限的,引力波在某种意义上可能达到一种平衡,类似于黑体辐射的状态。

查看或添加留言

Silverlight程序中显示帧数的方法

· 阅读需 3 分钟

接到一个需求:要在Silverlight程序的界面上放置一些控制选项,可以开关Silverlight的EnableFrameRateCounter,EnableRedrawRegions等和显示效率相关的一些设置项。我开始在网上查了一下,这几个与显示性能相关的设置主要被用在装载Silverlight控件的HTML文本中。在Silverlight程序启动之后,这几个属性仍然可以被修改,除EnableGPUAcceleration之外。问题在于,如果EnableGPUAcceleration没有在HTML文件中被设置为True的话,EnableCacheVisualization和EnableFrameRateCounter也无法工作。看来微软给出这几个属性就是为了帮助开发显卡加速的动画的。

EnableFrameRateCounter被设置为真时,Silverlight界面左上角会显示出几个和GPU相关的数据,其中包括动画刷新帧数。但是我搜索了一下,Silverlight似乎没有提供函数,可以在程序中把这个帧数读出来。MSDN中提供了一个间接方法来计算帧数,利用CompositionTarget.Rendering这个事件。Silverlight没刷新一帧,都会抛出一个CompositionTarget.Rendering事件,对这个事件计数,就可以算出每秒帧数了。不过,用这个方法计算出来的帧数,与EnableFrameRateCounter设置显示的帧数居然是不同的。

CompositionTarget.Rendering事件的发生次数与用户设置的MaxFrameRate和系统繁忙程度相关。而EnableFrameRateCounter显示出来的那个帧数还与Silverlight动画是否需要刷新相关。比如对于一个界面不怎么活跃的Silverlight程序,当Silverlight觉得不需要刷新界面时,它就不刷新,显示出来的帧数很可能是个位数,甚至为0。

查看或添加留言

Scrum

· 阅读需 5 分钟

我居然没能在网上找到这个词的中文翻译(也许可以称为迭代开发?),就直接用英文吧。Scrum是敏捷开发的一种方法,简单来说,就是把传统软件开发流程的周期时间缩短,周期数量增加。就拿LabVIEW做例子吧,目前LabVIEW每年发布一个新版本,如果换用Scrum流程,就应当每个月发布一个版本,一年12个版本,但每个版本的更新只有原来一个版本的1/12。

Scrum现在非常时髦啊,也许是Google的成功起到了示范效应,原来越多的软件企业开始采纳这套开发流程。Google的开发模式被称为永远的Beta版:一个产品刚有几个基本功能就发布给用户去用了,然后再根据用户的反馈,每隔一小段时间就更新一下。

我最初在网上了解到Google这套开发理念的时候,就被它的优势吸引住了:软件的很多新功能都是程序员或者经理拍脑袋想出来的,它们或许并不符合用户的需求。越早拿给用户看,也就可以越早改进,少走弯路。真的遇到一个垃圾想法,也好早死早超生。我当时就预感,这套开发方式必定会被广泛采纳的。

Scrum流程肯定不适用于所有领域。比如说盖楼,原本盖一栋楼要一年:1月挖坑、2月打地基……11月封顶、12月装修外墙。用Scrum就不能按这个顺序了,因为最终用户不关心挖坑、地基和内部结构。所以施工队必须一个月内就挖个小坑、埋几根地基,竖起一面墙,粉刷好,然后给用户看。用户说墙太薄,窗户不够大等,于是施工队下个月按照用户的意见再建下一堵墙。我很怀疑按这种方法,施工效率会有多高。

实际上,使用了Scrum流程的公司也并非都取得了成功,比如说引入Scrum流程之后的诺基亚…… Google的成功与诺基亚的失败也许可以说明开发流程不是影响企业的成败主要原因;或者也可能是因为Scrum不是狗皮膏药,它只在某些领域才能发挥出功效。

还是说我熟悉的LabVIEW吧,LabVIEW的主要应用领域依然是是工业测控。这个领域的用户与互联网用户的一个明显差别就是,工业领域的客户要谨慎的多。受大多数用户喜欢的技术的特点是稳定而非先进。LabVIEW每年升级一次,居然很多用户抱怨说升级太快了。与之对比,某个拼音输入法的用户们天天在论坛上叫:“都几个星期了,怎么还不更新?”让LabVIEW的用户每个月更新一次,他们还不疯了才怪。我估计LabVIEW在这一点上是学不了Google的。

对于不能频繁更新的软件来说,一定要走Scrum的流程,又不能每个月从外部客户那里收集反馈,那就只好去经理那里要反馈了。每个月做一个版本,然后给经理看看,再去做下一个版本。我个人看法:敏捷开发的精髓在于:最终用户的快速反馈使得软件可以紧跟用户需求的变化。内部人员无论是谁,他们的需求都必然与用户不同,都代替不了最终客户。至于Scrum流程上的东西,如每日例会、用户故事、燃尽图之类的都只是形式而已,没了最终用户的参与,新开发流程只能算换汤不换药吧。

查看或添加留言

豆豆的爬行姿势

· 阅读需 1 分钟

周末突然发现豆豆可以肚皮离地,仅靠手和膝盖把身体支撑起来。不过豆豆的爷爷奶奶说,他两星期前就可以支起来了,只不过我白天都不在家,没有看到而已。

尽管豆豆力气是够了,但神经系统还没发育好呢,所以还不能进行真正的爬行。他现在每次先把手放在胸前,撑起身体来,接下来向后使劲,把屁股撅得老高,然后再伸直腿,身体就嗞溜一下滑到后面去了。

DSC01575

查看或添加留言

Modkit 一种图形化编程语言

· 阅读需 5 分钟

目前,像LabVIEW这样功能强大,比较通用的图形化编程语言可能绝无仅有的。但市面上,比较小型的,针对特定应用的图形化编程语言却五花八门,随处可见。今天同事又给我介绍了一款,叫做Modkit,官方网站:http://www.modk.it (河蟹们访问需翻墙)。

这款编程语言是基于Web的,也就是打开了网页就可以直接开始编程,不需安装额外软件。这一点与NI去年发布的 LabVIEW Web UI Builder 相类似。区别在于LabVIEW Web UI Builder 是基于Silverlight的,而 Modkit 据我观察,没有使用任何插件,很可能基于HTML5标准编写的。

如果可以选择,我个人会倾向于使用HTML标准开发程序,而不是使用Silverlight。目前来说,开发Silverlight程序的确比开发HTML5程序要容易。但是,Silverlight只是微软一个无足轻重的产品,随时可以被抛弃;而HTML标准却是w3c组织最核心的产品,又有一干顶尖厂商的支持。从长远来看,HTML可能更会被广泛采用。

回头再说 Modkit 这个产品,同为图形化编程语言,它的风格与LabVIEW迥然不同。我觉得它的设计最有两点的地方就是把编程序搞得像玩拼图游戏一样:

它的每个程序模块是一个拼图(或者叫积木)模块,搭在一起形成一个完整程序。它的模块之间不需连接数据线,贴在一起就行。

图形化编程语言可能都免不了模仿一些已有的概念。比如Modkit模仿拼贴画、LabVIEW模仿电路图、VEE模仿流程图。想不起来,对于一个任何背景知识的人来说,拼贴画最易入门。

Modkit 使用颜色来区分不同种类的模块,比如:蓝色表示对硬件进行配置;紫色表示数据输入输出通道;绿色表示运算模块;橘黄色用于流程控制。

用拼图的形状来保证数据类型安全。有的拼图块是方的(数值数据),有的拼图块带个卡口(执行模块),有的拼图块两侧带尖的(表示逻辑数据)。插槽也是有形状的,这样,只有形状匹配的积木才能放进相应的插槽。这和拼图的理念完全一致。

看,这就是我编的一小段简单程序: image

Modkit是专用来对Arduino这款硬件进行编程的。这种针对特定硬件设计的编程语言,最大优势就是效率高。我在和LabVIEW用户聊天时,听到的一类比较多的抱怨就是LabVIEW太大了,包含了各种他们不需要的功能,拖累的他们的程序爬都爬不动。

单从用户的角度来考虑,把LabVIEW的功能分离开来,搞出一系列针对特定硬件的精简版本来,会更利于使用。我得理想情况是:为每个硬件设备都安装一个基于Web的LabVIEW编程服务,这样用户只要使用浏览器打开一个硬件设备,就可以直接为它编写程序了。不过从商业利益考虑,这件事只能是硬件厂商自己去做了。

查看或添加留言

最清闲的爸爸

· 阅读需 2 分钟

刚有了孩子的同事们,看上去一个比一个憔悴,甚至还有人直接就跟我抱怨当爹的艰辛。相比之下,我这个爸爸当得还真是轻松啊。

豆豆出生的头两个半月,呆在山东外婆家里,期间我只去陪过他三个星期左右吧,最辛苦的阶段被我逃了。等豆豆回上海的时候,已经变成小乖乖了,十分好带。豆豆爱笑不爱哭,如果不高兴,不是就是饿了,就是困了。只要掌握好他的吃喝拉撒、睡觉、玩耍的时间规律,豆豆就几乎从不哭闹。现在,豆豆晚上跟爷爷奶奶一起睡,半夜里吃那一次奶也不需要我管了。我常常可以一觉睡到天亮,真是天底下最幸福的老爸啊。

不过豆豆现在大了,脾气见长,也许以后要烦心的事会变多吧。昨晚,豆豆喝水的时候,我故意把他奶瓶抢走,他居然恶狠狠得朝我大吼大叫,这脾气像他妈。

中午我还在上班,老婆就迫不及待的打来一个电话,说她摸到豆豆的小牙了。晚上我回家一摸,豆豆下牙床上果然有个硬邦邦的小尖。由于豆豆极不配合,露出来的牙齿又极小,我们一家人费了好半天,才看清楚它的位置,是左下方的门牙。

查看或添加留言

五个半月大的豆豆

· 阅读需 5 分钟

学会倒着爬了。豆豆自从学会了翻身,就一直努力往前爬,无奈年纪太小,腿脚根本不听使唤。可怜豆豆一把子力气,不知道往那里用才好。豆豆常常把手拼命往床上撑,胸脯挺得老高,自己跟自己较劲,一会脸就憋的通红了。后来豆豆就不用蛮力了,反正不好使。他有时候会突然一松手,身子扑到在床上,然后再撑起来看看挪了地方没。两个星期前,豆豆学会了原地打转:把肚子作为支点,两只手交错向左或右倒腾,几下子就能来个180度大转弯。最近,豆豆又学会了后退了:两只手先缩到胸前,然后他身体的前上方用力一推,他的肚皮就会朝脚的方向一划。他这一招效率还挺高,我们全家不得不对他提高了安全警戒级别,生怕他自己促溜一下掉到床下去。

这是豆豆在床上爬呢: DSC01389

豆豆给家里每人个都分了工:爷爷是抱他散步的;奶奶是陪着睡觉的;妈妈是用来吃饭的;爸爸是陪玩的。想干某件事了,就去找特定的人。比如说饿了,就会对着妈妈来一个十分谄媚的笑容;不饿的时候,看见妈妈,立刻把头一扭,就好像挡了他的视线一样。周末,豆豆睡午觉醒来,发现奶奶居然不在家陪睡,立刻就不高兴了。我和豆豆妈只好抱着他出门去玩,分散一下注意力,顺便给豆豆拍了几张外景照。

豆豆和爸爸: DSC01412

豆豆和妈妈的大头贴: DSC01430

豆豆喜欢别人逗他玩,一玩起来就嘎嘎嘎嘎笑得像个小疯子。他对游戏的要求还挺高呢,一定要换着花样才行。头一次玩骑大马、藏猫猫、举高高等的时候,他都乐的哈哈的;可是第二次再来就兴趣不大了;第三次还玩,就面无表情表示不满了。我们一家人早已使出浑身解数,现在都黔驴技穷了。

爸爸使出各种招数逗豆豆:http://v.youku.com/v_playlist/f5520621o1p11.html

豆豆晚上还是要吃着奶睡觉,白天倒是可以抱着他哄哄就睡了。哄他睡之前,他是一定要哼哼唧唧的才行。有时候能哼哼四五分钟才睡着,也不知道他这是表示高兴?表示不满?还是自己哄自己睡呢?

豆豆哼哼唧唧的睡觉:http://v.youku.com/v_playlist/f5520621o1p13.html

豆豆满五个月的时候开始添辅食。现在他主要吃的辅食只有配方米粉和苹果,他可爱吃这两样东西了。开始吃苹果的时候,我只给他刮一些汁,看他爱吃,就又刮了些末给他。现在我每天还会给他削一个苹果块,放在他嘴里咬。别看豆豆没牙,吃奶的劲可不是白练的。苹果块被他咬的嘎吱嘎吱响,一会就嗑出两个大坑来。

豆豆在啃爸爸吃剩的苹果核: DSC01398

豆豆吃米糊:http://v.youku.com/v_playlist/f5520621o1p14.html

查看或添加留言

反馈节点

· 阅读需 6 分钟

https://labview.qizhen.xyz/

基础

反馈节点和移位寄存器相比,他们的功能与本质是完全相同的。反馈节点的优点在于它不需要从循环的边框上去连数据线,因此可以把程序写的更简洁美观,尤其是控制或电子行业的工程师,他们本身很熟悉反馈的概念,可以直观理解这一节点的用途。但是由于反馈节点实际依赖于循环结构,而他们之间又没有数据线相连,使用反馈节点可能一不小心就把逻辑写错。

下图是一个简单的使用了反馈节点的程序代码,它的运行结果是什么?

image

但从这个程序我们是无法判断运行结果的,因为我们既不知道反馈节点的初始状态,也不知道它运行了几次。给定了这两个条件我们才能推算程序的运行结果,比如下图中的程序,运行结果是5。

image

那么下面这个程序运行结果是几呢?

image

如果出现循环嵌套的情况,反馈节点是针对于包含它的每一层循环结构的。它相当于在每一层循环结构上都建立一对移位寄存器,然后把它们串联起来。因此,上图程序运行的结果是25。

特别值得注意的是,反馈节点与循环结构不一定要放在同一个VI里。比如上上图里那个简单程序,当它作为子VI的时候,运行整个程序,result输出的值可能不是5,初始化的值就是不起作用。这个很可能是因为这个子VI的某个上层VI中还有循环结构,而这个循环结构能够影响它里面非常深层的子VI中的反馈节点。

运用下面的技巧可以让反馈节点变得更难以捉摸,如果你诚心想让人看不懂你的程序,不妨试试。

反馈节点有个使能输入端,右键点击反馈节点,选“Show Enable Terminal”可以显示出这个输入。它的输入为真时,反馈节点正常工作;输入为假时,反馈节点并不拿新的数据,而是把上一次得数据返回回来。大家猜下面这个程序运行结果是啥?

image

反馈节点只有在i为偶数时才工作,因此程序是在统计0~4中有几个偶数,结果为3。

移位寄存器出了可以可以返回上一次迭代的数据,还可以返回上n次迭代数据。反馈节点也有类似功能。右键点击反馈节点,打开它的属性配置对话框,在Configuration中可以选择Delay的次数,比如咱们设置延迟3次,那么反馈节点每3次迭代才把数据反馈一次。比如下面这个程序,result控件在程序的5次迭代中分别返回值1、1、1、2、2……,其运行结果是2。

image

那么多层循环会对延迟有什么样的影响呢?

image

在上图的程序中,result总共经历25次迭代。在这个多层嵌套的循环中,带延迟的反馈节点依然是每隔3次迭代(最里层循环的迭代)返回一次反馈数据。每次迭代返回的数据分别是:1、1、1、2、2、2、3、3、3、4、4、4、5、5、5、6、6、6、7、7、7、8、8、8、9。也就是最终结果为9。

最后大家猜一下下面这个程序的运行结果是几?

image

子VI有多个实例

今天又想到一个问题,于是编程序验证了一下。如果一个包含反馈节点的VI在主VI中有多个调用实例,那么它们之间是共享一个移位寄存器呢,还是每个实例有自己的移位寄存器呢?

这是子VI:
image

这是主VI:
image

程序运行结果如下:
image

看来它们是分享了同一个移位寄存器。

甚至子VI在不同的循环中被调用,它们也还是共用同一个顶层移位寄存器。比如下图这个程序:
image

运行结果:
image

只有把子VI设置成为每个实例都生成副本的可重入运行方式时,不同的子VI实例才会有独立的移位寄存器。

之前介绍的反馈节点内容:http://ruanqizhen.wordpress.com/2008/08/20/循环结构的反馈节点http://ruanqizhen.wordpress.com/2011/05/22/反馈节点

查看或添加留言

reference 死锁问题

· 阅读需 2 分钟

https://labview.qizhen.xyz/

LabVIEW中的引用经常需要和“In Place Element Structure”配合使用。In Place Element Structure 对一个引用的数据进行处理时,为了保证多线程安全,它会锁住引用指向的数据;其它线程若需对同一数据做操作,必须能这个In Place Element Structure中所有代码执行完毕才可,这样就避免了多线程读写同一内存数据所产生的竞争问题。

举例来说,下面这段程序的执行时间是1秒:

image

而下面这段程序的执行时间则是2秒:

image

因为第二段程序中的两个In Place Element Structure必须顺序执行。

有了“锁住”这个操作,就有不小心造成死锁的可能。比如对于同一数据的引用,千万不能嵌套使用In Place Element Structure,否则就会死锁:

image

在上面这个示例中,程序运行至内层的In Place Element Structure,就会停在这里等外层In Place Element Structure运行结束,释放它锁住的数据;而对于外层In Place Element Structure来说,它内部的全部代码要运行结束,它才结束。因而它们相互等待,造成了死锁。

查看或添加留言