07-22-2009 08:46 AM
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.
07-22-2009 09:06 AM
07-22-2009 02:26 PM
Thanks Dr. D.
If you're optimizing for diagram space and need good performance, there's always the OpenG solution:
10-21-2010 08:03 AM
@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).
11-02-2010 09:09 AM - edited 11-02-2010 09:19 AM
@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":
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...
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.
11-02-2010 09:21 AM
@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!
11-02-2010 09:29 AM
@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.
11-03-2010 02:18 PM
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?
11-03-2010 02:41 PM
@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?
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
11-03-2010 02:54 PM
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).]