LabVIEW 8.5的Timed Loop优先级及双核处理器支持

 

Timed loop是LabVIEW 7引入的一个新VI,目的是为了提供具有确定性周期的定时方法。在LabVIEW 8里面又增加了Timed Sequence VI使我们编程更加灵活。不过随之而来也给我们使用造成困扰。

clip_image002

clip_image004

从上面两个图可以看出来Timed Loop和Timed Sequence的参数非常的多,很容易把人搞糊涂。所以就介绍一下主要的几个参数:周期,优先级,处理器分配。

周期Period (dt):

这个是Timed Loop专有的一个参数,指定循环的周期,作用和普通循环里放Wait[![clip_image006](http://byfiles.storage.msn.com/y1plQtNYHsRGl1GA1JOS9lLrlrTovEnvwhA63M5ptwHxPE7xlzLzahosrUwKKFHH5SV?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p3g1I9FEARVkht004Ovpn_CaHJS_z0abLpmuQz0vD544c8zt-kbUqXUoTSO-DFmxh?PARTNER=WRITER)是一样的,定时循环内的代码执行完毕以后会自动释放CPU时间供其它代码执行。

[![clip_image008](http://byfiles.storage.msn.com/y1pHWwtwZtFiNzczLTU1Pe5VuSRezX2fp4nPME0PjuTsXhIr4xZgHLzUOMVP4cnMeQ4?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p_5yQRnvPhM1veaUMfyWTLXKIxFv03jKdiKSl8LGNjJ2ifi6FjkdJKEnSDCOxMgmO?PARTNER=WRITER)

[![clip_image010](http://byfiles.storage.msn.com/y1p9SxAcpOPNa6WsxjLflinwQcGQOcPYo9H2rnwt7Co67AMnFwwgRB9Du33sB0cFxvl?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p2anbNOAzsZXIpKmZPtJahVCKaP2AynAcSXvf8Kqwswd84Z88Zdb2bwcpWIgEtt1Z?PARTNER=WRITER)

假如将循环周期占满则不会给低优先级程序运行,

[![clip_image012](http://byfiles.storage.msn.com/y1pK9OhVcxUho-FnydU7P2uLjwktIjH7BqQYxHzBK2Uo6xAF4Zp6yqLj99QCp8c1XFu?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pWYrElLUaWegCA5efKAxgzTM_GpoKdLsgT29Tq0T6iZui3eW-8TkztkS16hSy5ii6?PARTNER=WRITER)

[![clip_image014](http://byfiles.storage.msn.com/y1pOtJWC7xw-zRbzRCLfTtxcfCjBk-sL682Vasowf4gGjDVIc2qJi4xPqIPVgy1sdoy?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pyEvVmGtvcMbvc7q1WnAK4QJFrGoH7wZH6HD8dPSOy6sYGjmTUg7N4BwyNyPtFID7?PARTNER=WRITER)

注意要取消这两项钩选以确保不会将剩余时间放弃。

[![clip_image016](http://byfiles.storage.msn.com/y1pPML6MyHGFZz6-vvCfnoxHxUSgD5VTAHjUZgq6aUXLsqQXRLQUda-n70mSaQHPxSO?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pGXeQXo_vtM3eJqvn1txMr7vF35lC0ZmFjmxlaETJpM4RJp7I6syIK5b4tS_v0t4T?PARTNER=WRITER)

也可以将周期设为零这样就不会自动释放CPU了。

[![clip_image018](http://byfiles.storage.msn.com/y1p6KaeOHKZhHkURt_fdHLXJkeh7nSJuLiMJ4rddmmv--Tk-sUGApUIUashNbi7qOOO?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pWKf9tbw56dOhFS6BbXicgZO890x-ZzL3YS7fgXFiRHAgJfm-6SUfOCdy56IY5m3R?PARTNER=WRITER)

[![clip_image016[1]](http://byfiles.storage.msn.com/y1p8lnU9kUWGm8k52PTqyQ2-fVOXKa5q6UreYuY8G2DeNvSaNKtFb_bznH1hxhX5Hw2?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pJPZ1KHIMu_xVEvy343JDzK-2WtHtfd4j3lYcOIeEN7-5ZkwfTZE1ti59Koex9FZD?PARTNER=WRITER)

** **

优先级 Priority:

这里容易和Windows的优先级相混淆,所以先介绍一下windows的优先级概念。

对于NT内核系统都属于抢先时多任务操作系统。抢先多任务功能是由操作系统内部的调度器(scheduler)实现的,所谓抢先多任务就是CPU时间被分为一个个时间片, 调度器将时间片分给当前优先级最高的线程(thread ), 一旦有更高优先级的线程就绪,就马上抢先正在运行的线程,如果有多个优先级相同的线程,调度器把它们排队,先执行队头的线程,执行过的则放到队尾。线程的优先级范围从0(最低)到31(最高)。当你产生线程时,并不是直接以数值指定其优先级,而是采用两个步骤。第一个步骤是指定“优先级等级(Priority Class)”给进程,第二步骤是指定“相对优先级”给该进程所拥有的线程。

进程优先级等级共分为四等

“idle”等级只有在CPU时间将被浪费掉时(也就是idle time)才执行。该等级最适合于系统监视软件,或屏幕保护软件。

“normal”是默认等级。系统可以动态改变优先级,但只限于“normal”等级。当进行变成前台,线程优先级提升为9,当进程变成后台时,优先级降低为7。

“high”等级是为了满足立即反应的需要,例如使用者按下Ctrl + Esc时立刻把工作管理器(task manager)带出场。

“realtime”等级几乎不会被一般的应用程序使用。就连系统中控制鼠标、键盘、驱动器状态重新扫描、Ctrl + Alt + Del等的线程都比“realtime”的优先级还低。这种等使用在“如果不在某个时间范围内被执行的话,数据就要遗失”的情况。这个等级一定得在正确评估之下使用,如果你把这样的等级指定给一般的(并不会常常阻塞的)线程,多任务环境恐怕会瘫痪,因为这个线程有如此高的优先级,其它线程再没有机会被执行。

LabVIEW以及我们所编写的VI一般都属于normal级,驱动程序才属于high级。

另外对于XP来说realtime级并不是真正的实时,因为并没有给出时间上确定性的指标。对于CE来说其内核的realtime级才是真正的实时,可惜我们的LabVIEW还写不了CE上的RT程序。

对于线程优先级每一级来说又有7级优先级供调整

[![image](http://byfiles.storage.msn.com/y1pBR3ZF1casLTzP5QcaqUUvlfBKXJ6h2hqJ2XJf8k0GBXQaoS8zNdFG3MmCVIG83AR?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pM4-vL0bRF9rPmQ_tpDka9FMcfMvhQhL_7AgzlpYca7CucvJ4IIn9FxlHsWkgX6eP?PARTNER=WRITER)

我们在任务管理器里只能调整六级

[![clip_image020](http://byfiles.storage.msn.com/y1psFlSUT2h-e_jDbkcuUjC0-cZFjbSLzGH4x9G_705GUmxJZJpxdvfb2T6CfJLdG0Y?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pyMfm-9Dg36pLgmc4Y6ePnEFaweG9gobeJ5-nyIEC6-X3lCS1gtXNbSFAx24Yua7x?PARTNER=WRITER)

在LabVIEW里面对于进程是5级加一个子程序

[![clip_image022](http://byfiles.storage.msn.com/y1pOS0AvSorQNfT5_eH5zVmkC07cZ2iShEocrwBB35MKRdpH3QLwoLc0LeYy_jaKvt_?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p9n4lOnHf5OWkZ3W9DrWkuooQYXGfBBICj8SX9Ip8CmqiepZiK8gVK3_5BVm-FEP0?PARTNER=WRITER)

这个可以设置VI在那个线程里执行

[![clip_image024](http://byfiles.storage.msn.com/y1p1hshgW6kLFomKwGk-W2BUOkNCqXOpn-y3pY2F6jXAcXz-hieSP9Wij2K2WaFmMC-?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pUvll-e0ThEJKCQ1WxiIkUphVHnuB2GRBhRyKqj4l5OCuYGzWuiYWPahyDOeEwfco?PARTNER=WRITER)

对于代码,LabVIEW可以设置Timed loop和Timed sequence的优先级,这里的优先级应该和windows优先级不同,由LabVIEW管理,可以设置从0~65535的任意值。

[![clip_image026](http://byfiles.storage.msn.com/y1pOiaDeEpSrpxCGw2KwpbL_gSF6f1JG2jfZXDv4195CdOOMXxvBs_1J3w5tN4zn3WH?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pG5mOEvQGefKEyx7LSErsbktV-fEVqNqTMHmziN2KEj91CTykJM_EYjvUlYE61Mg2?PARTNER=WRITER)

** **

处理器分配 Processor Assignment:

下面是LabVIEW帮助里面的介绍:

在多核编程中使用定时结构

多核编程指一台计算机有两个或两个以上的处理器,每个处理器能同时运行一个单独的线程。而多线程应用程序能够同时在多个处理器上运行多个单独的线程。LabVIEW 5.0是第一个包含多核编程的LabVIEW版本。LabVIEW 5.0对用户界面线程与执行线程进行了区分。程序框图在一个或多个线程中执行,而前面板在另一个线程中进行相应更新。操作系统将对各线程进行抢占式多任务处理,即首先将执行时间分配给执行线程,其次分配给用户界面线程,依此类推。

定时循环和定时顺序结构的处理器输入端允许以手动方式分配用于执行结构的处理器。通过将输入值连线至结构或帧结构中输入节点的处理器输入端,可以配置如何分配处理器。 (Windows) 在配置定时循环、配置多帧定时循环、配置下一帧定时和配置下一次循环对话框的处理器分配部分,可配置处理定时结构的处理器。

如加载了来自前期版本LabVIEW中的VI并且其中含有定时结构,默认情况下,处理器输入端将被设置为0,其中0表示系统中第一个可用的处理器,在前期版本的LabVIEW中,所有的定时结构都自动运行于处理器0。

上面这段话里面“LabVIEW 5.0是第一个包含多核编程的LabVIEW版本”准确地说应该是包含多线程编程的版本,能充分利用双核技术的还是只有LabVIEW8.5。对于优先级可以看出LabVIEW的优先级有两级,一级是Windows管理的线程优先机,另一级是LabVIEW管理的代码优先级,虽然不知道LabVIEW那一级是如何实现的,不过优先级高的优先执行这个原则应该是不变的。如果要将LabVIEW程序迅速修改为单核运行,可以将程序另存为8.2版本。

如果你使用双核CPU,在windows的任务管理器里面就可以对进程进行核心分配:

[![clip_image028](http://byfiles.storage.msn.com/y1pI7HARdcCnimX_SAVqsluNzo4Sa3myihF_DZFCb-Vui_Dfxxrbzdtgoo-sblXhUSx?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1py6WJdt_nZMOGagXue5zFfltGJL_eOb8jA0aB3IIdTC4w6F7nOi0LwPP3ce9moBEI?PARTNER=WRITER)[![clip_image030](http://byfiles.storage.msn.com/y1pQmDWqgkBk6EH-r1wwq-U1Tf1oh9JP1Fb5pqdAt9x_Q1wwYRKrmvP7f3X5nL0rxOY?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pO072HCX7r2ExFgNWRUaI-pFxCv6OyXNqeNnvRVqhxwe-yrpyINlnO4DZm866hCK_?PARTNER=WRITER)

只给LabVIEW分配一个核心的话,程序运行就和单核上跑结果一致。

在LabVIEW 8.5里默认模式是自动分配,由LabVIEW负责分配不同的代码到CPU各个核心上执行,

[![clip_image032](http://byfiles.storage.msn.com/y1p0Zw1SEMc0FtdtcMNegXJaTTJe0madCkrnPlSAYQEEpbd51anzcnwVKSmkBKX6u1n?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pE5wkzcxI14couWkQLNKHhe1-Umx6Dc7L3AzdOgsOTONpSdrdq3UaonLZ-_QWjiGW?PARTNER=WRITER)

也可以手动指定运行代码的核心,输入介于0和255之间的任意值,0代表当前的处理器。输入的数量超过可用处理器的数量时,将导致一个运行时错误且定时结构不执行。

[![clip_image034](http://byfiles.storage.msn.com/y1pGBo3w0cgME8F5Yo-Y-3YCXK8JwHSbLE1zdgQghD2GMyyh2FD867prmy-w2Jt3kaq?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pNnjrlVfDJYssQODeimdqVJ18pMOjopPwTzQnpn1zuHxJDl0jqgjexmgdHOxQxYYR?PARTNER=WRITER)

对于timed sequence结构,可以指定每一帧的处理器

[![clip_image035](http://byfiles.storage.msn.com/y1p8qloU1H2NT0ij5iRfHEo7oc725IfjqF4jX2tmT31Vcgu-j3HAtqIZGq2jdguj6wr?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p6b0zRWml8lPAAJ-W4bezhipjyIUGI6z-bzIhMlGmRI06kgSqsi-df_JLXHc1pRts?PARTNER=WRITER)

在多核执行的情况下程序执行的结果和可能单核的情况下有所不同,因为不同优先级的代码可能同时执行,如果要严格规定程序的执行顺序,可以使用错误簇和数据连线。

[![clip_image037](http://byfiles.storage.msn.com/y1p2LGP9NiwgXjbPp_5iUnrntr90mlNjjm0lHLtkpL_xv_2pzqwvIVjrKfEoAYt_LDQ?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1p2qZUtSNcRTM97N7dj3shbgSDf0eat4uhPlnQMI8xA1NqKEmfLWWsiOai6cFmpLfP?PARTNER=WRITER)[![clip_image039](http://byfiles.storage.msn.com/y1pwJ91E9dNMAyip5qle4tWXbYo9JMFH8wYH5cPyzd7V2umXHikEvOJo3NAts6wMTvz?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1ptDI7UwfVTmFrWNeHh7kfjQYKRZ3hmQ1epRAAE8--wg433F7E2KG1pM6Uhdi3JH69?PARTNER=WRITER)

总结:

LabVIEW 8.5的优先级可以按Windows的优先级理解,优先级高的优先执行,执行完或者释放CPU之后才轮到低优先级代码执行。在多核的情况下低优先级代码可以和高优先级的代码同时执行,因此程序的结果可能和单核情况下不同。一般来说这是有助于提高程序执行效率的,没有必要更改,不过导致错误的话可以按以下办法解决。

解决办法:

1、 让程序以单核方式运行,可以在LabVIEW里指定核心(例如另存为以前版本就是一个很快速的办法),也可以在任务管理器里指定CPU关系到某个核心上。

2、 对于要求固定顺序执行的代码可以通过错误簇和程序连线来保证,使用信号量也是一种解决办法,还有一种办法是全局都指定成一个时钟源,然后在各个结构指定开始时间。

对于Timed Loop有以下几点要注意:

1、 CPU的释放:循环周期的设置,循环内代码如果没有把时间用完,会把剩余时间释放,分配给其他代码。在超时的情况下,如果钩选了保持初始相位也会把从代码结束到下一循环开始之前的时间释放。另外如果有Wait等函数也会释放时间。要想不释放CPU可以将用代码剩余时间都填满(这一点不好做到容易超时),或者将循环周期设为零。

2、 CPU的分配,建议使用自动分配,因为如果核心指派错误代码会不执行。必须要手动分配的情况下,比较可靠的办法是利用代码测出当前计算机CPU数目,然后用不同的CASE处理。

[**Using the GetSystemInfo Function from Kernel32.dll in LabVIEW**](http://zone.ni.com/devzone/cda/epd/p/id/3720)

[![clip_image041](http://byfiles.storage.msn.com/y1pPkvBHzbFvZSrWkwPmWwnis6jFwOMpA2iO-J301JW6uibVlYGxJ7afKd_RmUAXsf8?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pE4cU26qWk7rtt9INEEE3az-2XbwqHE4iYcs3SjjQus4bSikgF5MlVAeQrEjH1ZSC?PARTNER=WRITER) [![clip_image043](http://byfiles.storage.msn.com/y1pJjRrE9W3CN7M9dCotB3PBh0CLcqlNiVRUMbPNb_uX8gn4i10gEgpJ_-EfYcK_A4G?PARTNER=WRITER)](http://byfiles.storage.msn.com/y1pj1u2GaoZNLIUb7Q3G6kycO7A-uzjmo1so-eAfDH4q2AC1I9-X4xP9fwzV_2UsSwj?PARTNER=WRITER)