LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Queue implementation and stopping parallel loops

Solved!
Go to solution

I did here a small psuedo code to learn queue handling and parallel loops execution.

I need to stop the loops at the same time so i used a local variable of an indicator and did the program.

The problem is in the VI attached below the loops are stopping when i press stop button in the front pannel but the program is not stopping, its still in execution.

It only happens some times. I noticed that when the loop interations of first loop are more than the second loop than the program stops but when the case is viceversa it doesnt

 

Please help me understand why is that.

 

0 Kudos
Message 1 of 11
(8,073 Views)

Hi, Rex_Saint,

 

There are several ways to make it.

1) You can set the timeout to the dequeue function or it will listen forever without wiring.

2) You can move the release queue function to the upper loop, and add the case after the dequeue function.

     That is, the queue is released after you've pressed the stop, and then the dequeue will generate an error as the queue is released.

     The error can be determined to do a stop action by a case selection.

 

Message 2 of 11
(8,067 Views)
Solution
Accepted by topic author Rex_saint

If you are not enqueueing data, then the Dequeue functions will just sit there and wait forever.  Not what you want here.

 

I also do not like the idea of using a local or global variable for stopping your loops.  Yes, there are places where it is the best option.  But that should be avoided when possible.

 

I have used destroying of the queue to stop consumer loops.  But there is a major flaw in that: data loss.  If you enqueued 100 elements and then destroyed the queue, any data that was not dequeued will be lost.  In some situations, that is fine.  With most of my applications, that is not allowed.

 

So what I like to do is use the queue data to send a Stop command.  In your example case, I would send an empty array to tell the consumer loop to stop.  There is a really simple function in the comparison pallete to check for an empty array.


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
Message 3 of 11
(8,018 Views)

Often times, my Queues go between parallel loops that run in completely separate VIs (some of which might be running asynchronously).  The method I use is to use a "Write-only" structure (a VIG, a Global Variable, or, my preference, a Local Shared Variable) with a name like "Stop Loops" that is initialized (or set by default) to False and set to True when I determine it is time for the Loops to stop.

 

To prevent loss of data in the Dequeue loop that Crossrulz mentioned, I put a Timeout on my Dequeue of something like 10-100 msec and wire the "timed out" case to "do nothing except check for the Stop Loops condition".  I put the code that releases the Queue on the output of the Dequeue loop.  So the sequence goes like this:

 

Producer puts stuff on Queue.  Consumer empties the Queue, doing whatever you want with the data.  If there's a pause in the Producer, the Consumer might time-out, and would see that Stop Loops is not true, so would "do nothing", and wait for another Queue element.

 

Now user says "Time to Quit", and sets Stop Loops to true.  The Producer sees this, and stops producing, putting no more elements on the Queue, and exiting its loop.  The Consumer empties the Queue, and will time-out since the Producer isn't producing, and now will see that Stop Loops is true, and will exit.  On exiting, the Consumer destroys the Queue, since both the Producer and Consumer have stopped (and therefore stopped using the Queue).

 

If you have multiple Producers, this should also work.

 

Bob Schor

Message 4 of 11
(7,984 Views)

Thank you William, Cross_rulz and Bob. I got now, why the VI is not being terminated.

And yes the method of sending empty array and stopping it worked very well for my main program. Thanks a Lot.

0 Kudos
Message 5 of 11
(7,955 Views)

Sir have this doubt in my mind. Say i am using producer consumer structure as in here.. Where producer being "data aquisition loop" and consumer being "processing loop".  In such a case if my producer loop is running twice as fast as my consumer loop then isnt there a chance of my queue getting filled completely after every few interations. How shall i deal with such a situation.

0 Kudos
Message 6 of 11
(7,929 Views)

@Rex_saint wrote:

In such a case if my producer loop is running twice as fast as my consumer loop then isnt there a chance of my queue getting filled completely after every few interations. How shall i deal with such a situation.


You are more likely to get an Out of Memory error due to you not specifying a queue size.  But that's beside the point.

 

Depending on what your "data processing" is doing, you may be able to just use a duplicate consumer loop.  This would cause both loops to dequeue from the same queue, effectively doubling the rate at which the data is processed.  If you do this, you will need to send your "stop" command twice (once per loop).  But I have found this trick to not be practical due to what I need to do with the data (log it, update graphs, other things that really need to be done serially).

 

In the case of only logging the data, I have also put the dequeue in a loop with a timeout of 0 and stop when there is a timeout.  The dequeued data is then autoindexed out of this inner loop.  This creates an array of data that I can then log in bulk.  It makes things a little more efficient since the disk isn't accessed as much.


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 11
(7,910 Views)

If you are producing data faster than you can consume it, you do, indeed, stand the chance of losing data (which you never want to do!).  What Crossrulz (and I) would advocate would be to make the Consumer "more efficient".  In general, you have to produce data one element at a time.  But there's nothing to say that you can't accumulate it in much bigger chunks, and gain the "economy of size".

 

Here's an example of Efficiency in Consumers.  I'm assuming the Producer makes a million Dbls that need to be consumed.  I wrote (just now) a little test program that opens a file, and using a For Loop, writes a (fixed) Dbl a million times to the file (then closes the file).  It takes 690 milliseconds to do this.  I now open another file, take the same Dbl, but make an array of 1000 of these, and write these 1000 times to my file.  This takes 17 milliseconds, more than 40 times faster!

 

So how do you arrange to have your Producer, running a 1MHz, get its data saved and processed?  Well, if one queue is good, two queues are (sometimes) better.  As the data arrive in your Producer, don't waste time, put them in a Queue (of length, say, 5000, for safely).  Have an "intermediate Consumer/Producer" that dequeues the data and starts packing it into a 1000-element array (filling an array is very fast).  As each array is filled, it is put into a second queue (maybe of size 50, just to be safe) and sent to the final Consumer, who writes the 1000-point array to disk in 17 microseconds.

 

[You may have noticed that I specified the length of the Queues.  When you are using Queues "for speed", you want to define their size when you create them to prevent LabVIEW from allowing them to grow, which takes time for the memory management].

 

Hope you find all of this interesting and potentially "fun" -- LabVIEW has a lot of tricks up its sleeve.

 

Bob Schor

Message 8 of 11
(7,882 Views)

Here's a very quick (and really incomplete) example of what I meant by dequeueing a bunch of samples to batch process.  I used a FOR loop to limit the number of items I batch process at a time (not always needed).  Just stop the loop when the timeout (which is 0) occurs.  I recently had to do this with a CAN communication scheme.  It made things A LOT faster.


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
Message 9 of 11
(7,873 Views)

Bob - If you don't mind, weould you mind sharing that?

0 Kudos
Message 10 of 11
(7,362 Views)