LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Basic question about passing data between two parallel while loops

I have a VI with 2 while loops running in parallel (Loop1 & Loop2). I would like to have Loop1 set/clear a flag and Loop2 check that flag and act upon its value. I suspect there are more than one way to accomplish this.

 

Excuse my ignorance but can I create a Boolean indicator (Bool1) that Loop1 can set/clear and have Loop2 check the value of a Reference or Local Variable based on Bool1?

 

I also read that Channel Wires are a feature that can help achieve this.

 

Thanks

 

AJ

 

 

 

  

0 Kudos
Message 1 of 9
(292 Views)

Local Variables and References (as well as Global Variables) are, indeed, ways to ignore the Principles of Data Flow.  Prior to the "official" release of Channel Wires in LabVIEW 2016, a variety of other mec  hanisms (found on the Synchronization sub-Palette), such as Queues and Notifiers.

 

One of the (significant!) differences between "Synchronizers" (for example, Queues) and Local/Global Variables and References is what I might call a "Cause and Effect" relationship.  Take the example of two While Loops with one Stop Button in Loop 1 and a Local Variable of the Stop Button in Loop 2.  Start the Loops running at the same time.  Will they stop at the same time?  You can't tell -- did Loop 1 set the Stop before or after Loop 2 read its value?

 

So that's one virtue to, say, using a Queue to "synchronize" the exit from two While Loops.  The Stop button in Loop 1 goes to the Loop 1 "Stop" indicator, and also into a Queue that gets De-Queues in Loop 2, where it goes to the Loop 2 "Stop" indicator.  Loop 2 cannot exit before Loop 1 puts "Stop" into    Queue -- since everything goes into "Wires" (counting the Queue as a "kind of wire"), and you can keep these wires (temporally) "short" and next to their respective "targets", 

 

Asynchronous Channel Wires provide (in my humble opinion) a better metaphor (and also a better implementation) for asynchronous communication (which, paradoxically, you need to "synchronize" loops) because the "Channel Wire" goes "out" from the right end of the Writer, and "in" to the left end of the Reader, the same direction that data flows in every other LabVIEW structures.  For Queues and Notifiers, the connecting "wire" comes out the left end of both "Enqueue" and "Dequeue", which makes it appear that data "flows backwards" from the Enqueue function.  [I won't go into why this is only "confusing" ...].

 

In any case, if your goal is to have loops end at the same time, you want to use some kind of Synchronizer, whether from the Synchronization sub-Palette or Asynchronous Channel Wires.

 

Bob Schor

Message 2 of 9
(277 Views)

@AJ3D wrote:

Excuse my ignorance but can I create a Boolean indicator (Bool1) that Loop1 can set/clear and have Loop2 check the value of a Reference or Local Variable based on Bool1?

I also read that Channel Wires are a feature that can help achieve this.


You can, but it's not good form, as mentioned.

What you probably want is a Queue, Notifier or as you said, a Channel Wire.

G# - Award winning reference based OOP for LV, for free! ADDQ VIPM Now on GitHub
"Only dead fish swim downstream" - "My life for Kudos!" - "Dumb people repeat old mistakes - smart ones create new ones."
Certified-LabVIEW-Developer
Message 3 of 9
(234 Views)

@Bob_Schor wrote:

For Queues and Notifiers, the connecting "wire" comes out the left end of both "Enqueue" and "Dequeue", which makes it appear that data "flows backwards" from the Enqueue function.  [I won't go into why this is only "confusing" ...].

 

Bob Schor


Can you explain further what you mean? When I Enqueue something the data goes in on the left. When I dequeue something the data comes out on the right. Is the queue reference confusing? I understand that the queue reference doesn't come out from the enqueue and go to the dequeue (well, I guess it could, but then what would be the point of the queue, lol). Is that what you are referring to? I never thought of the data as flowing through the reference wire. I'm just curious as I've seen others talk about queues being confusing and I always found them to be very straightforward. Channel wires to me seem to be more confusing since they are wires that break dataflow.

Message 4 of 9
(227 Views)

@johntrich1971 wrote:

@Bob_Schor wrote:

For Queues and Notifiers, the connecting "wire" comes out the left end of both "Enqueue" and "Dequeue", which makes it appear that data "flows backwards" from the Enqueue function.  [I won't go into why this is only "confusing" ...].

 

Bob Schor


Can you explain further what you mean? When I Enqueue something the data goes in on the left. When I dequeue something the data comes out on the right. Is the queue reference confusing? I understand that the queue reference doesn't come out from the enqueue and go to the dequeue (well, I guess it could, but then what would be the point of the queue, lol). Is that what you are referring to? I never thought of the data as flowing through the reference wire. I'm just curious as I 've seen others talk about queues being confusing and I always found them to be very straightforward. Channel wires to me seem to be more confusing since they are wires that break dataflow.


Everything that can synchronize two parallel processes DOES "Break Dataflow."  What that really means is that some data communication must exist between multiple running sections of code.  All of them can be confusing if the only thing you think about is "Dataflow" where each node only starts when all inputs are ready and only ends when all outputs are computed.

 

The "Best" choice for your needs always requires two answers:

  1. What is the flow? A>B, B>A, A>Many, Many>1?
  2. What should happen if the Producer is faster than the Consumer? A Scalar value on an indicator should usually show only the current value so the communications could be "Lossy." while a measurement file should be "Lossless" and write every measurement.

Other factors can come into play as well.  Like, is the source really an "Event" like an alarm or a User Choice? Or is it maybe a large set of shared Data that should avoid copies and a DVR would be better.  

 

When you look at the communication path from those positions you can chose from the available Language Elements.

 

In what you described I would raise a User Event based on the condition that changes the value of the Boolean.  Others would use something else.


"Should be" isn't "Is" -Jay
0 Kudos
Message 5 of 9
(210 Views)

@JÞB wrote:

@johntrich1971 wrote:

@Bob_Schor wrote:

For Queues and Notifiers, the connecting "wire" comes out the left end of both "Enqueue" and "Dequeue", which makes it appear that data "flows backwards" from the Enqueue function.  [I won't go into why this is only "confusing" ...].

 

Bob Schor


Can you explain further what you mean? When I Enqueue something the data goes in on the left. When I dequeue something the data comes out on the right. Is the queue reference confusing? I understand that the queue reference doesn't come out from the enqueue and go to the dequeue (well, I guess it could, but then what would be the point of the queue, lol). Is that what you are referring to? I never thought of the data as flowing through the reference wire. I'm just curious as I 've seen others talk about queues being confusing and I always found them to be very straightforward. Channel wires to me seem to be more confusing since they are wires that break dataflow.


Everything that can synchronize two parallel processes DOES "Break Dataflow."  What that really means is that some data communication must exist between multiple running sections of code.  All of them can be confusing if the only thing you think about is "Dataflow" where each node only starts when all inputs are ready and only ends when all outputs are computed.

 

Oh, I realize this. I was just curious about Bob's reasoning as to me the break in data flow is more apparent in queues and notifiers than it is in channel wires. All of the approaches suggested here are valid, and depending on precise use cases some may be better suited than others. For the generic use case given I think that the OP would be reasonable to use whichever of the proposed solutions he is most comfortable with.

0 Kudos
Message 6 of 9
(204 Views)

Well let me explain the BS reason. Bob Schor likes Channels

QvsCh.png

Inspection shows both sections of the code do exactly the same thing both have unlimited (but limitable) elements that can be sent from loop to loop each will behave the same and except that the dice won't roll the same numbers they are two ways to do the exact same thing.  The only difference is how the data appears to flow along the Queue Reference or Channel wires.

 


"Should be" isn't "Is" -Jay
Message 7 of 9
(192 Views)

Yes, JÞB, that is exactly what I mean.  With LabVIEW, we "go visual" and can "see" the data moving around in "wires", generally going Left-to-Right (I wonder if the flow is reversed where Hebrew or Arabic are the major written languages -- no, that's just silly ...).

 

And I do like Channels.  Besides the "improved Metaphor" for Data Flow (going out the right side of the Writer and into the left side of the Reader), I also appreciate the built-in Sentinel in the Stream Channel (the LabVIEW 2019 Producer/Consumer Template still shows terminating the Queue by releasing it on the Consumer side, which generates a (deliberate?) error on the Consumer.

 

For those who are interested, the safer way to signal that a Queue can be terminated is to use a Sentinel.  The Producer, which gets (or generates) the data first, and thus "knows" when no more data needs to be sent, sends one last "special" piece of data, the "Sentinel" to the Consumer, and then exits.  It does not release the Queue, as it has no idea if the Consumer has finished processing the zillions of earlier Queue elements, so why run the risk of erroring out the Consumer?

 

One typical scenario (and "obvious" Sentinel) arises with Data-driven Producer/Consumers -- the Producer is something like a DAQmx Read that sends an Array of data (or some other data structure that has a non-zero size).  When the Producer wants to quit, it sends an empty Array (of the appropriate type -- if you are using Waveforms, send a Waveform with Y being an empty Array).  The Consumer simply looks at the data, and if it sees the special "This is the signal that you've processed all the data and can exit", it takes the Case Statement branch that does nothing except stop the enclosing While Loop, bringing the Queue Reference out of the Consumer Loop where it can safely be Released.

 

Bob Schor

Message 8 of 9
(155 Views)

@Bob_Schor wrote:

One typical scenario (and "obvious" Sentinel) arises with Data-driven Producer/Consumers -- the Producer is something like a DAQmx Read that sends an Array of data (or some other data structure that has a non-zero size).  When the Producer wants to quit, it sends an empty Array (of the appropriate type -- if you are using Waveforms, send a Waveform with Y being an empty Array).  The Consumer simply looks at the data, and if it sees the special "This is the signal that you've processed all the data and can exit", it takes the Case Statement branch that does nothing except stop the enclosing While Loop, bringing the Queue Reference out of the Consumer Loop where it can safely be Released.


This is a further argument to use the Streaming Channel Wire for a Producer/Consumer.

 

What if the producer has a recoverable error and therefore the waveform is empty due to the error instead of the sentinel actually being sent?  A couple of options would be to not send the data if there was an error or to add the sentinel to the waveform data variant.

 

Now what if the producer has a non-recoverable error?  You need to make sure that error does not interfere with the sending of the sentinel (the error wire cannot be directly wired to the Enqueue Element that sends the sentinel).

 

I think I have only created 1 Producer/Consumer since seriously considering Channel Wires, and I used the Streaming Channel.  The built-in sentinel solves the above issues.


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 9
(104 Views)