09-13-2010 06:39 PM
Trying not to reinvent the wheel...
I have started redesigning an old data acquisition/processing application using as much parallelism as possible.
UI/DAQ/Data Saving/Data Processing/Data Display are all handled in separate loops or VIs which communicate and exchange data via queues or notifiers. This works fine so far.
Then I realized that the way I provided the data processed by Data Processing (DP) to Display (D) tasks was not going to work in all circumstances.
I use a notifier, so that several D tasks can access the data and such that there is not much memory cost (no queue) if the D tasks can't keep up. If data is generated faster than the D tasks can get it, then they miss some but get a chance to catch up later or at least get some data every now and then. That was what I had in mind originally.
Then I realized that I may want to display all processed data (for instance offline). This architecture won't work. If I were to keep the data notifier approach, I would need a way to tell the DP task to send data to the notifier only when all D tasks are done with their previous chunk of data.
What is the best way to achieve that? I need to be able to change the number of clients (D tasks) dynamically, so I thought RendezVous might work. But then looking at the example "Wait for All Notifications Demo.vi", it seemed that this might be a more natural approach but a bit tedious to handle since the notifiers would be created (and destroyed() dynamically in separate VIs...
The point is that I want DP to know how many clients it is supposed to wait for (at all time) before sending a new notification (with new data).
Thanks for your feedback.
X.
Solved! Go to Solution.
09-14-2010 07:36 PM
Notifiers may in fact have the desired functionality I am looking for, but I am not so sure. I am getting lost trying to understand the innards of the VI referred to above ("Wait for All Notifications Demo.vi").
Get Notifier Status Function has a "# waiting" output: from my experiments, it is not the number of subscribers, but the number of subscribers actually waiting for a new notification. Somehow, if I knew the number of subscribers, I could wait until the "# waiting" output of Get Notifier Status is equal to the number of subscribers and use this as a criterion to move on and output new data. However, this requires polling, which is not very efficient (but I can live with this if there is no better idea out there).
Any hint?
09-15-2010 11:23 AM
Let me make sure I understand your problem. You have one data source, DP, and many data consumers, D. DP puts out data at a rate that might be too fast for some D to process. That's okay as long as they get the most recent data point when they are ready for it. However, there are some consumers (I'll call them D*) that you do want to display all the data. Finally, DP has to be able to accomodate any number of D and D*.
Here's what I would do:
Keep the notifier and have all D connect to it. That part is fine. For D* consumers, there are two options: queues and events. Queues, I think, require less overhead than events and are the preferred option, but the implementation will be a little different.
If using queues, each D* will need to create their own queue to receive the data and pass it into DP. DP will maintain an internal array of all the queues it has and when it creates a new data point it will post that data to the notifier and to each queue in the array.
If you want to use events, create a single user event in DP. Each D* will obtain a reference to and register for the user event. When DP creates a new data point it will post the data to the notifier and generate a single user event with the data. All D* will receive their own copy of the data.
09-15-2010 11:35 AM
[I intended to add this to my previous post but the edit time expired.]
"The point is that I want DP to know how many clients it is supposed to wait for (at all time) before sending a new notification (with new data)."
I don't understand this requirement. Why tie the producer's ability to process data to the consumer's ability to handle the data? The producer shouldn't care if the consumers are ready. The producer shouldn't even care if there are any consumers at all. It just collects and posts data leaving it up to the consumers to handle it appropriately.
09-15-2010 11:51 AM
Hi Daklu,
My original idea was to deal with either a case where all clients are D's or with a case where all are D*'s, but upon reading your answer, I am thinking of including that third case where both types can exist... But that would be for a "live mode" situation, not an offline one, which is the one I was discussing (in other words, a situation where all clients are D*'s).
As far as I can see, the solutions you offer don't solve the problem I foresee in the offline mode (where I "replay" saved data). If data processing is much faster than data display (and again, "display" is a simplification, there will be some post-processing involved), then both solutions will create massive queues (or queues of events?) and that's precisely what I want to avoid. I'd like to have DP know when all its clients are ready for more and only then "output" data (or process some more if need be).
I can think of "classic" ways of letting the clients register with DP, send messages when they are done or when they quit, etc, but I can't really find a way of avoiding to have DP be stuck in a polling loop waiting for these communications to be over before going for a new round of data. Maybe the overhead of having a polling loop is not that much of deal in offline mode, after all? I just wanted to make sure I am not missing a neat LabVIEW feature I don't know about before resorting to an old fashioned approach from my limited set of skills.
In particular, I think it would be nice to have the notifier be able to check how many registered clients have received the last notification (either as a "Get #Clients Having Received Last Notification" function - which would however require polling to make sure all clients have received it, so not really what I am looking for-, or better, as a "Wait for All Registered Clients to Receive Last Notification" function (with timeout)).
Thanks for reading.
X.
09-15-2010 11:56 AM
Did get your edit before I posted the response. But I think you'll find the reason why I want the producer to be able to limit its output if the clients are not keeping up. It might not be a "standard" producer-consumer design, but it follows the rule according to which "demands regulates production". Let a producer produce like crazy and ignore whether there is demand for its product and it will crash the market (but I digress 🙂
09-15-2010 04:10 PM - edited 09-15-2010 04:11 PM
Read "Didn't get your post" above...
Great "Edit your post within 5 minutes or you will the laughing stock of the community" feature we have on this forum 🙂
09-15-2010 04:28 PM
Anyhow, since LV 9 SP1 crashed and threw away all my work of today (what about AutoSave every 5 min? Is that not working on the 15th of each month or something?), I'll take a break and describe the solution I have come up with:
- I created a parallel process in the DP VI, which I call "Consumer Response Monitor" (CRM). This process polls a queue (waiting for messages to arrive using Dequeue, so no wasted resources) which is populated by both DP and D's.
- DP warns CRM that new data has been sent (and therefore to refocus its attention to the new data's fate.
- D's first register with CRM (and unregister when they quit) and then tell CRM when they have received data (which and who they are).
- CRM monitors the number of registered D's having received the new data and tells DP when all have (or there is a timeout). It does that using another queue.
- if I am in "live mode" and don't care whether the D's have time to process all data, I just ignore the traffic with CRM.