01-26-2009 04:43 PM
Solved! Go to Solution.
01-26-2009 05:05 PM - edited 01-26-2009 05:14 PM
Two independent while loops on a block diagram will automatically be run in separate threads by LabVIEW.
Using the "Producer/Consumer" architecture will suit your application.
http://zone.ni.com/devzone/cda/tut/p/id/3023
Send the data you want to process to a couple of consumer loops. That way it will run independently and not interfere with your data acquisition (producer loop).
Use a separate consumer for the two different data processing tasks.
The 'long computation consumer loop' will be a bit trickier than the short. You need some way to indicate to the producer that the long computation consumer is ready for more data.
There are many ways to do that. You could use another queue, notifiers, semaphores, the existing queue length, etc. Whatever you are comfortable with.
01-27-2009 04:52 AM
Troy K wrote:[snip]
You need some way to indicate to the producer that the long computation consumer is ready for more data.
[snip]
One of the open G toolkits includes the "Open G Message Queue", which will queue items as one would expect from a queue, but adds the functionality of a notifier. This simulates a function call and a return data, but there are a couple of other examples of how it can be used. However this form of processing in a produce/consumer would not be constructive in your case. When using a producer - consumer queue, you can add data and not worry about when it will be processed. If you know that one set of data will take a long time, and one will take a short time, then use 2 seperate queues for each data set.
01-27-2009 09:09 AM
If I use a conventional queue wouldn't there be lag between real-life adjustments of the instrument and the calculation display, as the consumer loops would process old data (especially the long-computation)? Is there a way to avoid this while still using a queue?
Instead of using a queue, could I use a global data variable that the "producer" writes to and that other two copy when they begin the computation? I suppose it's similar to a queue of length 1, except the producer can overwrite with the latest data.
If I go that route-- A semaphore of size 1 acts the same as a mutex, correct?
Also, say I have one front panel item in each loop - they update independently, correct?
And finally-- in the attached VI, the main VI keeps executing while the subVI is open, correct? I would like to avoid that if possible-- any ideas?
01-27-2009 10:12 AM
There are times when using a variable is warranted (for example writing to a control), but for something this simple it really isn't necessary, for the reason that it will break data flow. How long does your slow loop take?
Also, say I have one front panel item in each loop - they update independently, correct?
Yes, as each loop will be running its own thread, each loop is independant. It is for this reason that we use the synchronisation methods - to share common data between independant processes.
And finally-- in the attached VI, the main VI keeps executing while the subVI is open, correct? I would like to avoid that if possible-- any ideas?
The most preached method would be to use a statemachine. Put the data capture in one state and the sub VI in another state. The consumer loops would not run because they aer waiting for data from the producer 🙂
01-27-2009 10:53 AM - edited 01-27-2009 10:55 AM
yenknip wrote:
There are times when using a variable is warranted (for example writing to a control), but for something this simple it really isn't necessary, for the reason that it will break data flow. How long does your slow loop take?
Well, I have yet to write either loop. In addition, the execution length of both the slow loop and long loop will depend on how big of a Region of Interest the user selects. However based on similar VI's I have made I would put avg. run times at 100msec for the slow loop and perhaps 500msec for the long loop.
The reason I'm so concerned about latency, and why I can't just have both update at .5Hz, is because these programs are be used to optimize sensitive dimensions. It's very difficult to do if there is latency or if the update is slow.
yenknip wrote:
Also, say I have one front panel item in each loop - they update independently, correct?
Yes, as each loop will be running its own thread, each loop is independant. It is for this reason that we use the synchronisation methods - to share common data between independant processes.
I realize the data stored by the indicators update independently; I just wanted to make sure the indicators themselves would as well.
yenknip wrote:
And finally-- in the attached VI, the main VI keeps executing while the subVI is open, correct? I would like to avoid that if possible-- any ideas?
The most preached method would be to use a statemachine. Put the data capture in one state and the sub VI in another state. The consumer loops would not run because they aer waiting for data from the producer 🙂
There are times (fairly often, unfortunately) when the data stream fails and I need the VI to stop running-- in this case, I can't have teh consumer loops sitting around waiting for data that's never coming. Yet the subVI may be open for minutes at a time-- in this case, they really should sit around and wait. Is there a way to get the front panel button to trigger a wait state in both consumer loops and transition back only when the subvi closes?
And lastly, there are calibration routines that both consumer loops depend on for their calculations. These routines must be run when the user pushes a button on the UI. What is the best way to coordinate access to these? How would they fit into the state machine?
01-27-2009 07:17 PM
I can't have teh consumer loops sitting around waiting for data that's never coming.
Yes you can. They aren't consuming any significant resources when waiting for data.
Wire the error out terminal of the 'dequeue element' function to the stop terminal of the consumer loop. When you release the queue, the dequeue element functions will stop waiting and stop the while loops (by outputting an error).
If you detect a problem in your data acquisition, you can destroy the queues to stop the consumer loops.
01-27-2009 07:48 PM - edited 01-27-2009 07:49 PM
... calibration routines that both consumer loops depend on for their calculations. These routines must be run when the user pushes a button on the UI. What is the best way to coordinate access to these?
Use multiple producer, one for adding data to the consumers, one for inserting calibration information.
You'll need to make the data type for the queue a cluster. Use one of the elements to define function type, the other to add data or cal info.
Example attached...
01-27-2009 09:33 PM
Ooh, very slick on both solutions. Thanks, Troy!
I roughed out one of my other similar VI's using queues and the strategies you all suggested - it runs significantly better! R.I.P. Giant While Loop of Doom, haha.
Thanks all!