Jump to content
Cat

How many data copies should a graph make?

Recommended Posts

I have a vi that opens a file, reads it, and puts the data in a waveform graph. How many total copies of the data should be floating around after it does all that? I had thought it was 2, but it seems to be 3. This is not playing well with my Very Large data sets. And it's really bad when I need multiple data sets displayed at the same time.

I tried moving the read to a subvi, deallocating memory (which actually seems to work), and then passing the data to the waveform on the main vi. Still 3 copies.

Is my memory going along with my computer's?

Cat

Share this post


Link to post
Share on other sites

I you go to the Tools>>Profile>>Show Bufffer Allocations. It should indicate where theallocations are.

Share this post


Link to post
Share on other sites

I have a vi that opens a file, reads it, and puts the data in a waveform graph. How many total copies of the data should be floating around after it does all that? I had thought it was 2, but it seems to be 3. This is not playing well with my Very Large data sets. And it's really bad when I need multiple data sets displayed at the same time.

I tried moving the read to a subvi, deallocating memory (which actually seems to work), and then passing the data to the waveform on the main vi. Still 3 copies.

Is my memory going along with my computer's?

Cat

What "2" are you thinking about?

There is the data (1) and maybe the un-do buffer (2), and I would add in the default (3) but I suspect you know better than to save a large set as the default.

Just asking because I'm not sure how to account for three.

Ben

Share this post


Link to post
Share on other sites

Any control represents as many as 5 copies of the data.

Default value -- the value of the control by default.

Operate value -- the currently displayed value of the control.

Execute value -- the value actually in the FPTerminal. This may update several times before the data is passed to the control itself unless Synchronous Display is enabled.

Transfer value -- the value last moved from the FPTerminal to the Operate data. The transfer data copy is made by the executing thread so that the execution isn't locked by a transfer to the UI thread. Can't copy directly to Operate data since the UI might be in the middle of a redraw when the transfer occurs.

Extra value -- created only when VI Server Value property or a local variable gets involved trying to copy the data back out of the control. The comments here are talking about the extra data.

:o:blink::wacko:

Wow. Cool info to have. Never came across that before.

Thanks AQ.

Shane.

Edited by shoneill

Share this post


Link to post
Share on other sites

Any control represents as many as 5 copies of the data.

5 copies. Yeesh.

I'm attaching a pic of an example BD. All it does is read a file (~150MBytes) and send it to a waveform graph. The loop is there to keep the vi "alive". The default of all controls/indicators is "empty". There have been no edits done since the last save (in fact, I've been editing, saving, exiting LV, and starting the vi clean, just to make sure there are no residual memory or undo issues).

When the vi is opened, LabVIEW is showing 81MB of memory usage. After it runs and is in steady state, LabVIEW shows ~537MB of memory usage. This would be, I assume, three copies of the data. Where are they all coming from? I've got "Show Buffer Allocations" turned on for arrays in the pic, and there's only 1 little black box showing.

I'm running 8.6.1, if that makes a difference.

post-9165-125422352305_thumb.png

Share this post


Link to post
Share on other sites

5 copies. Yeesh.

I'm attaching a pic of an example BD. All it does is read a file (~150MBytes) and send it to a waveform graph. The loop is there to keep the vi "alive". The default of all controls/indicators is "empty". There have been no edits done since the last save (in fact, I've been editing, saving, exiting LV, and starting the vi clean, just to make sure there are no residual memory or undo issues).

When the vi is opened, LabVIEW is showing 81MB of memory usage. After it runs and is in steady state, LabVIEW shows ~537MB of memory usage. This would be, I assume, three copies of the data. Where are they all coming from? I've got "Show Buffer Allocations" turned on for arrays in the pic, and there's only 1 little black box showing.

I'm running 8.6.1, if that makes a difference.

post-9165-125422352305_thumb.png

If you drop an "deallocate" and let that code stop (to let the deallocate work), does the memory drop?

I'm thinking the transfer buffer is the extra copy.

Ben

Share this post


Link to post
Share on other sites

Further details... Items marked with "I THINK" may not be correct and may be amended by later posts.

  1. If the front panel of a VI is NOT loaded, there is only one copy of the data, the data actually in the terminal. So there isn't any copy overhead when calling a subVI whose panel is not loaded. Notice I said "loaded" not "open."
  2. A VI's panel is loaded if
    1. It's front panel is actually open
    2. There are any local variables or any statically-linked property nodes on its block diagram
    3. Someone has obtained a control reference to any control on the panel or to the panel itself
    4. The VI has unsaved changes (the panel is kept in memory until you save the VI)
    5. You're doing remote debugging of the VI

All of these can create the situation where a VI runs slower than expected, particularly while debugging.

[*]Application Builder strips the front panel from VIs by default except the top level VI. This is specifically to avoid this slowdown cropping up by accident.[*]I THINK that if a VI is running in the UI thread (File >> VI Properties >> Execution >> Preferred Execution System) then LV can skip the transfer data and copy directly to the operate data because it knows there cannot be a draw event going on at that moment. Not sure about that.[*]A local variable is more efficient than a Value property call because both make a data copy but the Value property has the overhead of having to switch to the UI thread. I THINK that if a VI itself is running in the UI thread that they are then equivalent. Nothing beats using the FPTerminal.[*]If you only need data storage and not data display, instead of a local variable, consider using a Data Value Reference, new in LV 2009. This is something that came up after release as a possible use after LV 2009 was released, and I don't know of any benchmarks comparing the two. I THINK that for a large array, the mutex overhead of the DVR will be less than the copy overhead of the local variable. But that's just a hypothesis.

I'm thinking the transfer buffer is the extra copy.
The "anxious deallocate" primitive can more often than not slow your performance more than the copy overhead. If your only concern is memory overhead, not speed, you might benefit from using it. Maybe. My recommendation is that you put it in a Case Structure and only invoke it if the array on your diagram is greater than size N where N is some large number that is rarely reached.

Share this post


Link to post
Share on other sites

5 copies. Yeesh.

I'm attaching a pic of an example BD. All it does is read a file (~150MBytes) and send it to a waveform graph. The loop is there to keep the vi "alive". The default of all controls/indicators is "empty". There have been no edits done since the last save (in fact, I've been editing, saving, exiting LV, and starting the vi clean, just to make sure there are no residual memory or undo issues).

When the vi is opened, LabVIEW is showing 81MB of memory usage. After it runs and is in steady state, LabVIEW shows ~537MB of memory usage. This would be, I assume, three copies of the data. Where are they all coming from? I've got "Show Buffer Allocations" turned on for arrays in the pic, and there's only 1 little black box showing.

I'm running 8.6.1, if that makes a difference.

post-9165-125422352305_thumb.png

When working with large files like this I generally try to read the file in chunks. If you can do that you may find that you significantly decrease your memory usage as well as see an increase in the performance. Reading large files in a single read is extremely inefficient, at least based on my experience so far.

Share this post


Link to post
Share on other sites
If you drop an "deallocate" and let that code stop (to let the deallocate work), does the memory drop? I'm thinking the transfer buffer is the extra copy. Ben
Whether I deallocate or not, when I stop the vi the memory drops by about ~150MB, ie, I'm down to two copies of the data in memory. In another version of this code, I took the loop out of the code I attached above, and turned the graph into a plain array. Then I called that vi from another vi and attached it to an array on the calling vi. I did this because I thought there might be something with the Read function that was holding on to extra data (I know, I was grasping at straws). I deallocated the memory in the subvi. It actually did deallocate -- I was pleasantly surprised, since I haven't had a whole lot of luck using that function in the past. <BR><BR>I put the call to the subvi in a sequence where I call it and wait 10 seconds after it returns -- passing the data wire thru that frame. Up to that point only 1 copy of the data is made. In the last frame, the wire is connected to the array terminal. As soon as program flow gets to that last frame, two more copies of the data are made. I understand LV makes 2 copies of FP controls, but why isn't it reusing the copy that's there not doing anything else? Edited by Cat

Share this post


Link to post
Share on other sites

You have the FP open when running this VI. That means that you have the buffer coming from the Read node, the Operate data and the Transfer data.

Do this: Close the VI so it leaves memory (that deallocates all the data). Open a new VI. Drop your current VI on the diagram as a subVI and then run the new VI. You should only see the one copy of the data that is coming from the Read node.

I understand LV makes 2 copies of FP controls, but why isn't it reusing the copy that's there not doing anything else?
Because that one copy is the already allocated buffer for when you run the VI again. In other words, if you run the VI a second time, you won't take a performance penalty having to allocate that first buffer because LV will use the one already allocated, assuming it is the size needed. Running thousands of VIs you'll find that most of the time arrays and strings are the same size every time they go through a given block diagram. LV leaves the dataspace allocations allocated all the way through the diagram because for repeated runs, especially direct runs of the VI that happen when you're testing and debugging your VIs, the data is the same size and you don't have to do the allocation every time.

Share this post


Link to post
Share on other sites

When working with large files like this I generally try to read the file in chunks.

I agree, and if I wasn't outputing this to a graph, I would be reading in chunks.

This really all started because my users have been getting "out of memory" errors when running one of my analysis programs. I went in to it to see if I could make it more efficient, and kept running into copies of code where I didn't think I was making any.

I'm going to have to break the files up anyway, in a macro sense. These files can get quite large and impossible to read on a generic laptop. However, I would like to break it up as little as possible for better usability.

Share this post


Link to post
Share on other sites

I agree, and if I wasn't outputing this to a graph, I would be reading in chunks.

This really all started because my users have been getting "out of memory" errors when running one of my analysis programs. I went in to it to see if I could make it more efficient, and kept running into copies of code where I didn't think I was making any.

I'm going to have to break the files up anyway, in a macro sense. These files can get quite large and impossible to read on a generic laptop. However, I would like to break it up as little as possible for better usability.

Why can't you read the file in chunks and simply build up the data to pass to the graph? You could preallocate the array used for the graph data and replace it as you read from the file. Once all the data has been read pass the entire data set to the graph for display.

Share this post


Link to post
Share on other sites

Why can't you read the file in chunks and simply build up the data to pass to the graph? You could preallocate the array used for the graph data and replace it as you read from the file. Once all the data has been read pass the entire data set to the graph for display.

I was going to ask you if that's what you meant, but then I thought that wouldn't help any because I'd be making a copy (or more) for the array and a copy (or more) for the graph. At this point I'm not sure if that's not just going to make matters worse. But I can give it a try.

If I do the read in a subvi and deallocate, that works fine (1 copy made), it's just when that output gets put into the control on the calling vi that extra copies are made.

Share this post


Link to post
Share on other sites

I was going to ask you if that's what you meant, but then I thought that wouldn't help any because I'd be making a copy (or more) for the array and a copy (or more) for the graph. At this point I'm not sure if that's not just going to make matters worse. But I can give it a try.

If I do the read in a subvi and deallocate, that works fine (1 copy made), it's just when that output gets put into the control on the calling vi that extra copies are made.

Hi Cat,

Do you agree that Aristos has answered the mysterious parts fo the challenge and now you have to work with that limtiation?

If yes, then you may want to concider Dr Damien paper on managing large data sets that can be found here.

http://zone.ni.com/devzone/cda/tut/p/id/3625#toc2

The section called "Fast Data Display with Decimation" may be useful.

Ben

Share this post


Link to post
Share on other sites

You have the FP open when running this VI. That means that you have the buffer coming from the Read node, the Operate data and the Transfer data.

Do this: Close the VI so it leaves memory (that deallocates all the data). Open a new VI. Drop your current VI on the diagram as a subVI and then run the new VI. You should only see the one copy of the data that is coming from the Read node.

Yes, I agree, there is only 1 copy made of the data. Or 0 copies if the subvi deallocates memory. But attach the array in the subvi to a control in the main vi and 3 copies are made. Given no local variables, no references, no updating -- I'm still not sure where they are all coming from.

Because that one copy is the already allocated buffer for when you run the VI again. In other words, if you run the VI a second time, you won't take a performance penalty having to allocate that first buffer because LV will use the one already allocated, assuming it is the size needed. Running thousands of VIs you'll find that most of the time arrays and strings are the same size every time they go through a given block diagram. LV leaves the dataspace allocations allocated all the way through the diagram because for repeated runs, especially direct runs of the VI that happen when you're testing and debugging your VIs, the data is the same size and you don't have to do the allocation every time.

It sounds to me like what you're saying is that LV sees that 150MB worth of data has entered a vi from somewhere and it decides to make a 150MB buffer for that vi. Then when the data actually goes somewhere (ie, gets wired to a control) it passes thru that buffer, but that buffer is not used for making the 2 usual copies of the data for the control; 2 more copies are added. I've been saved the time of having to allocate 150MB of memory next time I run the program, but in the meantime, my 150MB of data is eating up almost a half a Gig of memory.

Am I getting close??

Do you agree that Aristos has answered the mysterious parts fo the challenge and now you have to work with that limtiation?

We may be getting close...

If yes, then you may want to concider Dr Damien paper on managing large data sets that can be found here.

http://zone.ni.com/d.../p/id/3625#toc2

Thanks for the suggestion, but I read that article before bugging you all with this. I actually do decimation on some of my graphs, but in this case I can't. It often gets used for transient analysis -- where 2 or more plots are compared in time -- and the user needs to get down to sample-level resolution.

Share this post


Link to post
Share on other sites

Yes, I agree, there is only 1 copy made of the data. Or 0 copies if the subvi deallocates memory. But attach the array in the subvi to a control in the main vi and 3 copies are made. Given no local variables, no references, no updating -- I'm still not sure where they are all coming from.

It sounds to me like what you're saying is that LV sees that 150MB worth of data has entered a vi from somewhere and it decides to make a 150MB buffer for that vi. Then when the data actually goes somewhere (ie, gets wired to a control) it passes thru that buffer, but that buffer is not used for making the 2 usual copies of the data for the control; 2 more copies are added. I've been saved the time of having to allocate 150MB of memory next time I run the program, but in the meantime, my 150MB of data is eating up almost a half a Gig of memory.

Am I getting close??

We may be getting close...

Thanks for the suggestion, but I read that article before bugging you all with this. I actually do decimation on some of my graphs, but in this case I can't. It often gets used for transient analysis -- where 2 or more plots are compared in time -- and the user needs to get down to sample-level resolution.

We had a similar problem with large images. Our solution was to view at different resolutions (i.e decimate) and load from disk only the sections of the image the user could see as he zoomed in rather than try to keep the whole image in memory. So in the whole picture we had reduced resolution but as he/she zoomed in it would reload at finer and finer granularity. You could do the same thing with a graph after all, when viewing the whole timeseries of lets say 1 week, can a user really visually resolve 1us? As he changes his axis, you could reload that section of data and at some point (where you decide) you no longer decimate but load raw data.

Share this post


Link to post
Share on other sites

We had a similar problem with large images. Our solution was to view at different resolutions (i.e decimate) and load from disk only the sections of the image the user could see as he zoomed in rather than try to keep the whole image in memory.

Yeah, I've been bouncing something like this around in my head for awhile. I haven't been able to do it with graphs I've decimated in the past, because they are drawn in "real time". There's no historical data buffer to go back to and zoom in on. But my current application is a static file, so it should be doable.

Share this post


Link to post
Share on other sites

Yeah, I've been bouncing something like this around in my head for awhile. I haven't been able to do it with graphs I've decimated in the past, because they are drawn in "real time". There's no historical data buffer to go back to and zoom in on. But my current application is a static file, so it should be doable.

Good excuse to get an SSD too :thumbup1:

Share this post


Link to post
Share on other sites
Application Builder strips the front panel from VIs by default except the top level VI.

One addition - the AB also keeps the FPs in these cases:

  • VIs which are set to have their FP open (duh)
  • VIs which are explicitly marked in the AB as "don't remove FP".
  • VIs which have property nodes statically linked to controls on their FPs (useful if you want to keep an FP in the EXE without explicitly setting it in the AB).
  • Probably all VIs if you enable debugging (guess), but that's not really relevant in this case.

Share this post


Link to post
Share on other sites

One addition - the AB also keeps the FPs in these cases:

  • VIs which are set to have their FP open (duh)
  • VIs which are explicitly marked in the AB as "don't remove FP".
  • VIs which have property nodes statically linked to controls on their FPs (useful if you want to keep an FP in the EXE without explicitly setting it in the AB).
  • Probably all VIs if you enable debugging (guess), but that's not really relevant in this case.

  • If there is an event structure (maybe only when an event is registered for a control

Ton

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.