From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.
We appreciate your patience as we improve our online experience.
10-04-2019 10:55 AM
@Mark_Yedinak wrote:
...avoid processing the queue one element at a time. We create a simple state machine that is time based and when the timer expires, we flush the queue (flushing the queues returns an array of the queued elements) and process all of the elements at one time. ...
Not to pick a fight but you got me thinking...
I have done that as well but rather than flushing, I have checked the number of elements waiting in the queue and if greater than zero, invoke a For loop to iterate through each of the elements in the queue ONE at a TIME.
That approach is based on the theory (only AQ really knows) that when an element is queued-up the pointer ( I know! probably a handle or what-not) to the buffer holding the new element is what gets transferred to the Dequeue such that Queues can operate "in-place" with only the pointer moving and not the data.
If on the other hand we flush the queue, it seems that all of elements in the queue have to be moved to the buffer that the Flush queue returns.
Just talking alternatives since "alternatives" is the name of this thread.
Ben
10-04-2019 11:29 AM
@Ben wrote:
@Mark_Yedinak wrote:
...avoid processing the queue one element at a time. We create a simple state machine that is time based and when the timer expires, we flush the queue (flushing the queues returns an array of the queued elements) and process all of the elements at one time. ...
Not to pick a fight but you got me thinking...
I have done that as well but rather than flushing, I have checked the number of elements waiting in the queue and if greater than zero, invoke a For loop to iterate through each of the elements in the queue ONE at a TIME.
That approach is based on the theory (only AQ really knows) that when an element is queued-up the pointer ( I know! probably a handle or what-not) to the buffer holding the new element is what gets transferred to the Dequeue such that Queues can operate "in-place" with only the pointer moving and not the data.
If on the other hand we flush the queue, it seems that all of elements in the queue have to be moved to the buffer that the Flush queue returns.
Just talking alternatives since "alternatives" is the name of this thread.
Ben
You raise a valid point Ben. In the cases that I have done this the data size was actually not that large so I hadn't really consider the issue of the data copy. We had found with our experiments that the flush was faster than using a FOR loop. This may not hold true though if the data size is quite large.
10-04-2019 11:37 AM
@Mark_Yedinak wrote:
...You raise a valid point Ben. In the cases that I have done this the data size was actually not that large so I hadn't really consider the issue of the data copy. We had found with our experiments that the flush was faster than using a FOR loop. This may not hold true though if the data size is quite large.
I had the same thought after I posted!
So "it depends".
Thank you for being a sounding board!
Ben
10-04-2019 01:13 PM
@Ben wrote:
@Mark_Yedinak wrote:
...avoid processing the queue one element at a time. We create a simple state machine that is time based and when the timer expires, we flush the queue (flushing the queues returns an array of the queued elements) and process all of the elements at one time. ...
Not to pick a fight but you got me thinking...
I have done that as well but rather than flushing, I have checked the number of elements waiting in the queue and if greater than zero, invoke a For loop to iterate through each of the elements in the queue ONE at a TIME.
I the past, I have skipped the waiting and just used a FOR loop with a Dequeue in it. So I can get a maximum of, for example 10 elements, but on a timeout (100ms sticks in my mind), just process what I have. This was after LabVIEW 8.6, which introduced the conditional terminal to the FOR. It was actually quite simple and I could always adjust the timeout if I needed a faster reaction.
10-04-2019 01:43 PM
Why would there have to be a full (deep) copy of the queue elements in the case of a flush? Sure if your queue element is all consisting of a cluster of simple scalar then yes there might be a copy involved as the Flush Queue node returns an array of queue elements, but if that is the case you are making yourself busy over a very little effect here. Clusters will hardly contain thousends of scalar elements. That would be a true software maintenance nightmare! And for a few dozen scalars you would need a queue with million of elements in there to impose a significant overhead for copying them into the flushed output array and even then you do this Flush hopefully not every few seconds or you have very different problems to tackle first.
More likely your queue element will consist of a cluster with a few elements in there that might be scalar and others that might be substantial arrays or strings. No need for the Flush function to copy those embedded arrays too as it will have to delete the original right after anyhow. So it rather does at worst a shallow copy of the top level memory layout for the queue element into the flushed array and then the ownership of those (potentially huge) arrays and strings will be simply passed to whoever processes the flushed array. Nothing fundamentally different to retrieving each queue element individually. In fact it might be usually faster since each Deque call has to verify the queue refnum again and dereference the actual queue that this refnum refers too. That costs some time too and that overhead is likely just as big as the shallow copy of the top level memory layout for a queue element unless your queue datatype is truely huge and totally flat (cotaining only scalars).
10-04-2019 02:27 PM
@rolfk wrote:
Why would there have to be a full (deep) copy of the queue elements in the case of a flush? Sure if your queue element is all consisting of a cluster of simple scalar then yes there might be a copy involved as the Flush Queue node returns an array of queue elements, ...
If I am queue-ing up a 2d-Array of scalars, the flush queue would return an array of clusters of 2d arrays.
Wouldn't there be a data copy involved in that case?
While it has been a few years and I don't have that hardware ...
I was acquiring from a HSDIO PXIe board to sample from a digital microphone. I had to get it out of the hardware buffer as quickly as possible to keep the acquisition from over-flowing.
That data got passed via a queue to an initial processing loop (the code looked like it was FPGA code) that separated the left and right channels of a microphone based on a rising or falling clock.
Those two binary bit streams were then passed to two more queues that did the PDM conversion down into the audio range.
The PXIe application was able to keep up as long as the HSDIO sampling rate was 400Mhz. At 800 Mhz... my queues were backing up because I simply could not process the binary stream fast enough.
I dearly wanted to post that code as a challenge to se if people could double my performance, but sadly "it was against the rules".
Ben
10-04-2019 02:31 PM - edited 10-04-2019 02:32 PM
Well the queue element would be a cluster with an array handle to a 2D array. That would copy exactly 4 (8 on 64 bit LabVIEW) bytes per queue element, namely the handle pointer. The array itself is stored in its own memory block and referenced by the handle and whoever receives that handle is the owner of it.
10-04-2019 03:07 PM
@Ben wrote:
@Mark_Yedinak wrote:
...You raise a valid point Ben. In the cases that I have done this the data size was actually not that large so I hadn't really consider the issue of the data copy. We had found with our experiments that the flush was faster than using a FOR loop. This may not hold true though if the data size is quite large.I had the same thought after I posted!
So "Depends".wasn't that Dole's answer to "Boxers or Briefs?"
Thank you for being a sounding board!
Ben
You ALWAYS have an alternative to Queues..They won't often be faster! In fact, I bet the other methods will not be faster..