LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Good practice for memory management

Hello,

 

I am programming a LabView VI based on an ActiveX from Horiba Jobin Yvon.

The Vi allows to acquire a 1024x256 pixels picture, or a part from it.

The program can run an acquisition a single time (single acquisition) or in loop (continuous acquisition), or triggered/driven by a measurement program.

Unfortunately, it seems that while acquiring the full 1024x256 pixels, the program can only run a given number of times before having memory issues. The problem appears to be correlated to the number of pixels being read...

 

Yet I have no experience about the memory management in LabView: when should one use local variables? What are the other alternatives when I have to modify a variable (typically in my case the graph) at different diagram position?

 

I cannot identify where my problem originates. And would appreciate any general or detaillled comment on this VI.

Message 1 of 7
(3,997 Views)

Your problem is certainly with local variables and extremely inefficient code design. There is no need to use any local variables, but you seem to use them for everything, including large data structures, reading from and writing to them in tight loops. This escalates your memory use.

 

You clearly have a background in text based code and some old habits prevent you from writing efficient LabVIEW code. (see also).

 

All you need is shift registers. Let's look at one of your subVIs. (See image). You seem to be under the false impression that it is illegal for a wire to cross a structure boundary :o.

 

There is the terminal for "areas data" on the left, not connected to anything. Then, instead of simply wiring into the code, you first read it with a local variable to get the size and then you read another local variable instance of it with every iteration of the loop. Why? The control never changes during the execution of the loop! Right? Same with the orange 2D arrays. Initialize a shift regsiter, replace the data, and write to the indicator once after the loop has finished. No locals needed.

 

Also, why do you write to locals of all your scalar indicators? While this has no significant memory impact it doubles the complexity of your code. Simply delete the locals and place the indicator itself there.

 

THere are also potentially serious race conditions, because you have no quarantee that e.g. "Xbin" and "Binned X size" actually gets written by the upper code before the locals of same in the inner structure are read. The order of events in not determined. These thing can execute in parallel. Only a wire forces execution order.
Message Edited by altenbach on 05-26-2009 08:13 AM
Message 2 of 7
(3,977 Views)

Your code suffers from the dual-condition we here like to call "sequencitis" and "local variablitis". Text-based programmers would absolutely love your code. LabVIEW programmers, on the other hand, would have a heart attack. A quick look at it tells me that I could bet that 95% of your local variable are unnecessary, and I'm only holding out on the 5% since I'm not going to look at the code in detail. It hurts my eyes too much. Same goes for the sequence frames.

 

That said, your memory issues are probably caused by several issues:

  •  Coercion dots : There are several places where you are bouncing between 3D arrays of I32 and 3D arrays of DBL. All of this comes at a cost.
  • The ActiveX function that returns the data: How does this work? This likely allocates another chunk of memory each time it runs.

 

I would stronly recommend looking into application design structures such as state machines. As it is your code is virtually impossible to maintain.

 

Couple of other comments:

  • You should NEVER use the Stop function unless you really mean it, and even if you do, it's probably still the wrong way to do it. This is the same as pressing the Abort button on the toolbar which is almost never a good idea.
  • Some of the subVIs don't make much sense. The "Areas2LargeArea" for example. You have a loop that is set up to run for as many columns as are in the 2D array, but the output array will only be based on the last iteration. Why? I don't know if the default values you have for "Areas Data" is what you expect, but if it is, what's the point of the loop?
Message 3 of 7
(3,975 Views)

As another example, let's have a closer look at the VI "ShowAcquisitionOnChip.vi" that I quoted above.

 

  • The "datas" control is I32, but you wire it a DBL array in the main VI. let's assume that the data is actually I32. We don't need any orange wires!
  • 9 of your controls/indicators have no purpose in life except to serve as a local variables. The can all  be deleted.
  • Instead of rounding down a division, you can use q&r division. All blue!
  • Note that "index array" is resizeable. No need to have X instances, each with a different index hardwired. Also note that unwired indices are automatically assumed to be one higher than the index above it (recursively).
  • Below is an image of a quick rewrite that eliminates all these unecessary controls/indicators and does everything in blue. I did not inspect the sanity of your code logic per se, so this is just a mindless refactoring for performance. It is probably possible to do things even simpler.

 

I am sure this would be factors faster and would use significantly less memory. Of course it would only make a difference if you would refactor your entire application for consistent datatypes. Unfortunately, this will not be easy.

 

 

 

Message Edited by altenbach on 05-26-2009 01:11 PM
Message 4 of 7
(3,922 Views)

Hello,

 

Thank you very much for your comments! And sorry for the eye-pain & heart attacks I caused!

 

For some obscure reason I thought using local variable was a good idea. I am glad you corrected me on this point since I am still learning how to program in LabView.

 

I am currently in the process of rewriting the whole thing based on your comments. Hopefully this will kick out most of the issues I encounter.

 

Best regards!

 

Mathieu

Message 5 of 7
(3,868 Views)

It's no wonder you think Local Variables are good, as the same term is used for Good Programming in text based languages. Comparing with text based languages, you can view Wires as a pointer and a Local variable as a data copy. (Maybe not quite correct, but good enough as a rule of thumb)

 

Basically, both for performance and memory usage: Wires > Shift registers > Local variables > Properties

 

Situation ofcourse often dictates which needs to be used, but when you have the choice ...

 

/Y

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
Message 6 of 7
(3,863 Views)

Yamaeda wrote:

 

you can view Wires as a pointer and a Local variable as a data copy. (Maybe not quite correct, but good enough as a rule of thumb)

 

Basically, both for performance and memory usage: Wires > Shift registers > Local variables > Properties


Just a small change, wires as such are variables in LV & locals as data copies of those variables...

 

Mathieu,

 

To visualise what Yamaeda has said, just see the attached pic from LV Help, for efficient data passage.

- Partha ( CLD until Oct 2024 🙂 )
Message 7 of 7
(3,833 Views)