Jump to content

[CR] GPower toolsets package


Recommended Posts

index.php?app=downloads&module=display&section=screenshot&id=207

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 :cool:). 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

Link to post
Share on other sites

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 by Steen Schmidt
Link to post
Share on other sites

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?

Link to post
Share on other sites

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

Link to post
Share on other sites

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!

Link to post
Share on other sites

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

Link to post
Share on other sites

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.

Link to post
Share on other sites
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 :thumbup1:

I PM'd you offline about this question.

Regards

-JG

Link to post
Share on other sites
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

Link to post
Share on other sites

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 by Steen Schmidt
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.