LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Parallel Loop, one fast and one slow: how to update FGV?

Solved!
Go to solution

So I implemented an FGV whereby 2 subvis running in parallel write to the variable.

 

However what happens is that one loop is much faster than the other loop.

 

Assuming the start value is X so the faster loop writes Y value as the new updated value, meanwhile the slower loop had already read X value, but as it is slower it does not know that the value has already changed to Y. So in the middle of running it still has X value instead of Y, so it writes Z value using X value instead of Y. So an error is introduced. Now when the faster loop reads again, it reads Z value which is a wrong value.

 

What was needed: One loop runs and waits for completion before the other loop runs or something similar to avoid that the slower loop is reading an old value that has already been updated by a faster loop.

 

Any ideas?

 

0 Kudos
Message 1 of 6
(2,141 Views)

There are a few options.  The most obvious is to use an Action Engine to maintain your value.  The idea is that all actions that will be done to that value should be done in the AE.  So in a single call, the value is read, acted upon, and updated.  Because the AE must be a non-reentrant VI, one call will have to wait until the other call is done.  This helps eliminate the race condition you are seeing.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 2 of 6
(2,134 Views)

Hi rajiv,

 

use a queue when you don't want to miss values when sending data from one loop to the other…

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
0 Kudos
Message 3 of 6
(2,132 Views)

The typical FGV buffers a single value, and that won't work in this case.

 

You can make a FGV that buffers values. The write would add values, the read returns all of them and (optionally) clears them (in one action). To do this efficiently, you'd have to make a circular buffer.

 

This would more or less be a custom queue implementation...

 

 

0 Kudos
Message 4 of 6
(2,110 Views)
Solution
Accepted by topic author rajiv85

While an Action Engine or the use of queues may be *part* of the solution, I think there's a more important underlying problem.  Basically, you haven't properly managed the dependencies and responsibilities for the calcs you're doing.

 

Take a step back, maybe two steps.  Think carefully how your calcs and results depend on the the different data that changes at different rates.

- do you want to be alerted instantly when data changes, and then immediately redo calcs?   Queues, Notifiers, or User-Defined Events can all provide this kind of mechanism.

- Which calcs must be redone immediately?   Can you group them together?   I don't know enough about your calcs to say for sure, but it's possible that the kind of calcs you need to do can be *packaged* inside an Action Engine.

- Which calcs can wait for the normal loop cycle?  Maybe some results aren't sensitive to using slightly stale data on some iterations, or are similarly not sensitive to missing a few rapidly-changing values since the previous loop.   Evaluating these things takes some careful thought.

 

I've put together a number of apps where various instruments or data acq devices are updating at different rates.  Much of the time, the updates to the display simply accept the fact that the slow devices will show stale data some of the time.  Yes it isn't down-to-the-millisecond fresh, but it *is* the most recent actual knowledge I've gotten from some slow serial device.

 

That's just one simple example, but the idea is that it's important to assess where data freshness matters (or doesn't), where low latency is needed (or not), etc.

 

In your example, it sounds like both the fast and slow loops both read from and write to the same FGV.   Direct writes to global storage (whether FGV or native global variable) from 2 independent loops kinda *begs* for the kind of race condition problems you're seeing.

   Expanding the FGV into a more full-featured Action Engine *might* be the simplest immediate path forward.   You may also need to take care with dataflow sequencing to make sure you read values out of the FGV / AE *as late as possible* before using them in a calculation.

 

 

-Kevin P

CAUTION! New LabVIEW adopters -- it's too late for me, but you *can* save yourself. The new subscription policy for LabVIEW puts NI's hand in your wallet for the rest of your working life. Are you sure you're *that* dedicated to LabVIEW? (Summary of my reasons in this post, part of a voluminous thread of mostly complaints starting here).
0 Kudos
Message 5 of 6
(2,091 Views)

Thank you everyone for your replies. Very helpful!

0 Kudos
Message 6 of 6
(2,064 Views)