LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

how to exchange data between parallel running subVIs

Hi all,

In my App I've got 4 subVIs running in parallel with while loops inside. Can you tell me the best way to communicate between them? For example a while loop in subVI_1 has to process the data from the while loop in subVI_2. Or while loop in main VI has to pass information to all subVIs to stop while loops an terminate operation.

My current solution is:

- in main VI I initialize a cluster with all data and control signals

- I pass to subVIs Reference of this cluster

- in subVIs I read / write to the cluster using Property Node and bundle/unbundle

 

I've tried ques but this solution seems to be cleaner for me. Can I do it better?

0 Kudos
Message 1 of 14
(3,691 Views)

reading/writing property nodes sometimes are slow, using queues are better.
Read/write pr.node only when something changed, i mean

0 Kudos
Message 2 of 14
(3,679 Views)

Hi Tomasz,

 

For example a while loop in subVI_1 has to process the data from the while loop in subVI_2.

Use a queue.

Think Producer-Consumer structure…

 

Or while loop in main VI has to pass information to all subVIs to stop while loops an terminate operation.

Use a notifier.

Or a global variable. (In WORM aka "write once read many" mode.)

Or stop the subVIs when the producer queue is killed…

Best regards,
GerdW


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

Hi,

 

basically it seems as though you're using the cluster as a global variable and passing references to subvis to modifify the global variable.   If you want to use a global variable, just do that, no need for references.

 

That being said, global variables are usually a bad thing.  Funny things start to happen when you read/write from different locations in your code, like race conditions.  For passing data between loops, I would suggest queues, or channels.  Evaluate them, they are made for this kinda thing.

 

For your termination, I've always used a notifier.  I encapsulated this in an api which had 4 subvis (init, read termination notifier, write termination notifier, close).  This way, you have the notifier code centralised and can also react to any errors that might be passed.  

 

Depending on your requirements, there isn't a one-stop answer.  What I do know is that global variables tend to be a bad thing if not used properly.

0 Kudos
Message 4 of 14
(3,663 Views)

here's the example.

Yes it looks like a Global Variable but it's much faster (I've tested the performance)

The thing is that there's no an easy classification producer - customer. In target applications each while loop can produce something and be a customer for a data. So it need to access something and it need to be able to write its' own data. I'm passing the "terminate" information in cluster since it's already there and it costs me nothing to do it.

0 Kudos
Message 5 of 14
(3,653 Views)

Hi Tomasz,

 

The thing is that there's no an easy classification producer - customer. In target applications each while loop can produce something and be a customer for a data.

This leads to a discussion about using the proper code architecture…

 

So it need to access something and it need to be able to write its' own data.

What about CVT (current value tables) aka TagBus aka VariantAttributes implementations?

Best regards,
GerdW


using LV2016/2019/2021 on Win10/11+cRIO, TestStand2016/2019
Message 6 of 14
(3,635 Views)

@TomaszCiesla wrote:

here's the example.

Yes it looks like a Global Variable but it's much faster (I've tested the performance)


I would really like to see that benchmark code.  Every time I benchmark with property nodes, they are 1000s of times slower than local variables and global variables.

 

As far as what I do, I use a Queue or User Event to pass data and messages to my loops.  I set them up as Queued Message Handlers.  Included in those messages is the stop message.  I find it best to limit the types of communications to 1.


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 7 of 14
(3,620 Views)

We've got a measurement setup in the lab and idea is to control / read each equipment as a separate subVI in independent while loops.Hardware works with frequencies 0.1...2 Hz so the performance is not an issue.

So how can I convert my example to Queues?

0 Kudos
Message 8 of 14
(3,616 Views)

That references.vi code is riddled with race conditions galore.  Your second loop can very easily overwrite the data that loop 1 just wrote and visa versa.  In fact, I see a scenario that you will not be able to stop 2 of your 3 loops because of this race condition.  Have a look at this document I made: A Look At Race Conditions.  I did not cover the property nodes, but it will follow the same concepts as the local variable except A LOT slower.  I might just go ahead an update that benchmark to include the property nodes when I feel like going for a long walk since it will take forever.

 

So let's boil down to what you actually need here.  Do you need your main loop to handle ALL of the data or just the latest data at that moment in time?  This is a very important requirement to define.

 

If you only care about the latest data, then we are dealing with "Tag" data.  Ways to pass Tag data for only 1 writer are Global Variables or Tag Channel Wires.  If you are doing a Read-Modify-Write on the data in multiple places, then you need to look at an Action Engine.

 

If you need to process all of the data (for example, logging), then you really need to look at the Queued Message Handler.  Use a single queue.  In the queue data type should be a string (or enum) to state what the data is and a variant to hold the actual data.  The QMH can then handle the data however it needs to.

 

Your stop condition is the perfect example of a Tag.  So I would just use a Global Variable.  Alternatively, you can use a Notifier which will double as your wait function when using the timeout.


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 9 of 14
(3,602 Views)

I need logging. So let's got into the details a bit. Let's say that I've got 2 devices: pump and climate chamber. I need to be able to log the data from both and give them a setpoint (temperature, flow). Since there are more devices in total preferable architecture are parallel while loops.

 

- The device's while loop puts one the queue its' registered value (time + value) as string

- The main while loop reads the queue, decodes the data and builds tables for logging from it

- The main while loop communicates stop signal and setpoints using global variables

 

so in this scenario I abandon bidirectional approach - the device's while loop can only stream the data to mail while loop. And main while loop communicates with device's while loop using the global variables

0 Kudos
Message 10 of 14
(3,596 Views)