LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

FG array storage: out of memory errors

Solved!
Go to solution

Hello everyone, this is my first post here, I hope it's in the right place 🙂

 

I've been getting out of memory errors.  I'm running 32-bit LV on a system with 24GB of memory. I understand that LV can only use 2GB of memory, even so I have used the memory monitoring utilities to trace an issue to one of my subVI's, in which I am using a functional global to store arrays of data.

 

My LV program is taking in an array of new data periodically.  Each time a new array of data is received, I split it up into its components and store these components into another set of arrays.  I'm using USR's to store the arrays as functional globals, since I hear that this tactic improves performance.  However, using the memory monitoring utilities, I find that this subVI takes up much more memory than the amount of stored data suggests.  Therefore, I'm guessing that this subVI is making way more copies of data than it should.

 

Could someone please take a look at this VI, and tell me what "rule" I'm breaking that is causing problems?  It's not too big, I think it just needs an expert's eyes.  I'm still somewhat new to LV 🙂

Thanks!

Brian

0 Kudos
Message 1 of 10
(2,676 Views)

Can you please post the code in 2009 version. Also check your FG is re-entrant because if that is in re-entrant mode then always new  copies will get created wherever you use it.

-----

The best solution is the one you find it by yourself
0 Kudos
Message 2 of 10
(2,664 Views)

Do you have any idea of size that the arrays could be before hand?  I am asking because the Build Array is a memory leak waiting to happen.  It is better, if you can, to preallocate the array and use Replace Array Subset.  The build array will cause a copy of the entire array just to find a bigger memory location.  This causes massive fragmentation of memory.

 

The other thing is that the Delete From Array is not a good choice for parsing out your data.  Use the Index Array and Array Subset VIs to get the data you need.


GCentral
There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
0 Kudos
Message 3 of 10
(2,649 Views)

Thank you both for the suggestions.  I was even considering not parsing the incoming data at all, and just appending the new array as is.  There is really no need to store the f0, df, etc as separate arrays.  It could be just one giant 2D array.

 

However, I'm not sure how to get around using Build Array.  This VI processes a new array every time one of our robots takes a measurement.  Thus, I don't know how many measurements will be taken in a given session.  This makes it sort of impossible to preallocate exactly how much space will be needed beforehand.  I could allocate a large array, more than I think would be needed, or something like that.

 

I will post a 2009 version as soon as I get to work today.  Also, no one mentioned the case structures I was using.  Do they make copies, or are they OK to have in there?

Thanks for the help!

0 Kudos
Message 4 of 10
(2,636 Views)

Without seeing your code - ALL of it, not just the one functional global - there's no way to answer your questions, such as about the use of case structures.

 

EDIT: oh, and like others, I haven't installed 2012 yet, but I'll be happy to take a look when you post it saved back for an earlier version.  The reason it's helpful to see all of your code is that even if the code is correct in the functional global, you could be creating copies every time you put data in or take data out depending on how you're using the functional global.

0 Kudos
Message 5 of 10
(2,629 Views)

OK, here is the LV 8.0 saved version.  Unfortunately I can't share the rest of our source code.  As far as calling this VI is concerned, it is non-reentrant.  However, it only gets called in one place to store data, and in one other place to read the data.  Perhaps you could elaborate on "improper" ways of calling a functional global?

 

 

0 Kudos
Message 6 of 10
(2,624 Views)

That version appears to still be in LabVIEW 2012...

 

It's not so much that there are wrong ways to call a functional global, but, for example, if you store data in the functional global and also fork that wire to do something else with that data, you may force a copy (one getting stored, another being modified).  Same thing when you retrieve data - you force a copy so that the original can stay in the functional global unmodified while another copy is available to be manipulated.  You can write the functional global so it doesn't save a copy in this case but it requires a more sophisticated approach.  A more common solution is to move the manipulation into the functional global, making it an "action engine" where it can process commands and not just store data, so that the all the processing happens on a single copy of the data within one VI.

 

Fundamentally the problem is in your original post, "I'm using USR's to store the arrays as functional globals, since I hear that this tactic improves performance."  This isn't necessarily true.  While using shift registers to store data in functional globals CAN improve performance, their use alone does not guarantee efficient memory use.  You still need to understand how LabVIEW allocates memory and when it creates new buffers for copies.

0 Kudos
Message 7 of 10
(2,617 Views)

sorry about that, there was an incompatibility with attempting to save as version 8.0.  I saved as version 8.5, so this one should load 🙂

Thank you for the tips on globals, I will keep these in mind and maybe create an "action engine" to avoid processing outside the VI.  Let me know what you think of the actual code.

 

0 Kudos
Message 8 of 10
(2,613 Views)
Solution
Accepted by topic author beck.278

How much data are you trying to store in this functional global?  How often is it updated, and how many times is it called between resets?  If you know the maximum size of the data that you will need to store, it may be better to have the reset case allocate arrays of that size (instead of empty arrays) and then maintain an index which will indicate both the current size of the array and the position to insert the next piece of data.  This will be more efficient than build array.

 

Right now even if you have enough memory to store all the data it may be too fragmented to be usable.  Each time you use build array in the loop, LabVIEW may need to allocate an entirely new array of the current size + 1, then copy the the data to it, after which it can make the memory from the previous smaller array available again.  The next time through the loop you do this again, building up small blocks of available memory that may not be contiguous and are too small to reuse when the arrays next need to grow.  Pre-allocating the arrays to the maximum possible size and then replacing elements one at a time (as new data arrives) will solve this problem.  In addition it will be faster, because it takes less time to replace a single element than it does to copy an entire array to a new location.

 

Also, there's no need for the for loop to use Replace Array Subset.  Remove the shift register, and let autoindexing build up the output array.  You're actually generating an unnecessary extra copy by trying to reuse the array, instead of saving memory (because there's one copy in the shift register and one being used for autoindexing).  For loops are efficient for building arrays because their maximum size is known prior to starting the loop.  In addition the Initialize Array is not necessary - you're initializing values that will be immediately be overwritten - and you don't even need the Array Size function.  I'd do it as shown below:

Store Spectrum Data - For Loop.PNG

0 Kudos
Message 9 of 10
(2,608 Views)

Thank you very much to all who responded.  I appreciate the advice.  I think I have enough to go on now so I'll mark the issue solved.  I feel silly now that I see how simple it is to set up an array properly with a for loop!  The thing is, I just haven't dealt with arrays in LV until recently.  🙂

 

-Brian

0 Kudos
Message 10 of 10
(2,597 Views)