Steen Schmidt Posted March 15, 2012 Report Share Posted March 15, 2012 Name: GPower toolsets package Submitter: Steen Schmidt Submitted: 15 Mar 2012 Category: *Uncertified* LabVIEW Version: 2009 License Type: BSD (Most common) This is a submission for the GPower toolsets palette, which will also shortly be available on the NI LabVIEW Tools Network. I submit it to Lava to (of course) share it with everyone, but also to establish an open forum to discuss improvements and to provide support. Much better than hiding all this in private email conversations with each user. The toolsets are compiled for LV2009 SP1, are provided as VIPs for VIPM, and will mass compile to at least LV2010 and LV 2011 without problems (this happens automagically during the VIP-install process for those of you that don't know VI Package Manager ). The 'gpower_lib_toolsets-1.0.0.6.vip' is an umbrella for the four other VIPs, it doesn't add anything extra by itself. Currently this consists of 4 toolsets: Dynamic Dispatch Open, pass data to (without using the front panel), run, and close dynamic VIs. A cumbersome process using VI Server made easy with this toolset. Error Streamline common error wire tasks such as set, filter and clear errors and warnings, and unbundle the error cluster. Adds advanced features such as dynamic setting of custom global errors, that you can invoke from anywhere in your application, and bundling errors into a single error wire. No more need for arrays of error clusters! Timing Calculate elapsed and remaining time, and abort a running Wait function for instance. VIRegister High performance "global variables" that lets you pass data between any corners of your application. It's based on queues, so a "global" that does not involve using front panel controls, files, or the LV project - it all happens in the block diagram. In most cases you don't even have to pass a refnum around, just drop a VIRegister somewhere and you're done. If this thread generates too much noise across the different toolsets, we could split this into 4 submissions. But lets see how it goes. More toolsets are awaiting release, but I'll start with these four to get a feel for the process. Cheers, Steen Click here to download this file Quote Link to comment
Steen Schmidt Posted March 16, 2012 Author Report Share Posted March 16, 2012 Note to self (and Michael et al perhaps ): Should this thread be in the 'LAVA Code on LabVIEW Tools Network' forum instead? Anyways, let's see what you say about the code, if it should be here at all . Cheers, Steen Quote Link to comment
Steen Schmidt Posted March 18, 2012 Author Report Share Posted March 18, 2012 (edited) Since nobody else is replying I might as well keep this thread going with an important bit of info : A VIRegister must be located in an unshared call chain if you do not wire the Scope VI reference input! This means that no VI, in the call chain from the Top-Level VI all the way down to each caller that contains a VIRegister function, may be configured as shared reentrant nor non-reentrant. Only preallocated reentrant will work. The reason is that a VIRegister can be seen as equivalent to an uninitialized shift register when the Scope VI reference input isn't wired. The only way to get around this (as far as I can currently see) would be to check the Top-Level VI identity at each read and write - and that would make a huge negative impact on performance. There will be a note about this in a future update to the user guide, unless I find some elegant way to get around this limitation. Cheers, Steen Update: A quick test shows a 100 times performance degredation if I need to pull the call chain on each access. That's unacceptable. But I can make the VIRegister throw an error at runtime if it finds itself in a possibly shared call chain, without any impact on performance. That is acceptable for now I think. Edited March 18, 2012 by Steen Schmidt Quote Link to comment
asbo Posted March 18, 2012 Report Share Posted March 18, 2012 How does the VIRegister performance compare to the performance of a LV2 global? Is there any benefit using VIRegisters, except that you wouldn't need to create your own VIG VIs? Quote Link to comment
Steen Schmidt Posted March 19, 2012 Author Report Share Posted March 19, 2012 For a single I32: VIRegisters are 10-15% slower for a single read/write than the simplest LV2, but much faster than the LV2 for parallel reads (twice as fast for 5 concurrent reading loops for instance). Performance may depend somewhat on data type (the case for both technologies). I see the biggest benefit from VIRegisters in the fact that you don't have to tie them to anything to make them work. With globals and LV2 vars you need to create and maintain a file on disk. A local you must bind to a control/indicator on the front panel, and you'll have different sorts of performance and compatibility issues depending on the configuration of said control and hosting front panel (and you can't easily share this data between VIs). Variables like Shared Variables you must configure in a LabVIEW project, and they may need additional backends to work (the SVE for instance). A VIRegister basically wraps up a single element queue. You are given automatic obtain, error handling, and the most performance efficient method for accessing this queue. And it all lives inside a single "template"; the VIRegister polyVI. That it also performs almost as well as the fastest ordinary variables is just an added benefit in my mind. Even with 10 times worse performance I'd been happy (I actually improved performance from ~10,000 reads/s to more than a million reads/s along the way). /Steen Quote Link to comment
Götz Becker Posted March 19, 2012 Report Share Posted March 19, 2012 The dynamic nature of VIRegister has a drawback when used with dynamic code. Since the obtain refnum is done directly done, the potentially new global refnum has the lifetime of the calling VI references. e.g. use this with a dynamic TCP handler and created a new named register inside the dynamically instanced VIs. This new ref will be invalid when the instanced VI goes idle. This can produce some very hard to find bugs if not all references are obtained in a permanent running VI! Quote Link to comment
Steen Schmidt Posted March 19, 2012 Author Report Share Posted March 19, 2012 The quick answer would be that you have no need to communicate with idle code. The VIRegister instance(s) you create in the calling (non-idle) code will continue to live. There is no risk of a VIRegister in running code going unreferenced due to some other dynamic code going idle. Each instance is self-referencing as named queues are used - there is no "owner" of the queue other than the LV instance. That would've been the case with unnamed queues. /Steen Quote Link to comment
Götz Becker Posted March 19, 2012 Report Share Posted March 19, 2012 The "owner" is still the VI and it gets cleaned up no matter what. This can lead to a race condition which may lead to lost writes. I hacked together a small nutshell (LV2011) to demonstrate the problem. test_vi.vi tcp_server.vi tcp_conn_server.vi As long as you know all variable names in the static part and access them at first there, this is not a problem. But this detail can be easily forgotten and when such an app grows, it could be a nightmare to debug. Quote Link to comment
Steen Schmidt Posted March 19, 2012 Author Report Share Posted March 19, 2012 Thanks, I'll take a look. Cheers, Steen Quote Link to comment
jgcode Posted March 20, 2012 Report Share Posted March 20, 2012 Note to self (and Michael et al perhaps ): Should this thread be in the 'LAVA Code on LabVIEW Tools Network' forum instead? Hi Steen Congrats on the code release I PM'd you offline about this question. Regards -JG Quote Link to comment
Steen Schmidt Posted March 20, 2012 Author Report Share Posted March 20, 2012 The "owner" is still the VI and it gets cleaned up no matter what. This can lead to a race condition which may lead to lost writes. I hacked together a small nutshell (LV2011) to demonstrate the problem. test_vi.vi tcp_server.vi tcp_conn_server.vi As long as you know all variable names in the static part and access them at first there, this is not a problem. But this detail can be easily forgotten and when such an app grows, it could be a nightmare to debug. Oh, now I see what you mean. For sure, if you obtain a named queue A in callchain B and B goes idle before anyone else obtains A, then A will be released, thus losing any data in it. That's correct. Hmm, what would an elegant way around that be? I think a requirement of having to read all variables at least once at each call site is too much. The data should remain in memory even after callchain B goes idle. I'll have to think about this for a moment. Thanks for taking the time to construct the example. Cheers, Steen Quote Link to comment
Steen Schmidt Posted March 22, 2012 Author Report Share Posted March 22, 2012 Within the next few days I hope to have an update to the VIRegister toolset ready. This update fixes the issue brought up by Götz Becker without sacrificing too much performance. Cheers, Steen Quote Link to comment
Daklu Posted March 28, 2012 Report Share Posted March 28, 2012 You might consider changing the name of your dynamic dispatch toolset to avoid confusion with LVOOP dynamic dispatching. Quote Link to comment
Steen Schmidt Posted March 29, 2012 Author Report Share Posted March 29, 2012 You're probably right Dave. Any ideas for a good name? Cheers, Steen Quote Link to comment
asbo Posted March 29, 2012 Report Share Posted March 29, 2012 Asynchronous Worker sprang to mind, but having not used it yet I don't know if it's actually async. Quote Link to comment
Steen Schmidt Posted March 30, 2012 Author Report Share Posted March 30, 2012 (edited) It is asynchronous. The toolset simplifies the process of dynamically calling, sending data to, running, and closing a VI. Like when you open a VI reference, setup control values on it with VI Server, Run it with VI Server, and then close the reference, possible invoking the Abort method if the dynamic VI hasn't stopped when you needed it to. So Dynamic VI Call & Run would describe it quite clearly, but is cumbersome. The VI Call & Run part I combined into Dispatch, but that makes the name conflict with launching class member function VIs. Dynamic Call(er)? Dynamic Launch(er)? Dynamic Load(er)? Dynamic VI Call(er)? Dynamic VI Launch(er)? Dynamic VI Load(er)? Dynamic Invoke( r)? I'm probably inclined to Dynamic VI Caller at the moment. Cheers, Steen Edited March 30, 2012 by Steen Schmidt Quote Link to comment
drjdpowell Posted March 30, 2012 Report Share Posted March 30, 2012 I usually use “launch” to mean asynchronously running a VI, so “VI Launcher” sounds best to me. Quote Link to comment
Steen Schmidt Posted March 30, 2012 Author Report Share Posted March 30, 2012 VI Launcher is noted. I like that, and I agree that 'launcher' underlines the async behavior, where 'caller' can be both. /Steen Quote Link to comment
Daklu Posted March 30, 2012 Report Share Posted March 30, 2012 I agree with "launch." It's also keeps the lingo consistent with the Actor Framework terminology. Quote Link to comment
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.