LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

The best structure for a complex program

Hi.
I use LabView 8.6 SDK in WIndowsXP.

I try to plan the best structure for my program. I describe the program briefly, maybe you can give some hints basing on your experience.

Program should investigate the quality of the signal. It is rather big, so it has been divided into several parallel VI's.


Firstly, I collect an amount of samples with my pci board.
Basing on the samples I do some control over the board and change the board clock rate. New clock rate will be applied to collect data in next iteration.
The obtained measurements are enqueued in a queue of constant size (several hundred elements). Each element of the queue, apart of the data contains also a time at which the measurement was taken and the number of each element. All three are in a cluster.
 Afterwards, the notifier with the queue refnum is sent to some parallel VI's that should investigate the data.

There will be about 5-6 parallel VI,s. Each of them, triggered by notification, should take some constant number of the newest elements from the queue (using Get QUeue Status and choosing a number of last elements) and doing some calculations (like FFT, rms,...).
If the calculations show that the data deviates from the standards, that should be indicated and stored in a file (I have chosen tdms) together with time associated with given element.
At the moment parallel VI's take a constant number of the last elements from queue, but I have noticed that if Windows decides to do something else at the moment I lose some data.

There is also a parallel VI that checks the system time and sends a notification ( Boolean ) to all the others each 10 minutes. When a parallel VI gets this notification, it should start new cycle of calculations immediately but proceed with the old calculations so there is always a constant number of queue elements investigated in each cycle. I am still not sure how to implement that.

I hope that this is more less clear. My question is if you see some obvious improvements to the structure so I do not loose any data or so it works better, faster, more reliable...

Some parts of the program are already implemented.

Thanks for any hints.

Andrzej

0 Kudos
Message 1 of 15
(4,560 Views)

I see what you want to do and it is not hard to do in LV.

 

The basic idea is to utilize a producer-consumer with events type design pattern (there is a template for the basic structure available through the New... dialog box). But there are a number of changes you need to make to the basic structure:

  1. You want to use a named queue to pass the data. This change allows the producer and consumer loops to be in separate VIs.
  2. You want to save your consumer loop VI as a template. This allows you to launch multiple independent copies of the code at run time using VI server.

This structure will work because when you have multiple processes attempting to dequeue data from the same queue, LV guarantees that only one process will see each item that gets enqueued. For example, say your acquisition code is in the producer loop and you have 5-6 consumer loops all monitoring the same queue. When the producer loop enqueues the first item, consumer loop 1 will see the data, but all the other loops will remain quiescent. Likewise consumer loop 2 will see the second item enqueued, loop 3 the third item enqueued - and so on. After the last consumer loop gets its item from the queue, the next item enqueued will again go to the first loop that is available and the cycle will continue.

 

With this structure you can to some extent add more data processing bandwidth by simply launching more copies of the consumer loop template when the application starts up.

 

Mike...


Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
Message 2 of 15
(4,551 Views)

Thank you Mike for your response!

 

The producer - consumer scheme seems to be very good solution in my case, but I have few more questions to that:

 

Do I loose data if one of the consumers has more computations to perform then others and dequeues elements slower then they are enqueued. Does the queue grow and all other consumers wait for the slower one? THe simple example that I have made using the producer - consumer template shows that data can be lost, can I do something about that?

 

Let's assume that I have implemented the producer - consumer scheme. In my program I also need a subVi which notifies all the consumers in each 10 minutes. The consumers have to start performing some additional computations precisely after the notification, without any delay. What structure do you recommend? Can I use notifiers in the program or will it influence the consumers? 

 

Thanks for any help!

Andrzej

0 Kudos
Message 3 of 15
(4,447 Views)

handre wrote:

Thank you Mike for your response!

 

The producer - consumer scheme seems to be very good solution in my case, but I have few more questions to that:

 

Do I loose data if one of the consumers has more computations to perform then others and dequeues elements slower then they are enqueued. Does the queue grow and all other consumers wait for the slower one? THe simple example that I have made using the producer - consumer template shows that data can be lost, can I do something about that?

 Whether or not you have multiple consumer loops running, you should never loose data because the producer consumer design pattren uses a queue to pass the data. Also unless there are other dependencies, no consumer loop should be waiting for any other one to finish. Of course if the processing VIs inside the consumer loops are not reentrant there could be waits involved there.

Let's assume that I have implemented the producer - consumer scheme. In my program I also need a subVi which notifies all the consumers in each 10 minutes. The consumers have to start performing some additional computations precisely after the notification, without any delay. What structure do you recommend? Can I use notifiers in the program or will it influence the consumers? 

You can use notifiers or user events to trigger a simultaneous action in all consumer loops. The advantage of a notifier is that it can be named so you don't have to explicitly pass a reference to the comsumer loops. The advantage of the user event is that events are queued so you are guaranteed to see all event. Notifiers are not so they can be overwritten. To pass an event reference you can create a functional global to store it.

 

Thanks for any help!

Andrzej


 


Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
Message 4 of 15
(4,406 Views)

Thank you Mike for another helpful answer!

 

I have used the producer consumer structure in the program and found another interesting problem.

 

My main vi reads a waveform and enqueues twice each cycle of it in the queue. There are two VI's that read the queue. One of them is responsible for taking ten cycles and enqueueing them as a one element in another queue. 

 

Everything works fine until I started to do something in Windows (it can be moving windows around, resizing them, opening or closing them (for example internet browser) ... ). I checked the queue while doing that and the number of elements in the queue increased (which is what I wanted to obtain using queues) but in 10 cycles queue some of the cycles are doubled! Does that mean that consumers are taking the first available element even if they already enqueued that element? 

 

Does anyone know how to solve that problem? 

 

I attach the 10cycles vi, maybe I do something wrong.

 

Thanks

 

0 Kudos
Message 5 of 15
(4,307 Views)
You need to use two separate queues, one for each VI that needs to read from the queue.  Duplicating elements in the same queue is not reliable, because there's no way to guarantee which reader VI will dequeue the elements.  In your case your 10cycles VI is getting the queue elements first (maybe it's set to run at higher priority, or it could be random) and dequeueing both copies of the data before your other VI has a chance to see them.
0 Kudos
Message 6 of 15
(4,281 Views)

Thanks nathand!

 

I guess I will have to add more queues...

 

I must have misunderstood mikeporter's first post in this thread. I thought that LV will handle the problem of dequeueing elements for multiple consumers by itself and no data will be lost for any of the consumers. And from what I saw it works until there is more elements in the queue. Then, the consumers just start to dequeue elements as fast as possible loosing the correct order. Is that right?

 

andrzej

 

0 Kudos
Message 7 of 15
(4,247 Views)

No you didn't misunderstand me. You got the point correctly. LV will guarantee that parallel dequeue operations will not receive the same data. Now if you are trying to make assumptions about the order that things will be dequeued by a given dequeue operation, that is a problem. Each loop will simply get the next queue item available. If you are needing to do things in a particular order, perhaps you need to rethink your data structure.

 

Mike...


Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
Message 8 of 15
(4,209 Views)

I have made a small experiment to check how it works.

 

I have one queue and two consumers, each looking at the queue. I enqueue 6000 numbered elements. Each element is enqueued twice, so there is: 1-1-2-2-3-3...6000-6000. After the end I expect to have elements from 1 to 6000 dequeued in each of the consumers. Right?

 

It is so if there are no other processes working at the same time on my computer. Then, the element is dequeued directly after it is enqueued and the number of elements in the queue does not grow. However, if I load my processor (for example by opening web browser) while doing the experiment, the result is different: there is no longer nice sequence in each of the consumers. Some numbers are doubled and some are missing. 

 

So here, I do not care about the order in which the elements are dequeued, I just need to have all elements dequeued in each of the consumers. And it is not happening if the number of elements in the queue rises above zero.  At least this is what I have observed from my 'experiment'.

 

andrzej

0 Kudos
Message 9 of 15
(4,178 Views)

We need to see this test code. How many elements have you setup the queue to hold?? It sounds like 1.

 

0 Kudos
Message 10 of 15
(4,159 Views)