LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

memory goes crazy when calling a sub-vi

Hi,

i've got the following problem using labview 7 express:

For a monitoring application i need to store a lot of measuring-points
in memory (e.g. around 100 MB). I also want to load the whole data-set
from a file and thats where all the problems starts.

So i want to create a sub-vi that receives the original array as
input, loads the all data sets from a file and returns the "new" data
via an indicator. Just for the case it is important: the array-size is
constant all the time, so not even resizing is / should be done by
labview. And the initial array was created using InitializeArray at
startup - so everything has the right size before it gets to the
sub-vi.

For testing purposes i just connected the input control with the
out
put-indictator in the sub-vi (without loading data that is). So i
expected, that labview would only forward the data in the subvi
without allocating new memory (referring to the application note about
memory and performance). But once the sub-vi is called, the used
memory is increased by like 100-200 MByte.


Does anyone of you have a clue where my problem might be?

Thanks in advance,

Sebastian
0 Kudos
Message 1 of 11
(3,354 Views)
Sounds like you are passing a 100MB array to your sub-vi. As soon as you do this, you make a copy of the data. That is, the input variable is not a reference to the array, it is a copy of the array. To understand this more clearly, think about wiring the same array to four or five different sub-vis, each doing something different with the data. In order to have each of the sub-vis work with the original array data, each one must make a copy of the array.

You can limit the number of copies of the array by using global variable (Shh, don't tell anyone that I suggested it.). You can also use control references, i.e. if the value is in a control in the calling vi, you can pass a reference to the control to the sub-vi and get the array values from a property node
. Also, you can create your own memory chunk using the "extcode" library memory management functions and a CIN or a DLL. NI suggests using a "functional global" for this purpose. They are usually right. After all they wrote the stuff.

Check out this link to the NI site:
http://zone.ni.com/devzone/conceptd.nsf/webmain/6A56C174EABA7BBD86256E58005D9712?opendocument
jc
Mac 10.4
LV7.1
CLD
0 Kudos
Message 2 of 11
(3,353 Views)
> Sounds like you are passing a 100MB array to your sub-vi. As soon as
> you do this, you make a copy of the data. That is, the input variable
> is not a reference to the array, it is a copy of the array. To
> understand this more clearly, think about wiring the same array to
> four or five different sub-vis, each doing something different with
> the data. In order to have each of the sub-vis work with the original
> array data, each one must make a copy of the array.
>
> You can limit the number of copies of the array by using global
> variable (Shh, don't tell anyone that I suggested it.). You can also
> use control references, i.e. if the value is in a control in the
> calling vi, you can pass a reference to the control to the sub-vi and
> get the array values from a property node. Also, you can create your
> own memory chunk using the "extcode" library memory management
> functions and a CIN or a DLL. NI suggests using a "functional global"
> for this purpose. They are usually right. After all they wrote the
> stuff.
>
> Check out this link to the NI site:
> http://zone.ni.com/devzone/conceptd.nsf/webmain/6A56C174EABA7BBD86256E58005D9712?opendocument


I'm afraid that I'll have to disagree with most of these
recommendations. LV arrays and other types do work by value, so
splitting an array must behave as though each recipient gets its own
copy, but that doesn't mean that the LV compiler can't optimize some of
them away, and that is in fact what it tries to do.

What you are most likely seeing is that your subVI is left open or is
otherwise unsaved. This means that LV updates the values in the subVI
for debugging or display to the user when the panel is opened. If your
subVI has an array in, an array out, and uses replace array subset, you
should get it to work on the original array in. Beware that if your
subVI is a little off or if your top VI displays the array, copies can
be made.

So how about globals? Globals make copies too. In fact writing a 100MB
array to the global means you have two of them. You can then shrink the
callers, but you have to do it explicitly. Then when you read the
global, you get another 100MB. If you make a functional - LV2 style -
global, you can read back or access just what you need, so they are
better, but not better than wires.

How about control references? Please don't treat them like data
pointers. They are references to a complex UI element, not data. Most
of the same rules apply as wth the global, but since they are display
objects, you are going to get yet another copy used for UI.

As for the referenced article, this was written by someone who has dealt
with very large arrays on a regular basis. I'd highly recommend you
read it, then you can use the techniques when they are needed and when
the additional complexity and tradeoffs are called for.

Greg McKaskle
0 Kudos
Message 3 of 11
(3,353 Views)
I wanted to add a plug for one of the new features in LabVIEW 7.1. It now offers an enhanced tool that will show where LabVIEW is allocating buffers, and could be really useful for you to see where the allocations occur.

You can read more about it on page 19 of the LabVIEW Upgrade Notes

Evan
National Instruments
0 Kudos
Message 4 of 11
(3,136 Views)
Thanks for your insight, Greg. I was surprised to learn that global references each contain a copy of the data. This implies that each time data is written to a global, each copy of that global must get updated. The process sounds amazingly inefficient. Now I know why globals are taboo in LabVIEW.

I was also surprised to learn that control "references" are not like data pointers, or object pointers, in this case. Thanks for pointing out this error in thinking. This knowledge is sure to help me in future projects.

I have noticed that most of the NI code for interfacing with registers and managing memory have a dll at the core. The function details are handled outside of the LabVIEW development toolbox, precompiled and self contained.
It sounds to me that the only way to efficiently and effectively get control over the memory is to write the code block (in c or something) to manage the data the old fashioned way. It appears, as I have anxiously suspected, there's no substitute for knowing how to manage memory at the lowest level.

Since I am a slave to LV, I have only done this on rare occasions where the hardware I was controlling came with only a c app dev kit. I just deal with what NI gives me. 🙂
jc
Mac 10.4
LV7.1
CLD
0 Kudos
Message 5 of 11
(3,352 Views)
jcrooke wrote:

> Thanks for your insight, Greg. I was surprised to learn that global
> references each contain a copy of the data. This implies that each
> time data is written to a global, each copy of that global must get
> updated. The process sounds amazingly inefficient. Now I know why
> globals are taboo in LabVIEW.

Well for scalars they are ok. But never use them for arrays. The reason
this must be done so, is that LabVIEW execution is determined by dataflow
almost exclusively and that allows for multiple code sections executing
quasi-simultanous. Treating globals by reference could give you an issue
where one part of the program reads the global while another one writes
it, causing the read to read half of the old data and half of the new
data. In C you have typically sequential execution and if you happen to
create multiple threads and read a global from one thread while writing
it in another it is the programmers responsibility to protect that
resource or his program will behave erratically at best.

> I have noticed that most of the NI code for interfacing with registers
> and managing memory have a dll at the core. The function details are
> handled outside of the LabVIEW development toolbox, precompiled and
> self contained. It sounds to me that the only way to efficiently and
> effectively get control over the memory is to write the code block (in
> c or something) to manage the data the old fashioned way. It appears,
> as I have anxiously suspected, there's no substitute for knowing how
> to manage memory at the lowest level.

That is not the main problem. LabVIEW data types are a little different
than what C usually uses and it is easier to create the translation in C
than in LabVIEW. And since almost all direct hardware interfaces are
really C oriented this means that there is a DLL sooner or later. You
can't write a device driver in LabVIEW at all, as that is privileged
code executing in kernel space. Accessing a device driver from LabVIEW
although possible is quite a pain as the high level data structures used
in LabVIEW are most often completely different than the low level
interface of the device driver. So there again you need an intermediate
translation unit which is simply more convinient to write in C. And if
you don't know how to write that in C you couldn't possibly create a
direct interface in LabVIEW, but since you then know C it is easier to
do it in C then.

Not to mention that device driver interfaces are mostly undocumented and
often considered company secret. Putting the interface in a DLL hides
this interface much more effectively than trying to do everything
directly from within LabVIEW.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 6 of 11
(3,352 Views)
> Thanks for your insight, Greg. I was surprised to learn that global
> references each contain a copy of the data. This implies that each
> time data is written to a global, each copy of that global must get
> updated. The process sounds amazingly inefficient. Now I know why
> globals are taboo in LabVIEW.
>

The readers don't get a new copy until the next time they read. The
deal is that the global could be updated once a second with various
readers needing to hold the value they read for who knows how long.
Since there could be three readers needing to hold a different value for
ten seconds, that pretty much means there needs to be one global and one
per reader.

> I was also surprised to learn that control "referenc
es" are not like
> data pointers, or object pointers, in this case. Thanks for pointing
> out this error in thinking. This knowledge is sure to help me in
> future projects.
>
> I have noticed that most of the NI code for interfacing with registers
> and managing memory have a dll at the core. The function details are
> handled outside of the LabVIEW development toolbox, precompiled and
> self contained. It sounds to me that the only way to efficiently and
> effectively get control over the memory is to write the code block (in
> c or something) to manage the data the old fashioned way. It appears,
> as I have anxiously suspected, there's no substitute for knowing how
> to manage memory at the lowest level.
>

Each tool has its advantage, and C's advantage is that anything goes
with memory. Integers, pointers to A, pointers to B, its all the same.
The downside is that this lack of safeguards means lots of debugging
and head scratching. LV can't do everything as efficientl
y as C can,
but in the common case, you get the low level stuff written in C,
accessable and usable from LV so that you get the best of both. This is
true of most/all good libraries.

Greg McKaskle
0 Kudos
Message 7 of 11
(3,352 Views)
I want to thank you guys, Greg and Rolf, for taking the time to elaborate on the issue and encourage you to do so in the future. You both seem very knowledgeable and it helps to get a better understanding of what is really going on with the code. I have been operating under some flawed assumptions. This is a good forum for gaining understanding of some important, basic LV characteristics. Perhaps some of the passive readers of this discussion will benefit as well.

I don't really want to extend this discussion line further, but I am curious as to how you know so much about the internal structure of LabVIEW. Have you actually worked as a developer for one of the LabVIEW products, perhaps LabVIEW itself?
jc
Mac 10.4
LV7.1
CLD
0 Kudos
Message 8 of 11
(3,352 Views)
jcrooke wrote:

> I want to thank you guys, Greg and Rolf, for taking the time to
> elaborate on the issue and encourage you to do so in the future. You
> both seem very knowledgeable and it helps to get a better
> understanding of what is really going on with the code. I have been
> operating under some flawed assumptions. This is a good forum for
> gaining understanding of some important, basic LV characteristics.
> Perhaps some of the passive readers of this discussion will benefit as
> well.
>
> I don't really want to extend this discussion line further, but I am
> curious as to how you know so much about the internal structure of
> LabVIEW. Have you actually worked as a developer for one of the
> LabVIEW products
, perhaps LabVIEW itself?

Well for Greg it is easy. He is one of the core LabVIEW developers and
although he doesn't know every detail from his head, he can go and look
in the sources, if he needs to.

For me it is just 12 years of working with LabVIEW and having read a lot
on Info-LabVIEW, as well as having done my own extensive low level C
programming. Besides that, there has been a time when I had some spare
time left to dig rather deep into LabVIEW and experiment with it on many
levels to find out some of its internal workings.

Rolf Kalbermatter
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 9 of 11
(3,352 Views)
> Well for Greg it is easy. He is one of the core LabVIEW developers and
> although he doesn't know every detail from his head, he can go and look
> in the sources, if he needs to.
>
> For me it is just 12 years of working with LabVIEW and having read a lot
> on Info-LabVIEW, as well as having done my own extensive low level C
> programming. Besides that, there has been a time when I had some spare
> time left to dig rather deep into LabVIEW and experiment with it on many
> levels to find out some of its internal workings.

Easy huh? I don't know about that.

You will pick it up too. You learn from trying things, making mistakes,
and asking questions. LV has a simple syntax so that you can quic
kly
get started, but as with any good language, there are many different
ways to do things. This means that you can suite the solution to the
problem. Discovering when to apply which solution to what problem is
quicker if you are an experienced programmer in any other language. If
not, make lots of small controlled experiments and ask questions.

Greg McKaskle
0 Kudos
Message 10 of 11
(3,352 Views)