Jump to content

Q's - Whats all the fuss about


Recommended Posts

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

As lame as my weekends eh?

we may have converged on a spin-off topic. But you are still quite a way from convincing me that queues are "the magic bullet" and all applications should use this architecture.

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

Same thing would work better with a notifier. No polling, no latency.

Oooooh. No. Because then the UI would have to wait on the notifier(s). Also if you go down this path you end up with notifiers everywhere like a plague of mosquitos. A pain in proverbial to debug. All I have to do to debug is watch the global. There is no need for sequencing so a notifier is not useful.

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

:wacko:

I started this thread after a comment in another thread that suggested a fairly simple implementation would be better as a queue. I asked whats everyone fascination was with queues on this forum. As a newbie to this site, as I looked at more and more posts it seemed everyone was queue crazy and the remit was...lets start with a queue and make it all fit. So Rather than hijack the thread, I started a new one to find out why people thought (and I think even you said this too) queues are "the magic bullet" to application design.

All applications have some degree of asynchronicity that doesn't mean you should design around a queue. It sounds almost as if you are agreeing with me in repesct to queues adding complexity ;)

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

Amen, brother. Dataflow is your friend. Easy to read, simple coding. But when you have parallel processes, dataflow doesn't apply. If they need to share data, you can use globals, which have lots of problems, or queues, which don't.

The only problem with globals arises when you require synchronisation. But that isn't really a problem, it is (a very useful) feature of globals. The fact that it creates copies of data is a drawback (if you were running on a ZX spectrum...lol). But a queue isn't a replacement for globals as you point out in your example (removed the stop button from the user). And even in the first example it was used.

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

I did say that distibuted IO (which is I think what you are describing) is one scenario that would warrant a queue. However, yours is a large app as I seem to remember (how much of that is event management and interprocess comms?) and certainly realising the BT client wasn't a large app because Delphi is event driven therefore very suited to the task. Horses for courses.

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

I generally run these handlers with infinite timeout, so there is no timeout case (and no wait function). LabVIEW's internal execution scheduler may have to poll the queue somewhere deep in the bowels of
LV
, but that's not exposed to me. We have dozens of queues waiting in parallel with very low overhead and very low latency when an event is fired, so I suspect it's not polling at all, but is really sleeping. I don't know what you mean about a difference between queues and notifiers. As far as waiting and timing out, they act exactly the same.

Queues do not have a wait function. Yes you can get similar behaviour IF you only ever have 1 message on the queue at asny one time, but if your producer(s) is faster than your consumer this is rarely the case. Therefore having an indefinite timeout makes no difference as your sub process still needs to inspoect the message to see if it was meant for it. So it is not sleeping, it is inspecting. You would then need a case for if the message wasn't for it and you can't just let it run through a tight loop so a wait so many milliseconds would be needed. So it's not sleeping evertime there is a message on the queue regardless of who it is for.

QUOTE (jdunham @ Apr 26 2009, 06:29 PM)

Ummm. It doesn't do what it says on the tin.

It uses no globals, because you have removed the "Stop" from the user in SubVI1. The original example uses a global also.

In the example I posted (ver 2), I set the aquisition time to 0ms and could acheive 3 ms of aquisition (mainly due to the 1ms delay I have in my notifier VI). All of the VI's show 3ms and all the vi's show the same loop iteration thus proving they are all capturing the aquisition "Event" with no loss.(well. The aquisition VI might show one more since it gets an extra go after you press stop on the aquisition vi).

In yours, however. If I set it to 0ms the aquisition vi runs like the clappers (6229 for the length that I ran it) but the others show significantly less (2654). What is happening to the other 2654 samples of data?

Link to comment

QUOTE (ShaunR @ Apr 27 2009, 12:20 AM)

Queues do not have a wait function. Yes you can get similar behaviour IF you only ever have 1 message on the queue at asny one time, but if your producer(s) is faster than your consumer this is rarely the case. Therefore having an indefinite timeout makes no difference as your sub process still needs to inspoect the message to see if it was meant for it. So it is not sleeping, it is inspecting. You would then need a case for if the message wasn't for it and you can't just let it run through a tight loop so a wait so many milliseconds would be needed. So it's not sleeping evertime there is a message on the queue regardless of who it is for.

Why would you use a queue if the producer is faster than the consumer? That's what notifiers are for. Why do you need wait functions if there is data available? Why is the receiver inspecting the data? Why would you let a queue consumer get data that wasn't meant for it? That's what I call a bug.

One way I like to think about it is that a queue is a 'dataflow wormhole' between parallel loops. Since you like dataflow as much as I do, maybe that makes it clearer why a queue is so useful.

QUOTE (ShaunR)

The only problem with globals arises when you require synchronisation. But that isn't really a problem, it is (a very useful) feature of globals.

Well, do a Google search on "Global variables are bad". I got 400,000 hits. They are considered dangerous in every language. I have been using more unnamed queues and notifiers lately so that they are not available globally.

About my version of the sample application, I tried to add some asynchronous behavior to show the power of the queues. Did you read all the diagram comments? I though that would have answered your questions. It would be easy to modify it to match the original more closely. I took all the globals out because I think they are a defect, not a feature.

Link to comment

QUOTE (jdunham @ Apr 27 2009, 10:41 AM)

Well, sometimes it's a good idea to queue up operations where each and every operation should be processed. Just not necessarily in a UI.

QUOTE (jdunham @ Apr 27 2009, 10:41 AM)

One way I like to think about it is that a queue is a 'dataflow wormhole' between parallel loops. Since you like dataflow as much as I do, maybe that makes it clearer why a queue is so useful.

Well, do a Google search on "Global variables are bad". I got 400,000 hits. They are considered dangerous in every language. I have been using more unnamed queues and notifiers lately so that they are not available globally.

About my version of the sample application, I tried to add some asynchronous behavior to show the power of the queues. Did you read all the diagram comments? I though that would have answered your questions. It would be easy to modify it to match the original more closely. I took all the globals out because I think they are a defect, not a feature.

Unnamed queues are cool. Like secret post.....

Shane.

Link to comment

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

Quite the converse in fact. You would use a queue to "queue" ( or buffer) the messages/data/etc (because you can't process them fast enough) in the hope that they may ease up later so you can get through the backlog.

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

Why do you need wait functions if there is data available?

Because you may be busy doing something else that is time critical and higher priority.

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

So many why's. I've already explained that one.

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

Why would you let a queue consumer get data that wasn't meant for it? That's what I call a bug.

How can you not? Since there is data in the queue how does it know that its not for it? Thats what I call the nature of queues.

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

Don't get all Trekky on me now :P And I know why as queue is useful, in the same way I know that a car is useful unless you in a swamp.

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

Well, do a Google search on "Global variables are bad". I got 400,000 hits. They are considered dangerous in every language. I have been using more unnamed queues and notifiers lately so that they are not available globally.

Do a search on "kill Bush" and you get 12,700,000. Your point is?

This is what NI have to say on it:

http://zone.ni.com/devzone/cda/tut/p/id/5317

QUOTE (jdunham @ Apr 27 2009, 09:41 AM)

About my version of the sample application, I tried to add some asynchronous behavior to show the power of the queues. Did you read all the diagram comments? I though that would have answered your questions. It would be easy to modify it to match the original more closely. I took all the globals out because I think they are a defect, not a feature.

For asynchronous behaviour they are already in while loops. If data is lost, then I'm not really sure what you were trying to demonstrate with the example.

Link to comment

This is starting to become a heated debate. People have a tendency of finding a good tool and then try to use it as a cure-all. We have all done it. I think what ShaunR is trying to say is that a lot of people on this forum will instantly say to use a queue without much thought for any other tool. Yes, queues are one of the more powerful tools in LabVIEW. Are they for every situation? Absolutely not. They can easily complicate things, like any other powerful tool. But as far as passing data between loops, I'd say that, in most situations, queues are the best route to go for mostly two main reasons: 1. They do not lose data (every element written into the queue will be available for dequeue) and 2. if there is no data in the queue, there is no CPU usage for the dequeue loop (assuming infinate timeout). Polling globals uses valuable CPU time. I have to put code on computers that are 10+ years old, so I need all the CPU time I can get.

Link to comment

QUOTE (ShaunR @ Apr 27 2009, 07:25 AM)

Quite the converse in fact. You would use a queue to "queue" ( or buffer) the messages/data/etc (because you can't process them fast enough) in the hope that they may ease up later so you can get through the backlog.

Queues are cool that they can even the load if your data is bursty, but queue or no queue, if you're not processing fast enough, you have a problem that queues couldn't fix.

QUOTE (ShaunR)

How can you not [need to inspect the incomding data]? Since there is data in the queue how does it know that its not for it? Thats what I call the nature of queues.

I would never send data through a queue that wasn't meant for the queue listener. I would just use separate queues to send data to separate loops that were 100% devoted to handling that data.

OK, I give up trying to convince you. We obviously use queues in very different ways. I find them useful, even indispensable. My team's code doesn't suffer from any of those things you say queues suffer from, and we're doing things that you say are nearly impossible in LabVIEW, and they were pretty easy to code up and have great performance and scalability.

It's fine if you don't want to use more queues, but I don't think you'll manage to dissuade the rest of us.

Link to comment

QUOTE (jdunham @ Apr 27 2009, 08:09 AM)

Queues are cool that they can even the load if your data is bursty, but queue or no queue, if you're not processing fast enough, you have a problem that queues couldn't fix.

I would never send data through a queue that wasn't meant for the queue listener. I would just use separate queues to send data to separate loops that were 100% devoted to handling that data.

OK, I give up trying to convince you. We obviously use queues in very different ways. I find them useful, even indispensable. My team's code doesn't suffer from any of those things you say queues suffer from, and we're doing things that you say are nearly impossible in LabVIEW, and they were pretty easy to code up and have great performance and scalability.

It's fine if you don't want to use more queues, but I don't think you'll manage to dissuade the rest of us.

Maybe it's time to put this into a queue that has no dequeue or maybe a global variable that is never read..... :rolleyes:

Link to comment

QUOTE (ShaunR @ Apr 26 2009, 11:53 PM)

Even if there IS data in the queue but not for that "thread"?
Loop A reaches a Dequeue node. If there is data already in the queue, it gets the data out and continues running the rest of the diagram. If there is no data, it goes to sleep until data is supplied by another section of the diagram running an Enqueue node.

QUOTE

And (just a point to fill my knowledge gap) Are you saying that 2 while loops (or 50 even) will run in their own separate threads?

Generally, yes. Any parallel node in LV (meaning any two nodes where the outputs of one do not flow through wires to inputs of the other) will run in parallel. We only spawn N threads where N is "number of CPU cores x 4". This includes while loops. If the number of parallel nodes exceeds the number of threads, the threads will use cooperative multitasking, meaning that a thread occassionally stops work on one section of the diagram and starts work on another section to avoid starvation of any parallel branch. If you have two parallel nodes and you have two available CPU cores, each node will execute truly in parallel, one on each core.

This is the key reason why LV is such an incredibly powerful language in modern computers: from the raw syntax of the language, parallelism can be identified and acted upon without requiring explicit coding from the programmer (where as in other languages the programmer must manually create calls to Fork and Join and manage all of the communication between those).

QUOTE

There's a big difference between events and queues. (I think your comparison is to events as the rest of your post is about them although Aristos is talking about queues and notifiers I beleive). Events can happen in any order an at any time I think I heard someone say before
:P

Events are fired from the user clicking/typing or from one of four nodes: the user event firing node, the Value (signaling) property node, the FP.Close invoke node and the AppExit node. I believe this is a comprehensive list. So the events can be *generated* in any order. But that's no different from saying any two parallel branches can Enqueue into the same queue in any order.

When the events are *handled* they are always handled in the order they were generated. In the same way, data is always dequeued from the queue in the order it was enqueued.

QUOTE

API? Thats windows speak...lol. You weren't a C++ programmer in an earlier life were you?

API is pretty common term in any programming language when you have different modules or libraries. 21 years ago, when I started programming before Windows even existed, the term API was used for the C libraries, as in "I created a new .c file that runs faster than the UNIX version, but it has the same API."

Link to comment

QUOTE (Aristos Queue @ Apr 27 2009, 06:41 PM)

When the events are *handled* they are always handled in the order they were generated.

That's the way it should be, definitely. Here's a VI showing an example where they aren't always (which is almost definitely a bug). I'm guessing that this is an issue which has to do with how the event structure handles a timeout when it has user events registered.

I would personally rather avoid getting into the actual topic of the thread. Each of the methods mentioned in this thread have their uses and value. Queues are not all powerful, but they are generally better than globals and for applications with parallel code are often the best tool for transferring either messages or data from one part of the code to the other. The main reason for using a queue would usually be if you don't want to lose data.

Link to comment

For the speed freaks out there, here's a comparison between relative Queue and E vent "dequeueing" (for want of a better word).

I was a bit surprised to see that the Queue (with associated "Variant to data") is much faster than Events until the data gets quite large (where the "Variant to Data" probably becomes expensive).

Does an event structure require a thread switch even if there are ONLY user events being handled?

The following VI is saved in 8.2.1. It fills a Queue with N elements (A U32, a String and an XY point). It also creates N user Events with the same data. The Dequeuing requires a "Variant to data" to get the actual data out, the event structure dues not. The size of the string used can be set on the FP. Watch out for memory problems with high N and String size values....

Shane.

Link to comment

QUOTE (PaulG. @ Apr 27 2009, 05:44 PM)

You can always ignore us (like 90% of the lurkers :P ). Or you could read it during work time when your paid for it...lol.

QUOTE (jdunham @ Apr 27 2009, 04:09 PM)

Queues are cool that they can even the load if your data is bursty, but queue or no queue, if you're not processing fast enough, you have a problem that queues couldn't fix.

Unfortunately my data isn't "bursty". It is multiple continous streams with control on top. No problems either.

QUOTE (jdunham @ Apr 27 2009, 04:09 PM)

If I were to adopt the same strategy in the current project I would end up with 87 queues :o

QUOTE (jdunham @ Apr 27 2009, 04:09 PM)

OK, I give up trying to convince you. We obviously use queues in very different ways. I find them useful, even indispensable. My team's code doesn't suffer from any of those things you say queues suffer from, and we're doing things that you say are nearly impossible in LabVIEW, and they were pretty easy to code up and have great performance and scalability.

Ummm. Are you referring to spawning multiple (200+) threads like in the BT client? I don't think that is possible. Especially if you can only have cores x 4 threads.

QUOTE (jdunham @ Apr 27 2009, 04:09 PM)

It's fine if you don't want to use more queues, but I don't think you'll manage to dissuade the rest of us.

So I guess your in the Q or die camp :( (but suspected that quite a few posts ago)

Link to comment

Good discussion guys, I find it very interesting. I understand the argument for queues and I'm also trying to understand the argument for event structures as well. It seems to me that if you had n event sources, you have two (almost) functionally equivalent options

1) have n queues inside n while loops, or

2) have a single event structure with n cases

the benefit of queues is that

1) if they are named they can act as both global variables and detect events (you can also pass data through event structures so I don't know if this is really a difference), and

2) since they are in multiple loops, executing code from events is done in parallel

the benefit of event structures is that

1) your code is compacted down to a single structure and is smaller

2) you can write code which does one-off events without having to create a completely new queue just to handle that event-type or going through the hassle of using variants and typedefs

3) the event structure can register events generated by software (eg, front panel controls)

With this in mind, perhaps it would be nice to converge the functionality of both so that users can use one or the other depending on their coding styles/application. For example, register events from controls, or indeed any software events, into a queue so that an event structure is no longer necessary for things like GUI control (improving queues). Or, allow named events which are available globally like named queues (improving event structures -- coincidentally, this is exactly what ShaunR and shoneill are asking for).

Wouldn't this allow one to, theoretically, use queues and event structures interchangeably? Is there a fundamental reason why there shouldn't be more than a superficial difference between the two? AQ?

Link to comment

QUOTE (jasonh_ @ Apr 29 2009, 04:02 AM)

Good discussion guys, I find it very interesting. I understand the argument for queues and I'm also trying to understand the argument for event structures as well. It seems to me that if you had n event sources, you have two (almost) functionally equivalent options

1) have n queues inside n while loops, or

2) have a single event structure with n cases

the benefit of queues is that

1) if they are named they can act as both global variables and detect events (you can also pass data through event structures so I don't know if this is really a difference), and

2) since they are in multiple loops, executing code from events is done in parallel

the benefit of event structures is that

1) your code is compacted down to a single structure and is smaller

2) you can write code which does one-off events without having to create a completely new queue just to handle that event-type or going through the hassle of using variants and typedefs

3) the event structure can register events generated by software (eg, front panel controls)

Queues have other advantages like being able to preview the entire contents of the queue or to insert at the opposite end. With Events this is not possible.

Events on the other hand also have other advantages. Events can be 1 to n multicast capable (more than 1 register for events on the receiver side) and the fact that we can essentially use user events as a triggering mechanism for a state machine - Event-driven producer/consumer state architecture..... Events (when passed pre-registered) can be used as one-way communication channels. There is a workaround to get at the actual event using the Event refnum when the event in question actually fires (I have made a suggestion that this refnum NOT be exposed because I can't think of a use case for it and removing it would enable real "listener" events.).

QUOTE (jasonh_ @ Apr 29 2009, 04:02 AM)

With this in mind, perhaps it would be nice to converge the functionality of both so that users can use one or the other depending on their coding styles/application. For example, register events from controls, or indeed any software events, into a queue so that an event structure is no longer necessary for things like GUI control (improving queues). Or, allow named events which are available globally like named queues (improving event structures -- coincidentally, this is exactly what ShaunR and shoneill are asking for).

Wouldn't this allow one to, theoretically, use queues and event structures interchangeably? Is there a fundamental reason why there shouldn't be more than a superficial difference between the two? AQ?

I don't thnk Queues and Events are interchangeable just like that. They target different needs and that's good. There's no point having multiple tools for the same job, it just complicates things. There are many pieces of code where I use both queues AND user events, precisely because of their differing capabilities.

Having said that, I think there ARE possibilities to improve both, some of these you have already listed. In a mixed Queue/Event usage the ability to register an event for a queue receiving data (Or being destroyed and so on) would be SUCH a cool thing to have..... I know it can be done with a small while loop and an extra user event but I would love to be able to simply wire up a Queue to a "register for events" node and be done with it. Of course the same goes for Notifiers, Occurrences and so on.

Shane.

PS can anyone comment on the performance difference between event structures and queues I have mentioned earlier? Any reason why this should be so?

Link to comment

QUOTE (shoneill @ Apr 29 2009, 08:12 AM)

There is a workaround to get at the actual event using the Event refnum when the event in question actually fires

I think that's what I'm missing for me to use events effectively from within an encapsulated architecture.

Whats the workaround?

Link to comment

QUOTE (ShaunR @ Apr 29 2009, 02:06 PM)

I think that's what I'm missing for me to use events effectively from within an encapsulated architecture.

Whats the workaround?

If you have registered for an event and the event fires one of the parameters passed at the left-side of the event structure is the actual event refnum. In my mind this does not belong there but you could theoretically close this reference and kill all other processes "listening" to the event in other places.

Shane.

Link to comment

QUOTE (shoneill @ Apr 29 2009, 02:03 PM)

If you have registered for an event and the event fires one of the parameters passed at the left-side of the event structure is the actual event refnum. In my mind this does not belong there but you could theoretically close this reference and kill all other processes "listening" to the event in other places.

Shane.

Ah. Thats not it then. I'm looking for a way to link events from dynamically loaded vi's So that the vi can basically "hook" the existing event mechanism.

Link to comment

QUOTE (ShaunR)

Ummm. Are you referring to spawning multiple (200+) threads like in the BT client? I don't think that is possible. Especially if you can only have cores x 4 threads.

I don't know all the details of LabVIEW threading, but I learned a lot from these forum discussions:

http://forums.lavag.org/Parallel-execution-t10870.html

http://forums.lavag.org/Templates-t13200.html

QUOTE (ShaunR)

Indeed. From this thread I have gleaned that UI events (and indeed labview events in their entirety) aren't really have what I would consider "proper" events. My definition would be that defined by NI VISA as the callback event.

QUOTE (http://www.ni.com/support/visa/vevents.pdf)

It is important to note that because of the dataflow programming structure of

LabVIEW it is not possible to use the callback mechanism of event handling in

LabVIEW.

That's an interesting quote. I think just shows that the NI VISA team is not on the forefront of LabVIEW development (to be fair, I don't know how old that doc is). Their API could easily accept a VI reference and invoke VI.Run on it when the event happens. They could also accept an occurence or a queue refnum, but I think it would make more sense to do the VI reference. Then inside that VI you could invoke whichever queues or notifiers or occurrences (or polled globals) you need to interact with your running processes. LabVIEW with a callback (which you can also implement in your own code with a private notifier or a VI reference) is no less event-driven than C code with a callback.

Jason

Link to comment

QUOTE (jdunham @ Apr 30 2009, 02:45 AM)

I'll take a look later...thanks.

QUOTE (jdunham @ Apr 30 2009, 02:45 AM)

That's an interesting quote. I think just shows that the NI VISA team is not on the forefront of LabVIEW development (to be fair, I don't know how old that doc is). Their API could easily accept a VI reference and invoke VI.Run on it when the event happens. They could also accept an occurence or a queue refnum, but I think it would make more sense to do the VI reference. Then inside that VI you could invoke whichever queues or notifiers or occurrences (or polled globals) you need to interact with your running processes. LabVIEW with a callback (which you can also implement in your own code with a private notifier or a VI reference) is no less event-driven than C code with a callback.

Jason

You may be right. In fact, there ARE callbacks, in the true definition of callbacks (well in 8.6.x at anyrate). I've been playing with them for my event problem (well its not really a problem, it would just greatly simplify code and maintenance). But VISA doesn't expose the event refnum so you can't attach a callback. Or conversely, callbacks don't accept VISA resource sessions.There is/isn't/probably a way to get at it, but that aspect isn't on my priority list at the mo.

I would go one statment further. Labview is event driven (in the context of truly asynchronous events) with a callback, however C is not event driven....ever.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.