From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

RT Global Variables and Loop Speed

Hi, I need help from someone who understand RT better then me (that's most of you probably!)

 

Hardware is PXI-8106, running LV-RT 8.6.  Host is XP

 

I am working on a large application with multiple timed loops inthe RT, interacting with each other using many variables.  I found one loop taking an inordinate length of time to complete - more than 2s sometimes, when the timer wanted about 50ms. During this time the 2 processors have about 20% - 25% idle time - busy but not saturated. Is this normal?

 

The only thing I could see in that slow loop was a few Global Variable calls.  So I investigated, and found (eventually) advice culminating in this guide which recommended dumping the Global Variables in favour of Network Published variables.  So I went away and changed a whole heap of globals into a series of network vars, as can be seen in these snapshots of the same bit of code before & after: (they're big, sorry)

 

LVRT Vars Before.png

Before

 

LVRT Vars After.png

After

 

A few variables remain as Globals, but the vast majority are now in these Networked variables.  Now my code runs slower than before - about twice as long per iteration! And now the processors only have abouy 5% idle time.  Not much of an improvement...

 

What is the best way to share large numbers of individual values?  I don't need FIFO, as only the newest current value is of interest. 

 

And how can I work out where my time is being spent in timed loops that take too long? 

 

Thanks for any tips, including better ways to post large images Smiley Sad

0 Kudos
Message 1 of 15
(3,670 Views)

1. If you are just passing data between loops on a single RT target then you will get much better performance using Functional Global Variables (FGV) basically storing your data cluster in a shift register of a while loop.

2. If you need to get the data up to a windows HMI then you can use NSV's but will probably not need to update at 20Hz.

3. Could not tell from your code but your DAQmx reads should be preceded by a Create Task otherwise they will be very time consuming.

4. BTW, the index array function will be default assume consecutive indexes so you should not need all those constants.

Message 2 of 15
(3,666 Views)

One tip to save you a lot of time in the future.

 

You don't need to wire up all of those indexes to the Index Array function.  When you extend the Index Array function downwards, all the inputs are the next in series by default, and they automatically start with zero.

 

So with what you've shown, you could eliminate all of the blue constants and you'll find the code works the same.

Message 3 of 15
(3,660 Views)

sachsm,

 

Thanks for your reply. 

 

There is one RT target, with several VI's running in parallel.  Dat to the host is not needed in RT, but is handled elsewhere by different network variables. 

 

There are a series of DAQmx Create Channel & Start Task blocks upstream of the reads.

 

I have seen references to Functional Global Variables before.  Maybe I'm being thick but I don't know what they look like.  I guess they're not the same as a Global variable VI.  Looking again at http://zone.ni.com/devzone/cda/tut/p/id/4682 I see the pictures.  Do I need to build this as a separate VI, with a control and indicator for each value, or is this all handled automatically somehow? 

 

I'll try building one and see what happens. 

 

Thanks,

Ian

0 Kudos
Message 4 of 15
(3,652 Views)

You might want to store (write) your data as an array and read it out as a cluster with the names of each I/O point defined in the cluster elements.

A little trick...Inside your FGV you can use a typecast function to convert between the whole input array and the output cluster.

 

0 Kudos
Message 5 of 15
(3,646 Views)

I was thinking about that last night (sad I know), but to write a cluster would require two calls to the FGV, but reading is only one.

 

A few other specific questions:

 

1.  Is "Functional Global Variable" another clever, internally-managed LabView construct (such as Network Published Variable, Global variable, etc), or is it just a complicated name for a simple VI that you need to build yourself?

 

2.  How would it work if I have several variables defined in the FGV, but at some point in the code I only need to change one of them?  Will the FGV keep the current value for the others, or do I need to explicitly repeat the other values?

 

3.  If I use the suggestion in http://zone.ni.com/devzone/cda/tut/p/id/4682 to Skip Subroutine Call If Busy, what happenes to my time-critical loop if it is unable to access the FGV?  It will proceed I guess, but if it cannot read the FGV what value will it proceed with? 

 

Thanks,

Ian

0 Kudos
Message 6 of 15
(3,634 Views)

NI used to teach using an Action Engine for RT loops.

 

You will have to define each of the operations associated with your data (Set falg, Togel Y, etc).

 

To avoid rae conditions make use all of the read mod write functions are encapsulated in the AE.

 

Re: skip if busy...

 

If other code is running the AE code when the RT loops tries to use teh AE with the "skip if Busy" flag set the AE call will be skipped and any values retrned by teh AE will be teh "default-default" for teh data types. E.G. I usually return a flag set true labeled "executed". When the AE is actually run by the RT loop (and not skipped) the boolean is true. When it is skipeed the dault value for booleans (deault = F) is returned letting my RT loop know it should ignore the data coming fro the AE.

 

BTW:

I tried getting globals to work once and was never able to get them to stay deterministic. AE's have worked since the early days of RT and still are useful.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 7 of 15
(3,619 Views)

I would be surprised at 20Hz that a simple FGV or Action Engine (without skip if busy) could not keep up with your timed loops.  I often run timing tests where I run my code 1000 times in a loop.  I would guess your FGV would be < 100us/iteration.  Also feel free to put everything in one FGV or divide up your datsets into multiple FGV's.  Whatever makes sense.

0 Kudos
Message 8 of 15
(3,607 Views)

Ben,

 

Thanks for the link, that Action Engine nugget is very useful.

 

One further question: does it matter if I take the outputs from the shift register, or should they always come from a separate wire?

e.g.

DigOutGFV.png

Here I have one array which contains the status of all digital lines.  When a single line is updated the element name ring is used to define which array element to update.  The full array is then split into two, to match the hardware ports.  There are therefore three shift registers.  I take the outputs directly from the two split arrays, not from extra wires as in the examples elsewhere.  Does this matter?

 

Thanks,

Ian

0 Kudos
Message 9 of 15
(3,575 Views)

@IanDeaville(TRW) wrote:

Ben,

 

Thanks for the link, that Action Engine nugget is very useful.

 

One further question: does it matter if I take the outputs from the shift register, or should they always come from a separate wire?

e.g.

...

 

  Does this matter?

 

Thanks,

Ian


Thank you for the complement on the AE Nugget

 

Spoiler

(I am still accepting Kudos for that thread, wink wink nudge nudge).

  Smiley Wink

 

Did you get to the part of the thread where Jim Kring taught us about using wrappers for each action?

 

I use those in most of my apps with AE's for all of the reasons mentioned there.

 

Re:Does it matter?

 

For small data sets you would have a hard time measureing the difference in performance between the two but for larger set or apps that use the AE very often (so it has to be fast) the best answer I can give is to invite you to revie the "Clear as mud" thread found here.

 

That thread discusses the various ways we can pass data to/from sub-VIs and what we can do to structure our code to let LV optimize buffer re-use.

 

I hope that helps,

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 10 of 15
(3,561 Views)