关于面向对象的方法并行执行的问题
这几天跟同事讨论到 LabVIEW 的面向对象编程中,如果我设计的一个类有一个方法比较耗时,那么当我实例化多个对象时,那么这个耗时的方法是怎么执行的呢?是各自并行执行还是,必须等某一个对象的方法调用完,接下来调用第二个对象的该方法呢?
接下来,我们直接来做个试验吧!
试验设计:
我们设计一个类——Person
该类包含的一个描述其状态的私有数据——State;
有对该数据的读写的接口;
有一个耗时的方法——WalkAWay
好了,类的程序设计完了,我们做一个 Main.vi 来进行测试:
我们看下执行的结果:
该 Main 程序共计耗时为 2 个对象的 Walk 方法执行时间之和:2000+1500=3500ms;
由此,我们可以看到,默认设计的类,其方法在各个对象间是串行执行的;
接下来,重点:
我们回去修改下我们设计的类的 WalkAWay 方法。
然后再执行 Main 测试 vi,执行结果:
该 Main 程序共计执行时间为最长按个 WalkAWay 方法执行的时间:2000ms.我们可以看到,这次就是并行执行了 WalkAWay 方法了。
至此,我们可以得出结论:
默认设计的类的方法是串行执行的。那么,如果有耗时的程序,我们可以通过调整方法的共享副本可重入属性来实现不同对象间调用方法并行执行。这个能大大节约程序执行时间,尤其是我们在多 slot 并行测试的软件设计时尤为重要。
说明:上述如果将方法 vi 的设置为第三个——预分配副本的话,类的设计会直接报错,也就是说 LabVIEW 不让我们这么设置。
附件:vi 的可重入属性的说明:
Non-reentrant execution 不可重入: 多个调用者调用此 VI 时,是按照顺序逐一调用的。优势是最小的内存消耗,同时也会使得所有调用该 VI 的共享一个状态,在调用中保留控件和未被初始化移位寄存器的值。
Shared clone reentrant execution 可重入:在实例间共享副本(减少内存使用),允许多个调用者同步并行执行该 VI,这个类型的可重入,为了减少内存消耗,在调用中复用克隆副本。
当调用者 B 调用该 VI 时,如果克隆实例正在被调用者 A 使用中,那么 LabVIEW 会分配一个新的克隆实例给调用者 B。
当调用者 B 调用该 VI 时,如果克隆实例没有被使用,那么 LabVIEW 不会再开辟新的克隆实例。因此每个调用者维护自己的状态,保留控件和未赋值移位寄存器的值
Preallocated clone reentrant execution 可重入:为各个实例预分配副本,允许多个调用者同步并行执行该 VI,这个类型的可重入,为每一个实例预分配独立克隆实例,并以开辟更多的克隆实例为代价。
那么 VI 何时使用可重入,并且到底选共享副本还是各个实例预分配副本?
场景和原则
当 VI 中有使用全局变量、或者功能全局变量时,不能设置成---->可重入:在实例间共享副本(减少内存使用)
如读取文件一类时,可以考虑设置可重入,使得调用者可以并行执行,提高效率。
当需要实现一些,共享克隆实例时,可以考虑使用--->可重入:在实例间共享副本(减少内存使用) 例如 递归操作。
如果 VI 克隆实例暂用资源很小,但是运行时间较长,可以考虑使用---->可重入:为各个实例预分配副本
VI 可重入设置,是为多线程调用准备的,如果在该 VI 被调用过程中,不会出现多线程调用该 VI,那么没有必要设置可重入,保持默认即可。
文章转载自:StephenYoung
评论