LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Darren's Weekly Nugget 07/20/2009

It sounds like DFGray is saying that you can use Reshape Array to preallocate memory rather than letting the Build Array function do it for you.  This is especially true if you know the final size of your array:  just use Reshape Array once to set the dimension sizes and insert the elements into your array using the Replace Array Subset function.  If you don't know the size of your array then this technique can still work.

 

Dynamically-sized arrays in text-based languages (like a Vector in C++) work by preallocating a certain amount of memory when the array is first created.  If the array gets filled, then a new area of memory that is larger by some amount (say 10 elements) is allocated and the array must be copied into this new area (and the old area must be deallocated).  You get 10 more elements to add before this has to happen again.  If you can preallocate your array using something like the Reshape Array function, then you can make sure this doesn't happen as often by preallocating enough memory for your array at the start or at least allocating more memory than the built-in function will if you don't know your array size.

Message 11 of 24
(6,457 Views)
Ben, my apologies.  I should have included some examples.  See the attachments below (LabVIEW 8.2).  There is an order of magnitude performance difference between the simple case and the preallocated or periodically allocated cases.
Message 12 of 24
(6,448 Views)

Thanks Dr. D.

 

If you're optimizing for diagram space and need good performance, there's always the OpenG solution:

 

PreallocateArrayOpenGConditionalAutoIndex


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
Message 13 of 24
(6,411 Views)

 


@Darren wrote:

Gleichman wrote:
Interesting tip, but it will only work as shown starting with an empty array. If you started with a non-empty array, you would have to reverse it first.

Right...nevertheless, the initial reversal and the reversal at the end should still have a negligible effect on overall execution time and memory usage.


I'm not sure you would get the performance benefits in this case. Since a reversed array isn't actually reversed, appending to its "end" would still require allocation and shifting stuff around in memory. If anything, I would expect that appending to the BEGINNING of a reversed array would be more efficient (assuming LV had that optimization, but my guess is that this optimization doesn't actually exist).

 


___________________
Try to take over the world!
0 Kudos
Message 14 of 24
(5,705 Views)

 


@tst wrote:

 I'm not sure you would get the performance benefits in this case. Since a reversed array isn't actually reversed, appending to its "end" would still require allocation and shifting stuff around in memory. If anything, I would expect that appending to the BEGINNING of a reversed array would be more efficient (assuming LV had that optimization, but my guess is that this optimization doesn't actually exist).

 


 

This started out as a short two line post:

 

Someone earlier in this thread mentioned that there are rare cases where Reverse 1D Array will go ahead and make a copy. Well, this is often one of those rare cases. When you reverse the array and then immediately start editing it, LV's compiler will notice that and go ahead and make a full copy of the array at the Reverse call.

 

And then I started adding details. Read on for more details about LV, buffer allocations, and compiler optimizations:

 

I've told some of you for years that when you use "Show Buffer Allocations" and you see a black dot, that means something was allocated but it doesn't necessarily mean that a copy was made. This is an excellent example. Take a look at this VI in which I have turned on "Show Buffer Allocations":

 

ReverseArrayDemo.png

 

Notice that both of the Reverse 1D Array prims has a black dot on the output terminal, indicating a memory allocation. Now, if you load this VI and hover your mouse over the wires and look at the Context Help window, you'll see something interesting...

SubArrayCH.png

 

The value coming out of the constant is going to be modified in the For Loop. Since we don't want to modify the actual value displayed in the constant, LV needs to make a copy. LV could make the copy at the shift register, but LV generally moves copies upstream as far as they can go. The earliest point in this diagram is at the first Reverse function. That function decides to actually make a full copy of the array, reversing it as it goes. The Context Help reflects this by showing that the output type is a "1D Array of". But the second Reverse function doesn't need to make the copy, so it outputs what we call a subarray, and this is reflected in the Context Help as "1D (sub)array of". A subarray is a special data type that essentially is a temporary reference to another wire that says, "The same as that other wire but with the following modifications". Those modifications can include reversing, decimation, extracting a subpiece, etc -- any simple transformation on the existing data that can be recorded using a starting index and a stride length (positive or negative).

 

The "Show Buffer Allocations" shows a black dot on the second Reverse 1D Array primitive. Many people call these "copy dots", and here's one reason why I've always said that slang term is inappropriate: LV is not making a copy of the array at the second Reverse function. It is, however, allocating a new subarray -- a subarray takes 12 bytes (on a 32-bit system). The buffer allocation dot means space for something of that terminal's data type was allocated -- but you have to pay attention to what that output type actually is. (There are other reasons why the term "copy dot" is inaccurate, but I'm not going to go through all of those here -- they're documented in various places on ni.com).

 

So when you are "playing hide the dots" to try to optimize your VIs memory (those of you who work a lot on RT systems probably know this game), pay attention to the data type coming out of those dots. If the type is subarray (or substring, because we use the same trick for those), then you can ignore that black dot -- it doesn't mean a copy!

 

Now, you might be thinking, "Hey, that's cool, but LV could do the same thing for clusters. Why isn't there a subcluster for saving memory at an Unbundle node?" Because that breaks out a single element, LV doesn't need a special data type to optimize this case -- it just sets the address of the wire to be the address inside the upstream cluster (unless the element is being modified downstream, in which case a copy does get made... unless the item is being put right back into the same cluster using a Bundle node, in which case a copy is not made... unless... well, let's just say that the LV compiler does a deep analysis of how you're using the cluster data and does a great job of minimizing the number of copies of data). Similar deep anlysis is done when indexing a single value out of an array.

 

Currently, you'll never see a subVI output a subarray or a substring. As of LV 2010, passing through a subVI always makes a copy because we have to have a real array copied into the output FPTerminal in case it gets displayed on the panel. Work continues on the compiler to optimize cases like this.

Message 15 of 24
(5,664 Views)

@Aristos Queue wrote:

 

...

Currently, you'll never see a subVI output a subarray or a substring. As of LV 2010, passing through a subVI always makes a copy because we have to have a real array copied into the output FPTerminal in case it gets displayed on the panel. Work continues on the compiler to optimize cases like this.


It that a change from what Greg McKaskle wrote in the "Clear as Mud" thread where he taught us about placing the controls and indicators that are located on the icon connector should be on the root of the diagram?

 

Ben

 

PS: ditto the comments on the copy dots!

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 16 of 24
(5,651 Views)

 


@Ben wrote:
It that a change from what Greg McKaskle wrote in the "Clear as Mud" thread where he taught us about placing the controls and indicators that are located on the icon connector should be on the root of the diagram?

Nope. Everything that Greg wrote in that thread is still true. When I say "always makes a copy", I mean that the subarray is converted to a real array. Greg was talking about connecting to an FPTerminal when the wire type is already a real array.

 

Message 17 of 24
(5,645 Views)

 


 

Aristos Queue wrote:

I've told some of you for years that when you use "Show Buffer Allocations" and you see a black dot, that means something was allocated but it doesn't necessarily mean that a copy was made.


 

 

Have you seen this?  Could you explain why (A) runs ~20 times faster than (B)?  More importantly, how can we use "Show Buffer Allocations" to spot cases like this?

 

 

Buffer Allocation Outside Loop.png


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
0 Kudos
Message 18 of 24
(5,593 Views)

@LabBEAN wrote:

 


 

@Aristos Queue wrote:

I've told some of you for years that when you use "Show Buffer Allocations" and you see a black dot, that means something was allocated but it doesn't necessarily mean that a copy was made.


 

 

Have you seen this?  Could you explain why (A) runs ~20 times faster than (B)?  More importantly, how can we use "Show Buffer Allocations" to spot cases like this?

 

 

Buffer Allocation Outside Loop.png


In LV 8.6 I do not get that dot on the output of the Array Subset in version "B".

 

What version is that image from?

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 19 of 24
(5,586 Views)

 


 

Ben wrote:

In LV 8.6 I do not get that dot on the output of the Array Subset in version "B".

 

What version is that image from?


 

 

2009  [BTW, at some point (2009 SP1?) snippets started displaying the year at the top right of the image (see above).]

 


Certified LabVIEW Architect
TestScript: Free Python/LabVIEW Connector

One global to rule them all,
One double-click to find them,
One interface to bring them all
and in the panel bind them.
0 Kudos
Message 20 of 24
(5,576 Views)