Jump to content

Inlining a subVI that uses the In Place Memory Structure


Onno

Recommended Posts

In a rather time-critical VI in my project, I'm doing the following:

  1. Pre-allocating an array buffer;
  2. Storing this buffer in a shift register of the loop;
  3. Using the In Place Memory Structure to update part of the buffer.

This way I'm trying to prevent unnecessary copies of the array, and optimize performance.

Now I'd like to put part (3) in a subVI, to clean up the BD. What I've understood (but please correct me if I'm wrong), is that calling a subVI generally creates copies of the data. This would mean that creating the subVI for (3) would defeat the whole purpose of (3).

If that's correct, then my question is: can I solve this by making (3) an Inline subVI?

Thanks for sharing your insights!

Best regards,

Onno

Link to comment

Now I'd like to put part (3) in a subVI, to clean up the BD. What I've understood (but please correct me if I'm wrong), is that calling a subVI generally creates copies of the data. This would mean that creating the subVI for (3) would defeat the whole purpose of (3).

If that's correct, then my question is: can I solve this by making (3) an Inline subVI?

A properly-written subVI will not make a copy of data passed into it. You can use the "Show Buffer Allocations" tool to see this. In the subVI, all the front panel terminals should be at the top level (outside any loops and structures), and terminals should be marked required.

Link to comment

Hi Onno,

As the others have said a VI doesn't have to copy data into a subVI so if you have written your subVI to be inplace and not make copies then your job is already done!

The inplace subVIs do something slightly different. It means the subVI is their symbolically for you but the code from the subVI is placed directly into the calling VI. It means that what little overhead is required in calling subVIs is eliminated (at the cost of some features such as debugging) so it shouldn't impact your memory copies.

Cheers,

Mac

Link to comment

If you are updating the array with new values, you shouldn't need the in-place element structure. The replace array subset function should not make a copy in most instances. In-place really only shines if you are taking data out of the array, modifying it, and stuffing it back in.

Edited by jdunham
Link to comment

I have somewhat related question, I think.

I was disappointed to find that Labview 8.6 does not have a native "mod" function, but I found that I could create my own using a formula node:

post-4344-0-00037800-1292958379_thumb.pn

This runs the at same speed as the native rem/IQ function, but treats negative numbers the way I wanted it to.

It's pretty ugly, though, to have to sprinkle those formula nodes around my code, so I made it into a subvi.

Even with required inputs and subroutine priority, the subvi implementation is ~3000x slower than the formula node on its own. I understand that there's overhead associated with calling subVI's, and when the contents of the subVI are very fast, that overhead will become the dominant factor. Also, in this case, the factor of 3000 is the difference between "really fast (7us/iteration)" and "really really really fast (2.5ns/iteration)". That said, does anyone have any suggestions? Am I just stuck with that large (although possibly insignificant) slowdown as the price of having prettier code?

Thanks,

Gary

Link to comment

Correct me if I'm wrong, but doesn't this have the same result?

Not for negative numbers.

Try putting a negative number in your array... You'll get a different answer.

mod and rem aren't the same for negative numbers, although they vary from language to language (AARGH!).

The LabVIEW formula node has both versions, but the native function only supports the approach that gives positive remainders.

Edited by Gary Rubin
Link to comment

Even with required inputs and subroutine priority, the subvi implementation is ~3000x slower than the formula node on its own. I understand that there's overhead associated with calling subVI's, and when the contents of the subVI are very fast, that overhead will become the dominant factor. Also, in this case, the factor of 3000 is the difference between "really fast (7us/iteration)" and "really really really fast (2.5ns/iteration)". That said, does anyone have any suggestions? Am I just stuck with that large (although possibly insignificant) slowdown as the price of having prettier code?

I think you could you this information to allow you to inline the code, in the development environment, and still keep the code semi pretty. You can inline to a flat sequence structure and it takes about the same amount of space as a sub vi. Bad part is that the inline is one way. Of course if you did this right before you made an exe, and you had your code in version control, you could revert back after the exe was made. I believe JKI did this sort of thing in a build script, so it is possible to use this technique to inline subVIs at EXE build time, but you'd have to build your own build script.

On a side note, I believe LV 2010 can be told to inline VI's on a VI by VI basis. I believe it inline's new VIs by default.

Link to comment

mod is just a formula, why not code the one that returns the way you want? I think x - (y * int(x/y)) does the trick.

Right, but I still have the same basic problem. I have a small, but not insignificant block of code that will be used in several places. To me, that sounds like a textbook reason for making a subVI, but what I'm finding is that the actual calculations take about 0.03% of the time, and overhead associated with calling the subvi seems to take the other 99.97% of the time.

I was wondering about any tricks to trim that 99.97% overhead load.

I'll see what I can do with the inline subvi switch, but I was wondering what other methods might exist.

Gary

Link to comment

Right, but I still have the same basic problem. I have a small, but not insignificant block of code that will be used in several places. To me, that sounds like a textbook reason for making a subVI, but what I'm finding is that the actual calculations take about 0.03% of the time, and overhead associated with calling the subvi seems to take the other 99.97% of the time.

Ahh, I see the distinction. Perhaps some of the overhead is because of the formula node. Try benchmarking an all-native implementation?

As was mentioned, LV2010's inline option is advertised as being the same as merging the subVI instead of placing it, so maybe that will end up being a sufficient solution.

Link to comment

Right, but I still have the same basic problem. I have a small, but not insignificant block of code that will be used in several places. To me, that sounds like a textbook reason for making a subVI, but what I'm finding is that the actual calculations take about 0.03% of the time, and overhead associated with calling the subvi seems to take the other 99.97% of the time.

I was wondering about any tricks to trim that 99.97% overhead load.

I'll see what I can do with the inline subvi switch, but I was wondering what other methods might exist.

Gary

Making the VI a "subroutine" is the fastest call method (i haven't played with the in-line feature very much but inline+subroutine should be the fastest). What sort of execution times are you seeing? Even a normal call is only 10's of usecs.

Edited by ShaunR
Link to comment

Making the VI a "subroutine" is the fastest call method (i haven't played with the in-line feature very much but inline+subroutine should be the fastest). What sort of execution times are you seeing? Even a normal call is only 10's of usecs.

It looks like I'm getting about 7us per call. Still not sure if that's to slow or not.

Link to comment

...but inline+subroutine should be the fastest...

Can inlining and subroutine priority really be combined?

This would mean that the inlined code should run at another priority that the hosting VI.

I have never tried so I don't know for sure.

It looks like I'm getting about 7us per call. Still not sure if that's to slow or not.

1. How many elements are you feeding to your subVI when you get these times?

2. Are you running this on Windows/RT?

/J

Link to comment

It looks like I'm getting about 7us per call. Still not sure if that's to slow or not.

Well. I wouldn't be complaining about 7 us to calculate a formula node.

Can inlining and subroutine priority really be combined?

This would mean that the inlined code should run at another priority that the hosting VI.

I have never tried so I don't know for sure.

Sure it can. It has nothing to do with priorities. As I understand it, when a VI is set to subroutine it means it gets executed sequentiality within the VI so there is no chance that a task/thread switch can occur at the call boundary. As for in-line - in theory the code boundary shouldn't exist, but you can select both subroutine and in-line, so I'm not quite sure exactly what happens. Like I said. I haven't really played with in-line but the VI has to be re-entrant whereas for subroutine it doesn't have to be.

1) 20k.

2) Win7-64, although the code will eventually be deployed on Windows Embedded.

Well. 7 us for 20k elements isn't bad. That's 0.35ns per element yes.gif Any faster and it would have calculated it before you ran the VI biggrin.gif

Link to comment

Well. I wouldn't be complaining about 7 us to calculate a formula node.

Sorry, not 7us for the formula node -- 7us to call the subvi. The actual formula node calculation is much, much faster than that.

The calculation time is what it is. It's the overhead of the subvi call that I was hoping to be able to do something about.

Link to comment

Sure it can. It has nothing to do with priorities. As I understand it, when a VI is set to subroutine it means it gets executed sequentiality within the VI so there is no chance that a task/thread switch can occur at the call boundary. As for in-line - in theory the code boundary shouldn't exist, but you can select both subroutine and in-line, so I'm not quite sure exactly what happens. Like I said. I haven't really played with in-line but the VI has to be re-entrant whereas for subroutine it doesn't have to be.

Sorry, I think you mistaken when speaking about LabVIEW 8.6. What you are saying may be correct for LabVIEW 2010, but I don't know for sure. In LabVIEW 8.6, if you "inline" a subVI, the subVI's code is literally copied into a flat sequence structure on the parent VI while you watch. You get a choice to "hide" or "show" the code by allowing LabVIEW to shrink or expand your block diagram with the code from the subVI. If you choose to "hide" the code, you get a flat sequence structure that is approximatly the size of a subVI icon, if you choose to show the code, your diagram is expanded to hold a flat sequence structure with the code from the subVI.

Link to comment

Sorry, I think you mistaken when speaking about LabVIEW 8.6. What you are saying may be correct for LabVIEW 2010, but I don't know for sure. In LabVIEW 8.6, if you "inline" a subVI, the subVI's code is literally copied into a flat sequence structure on the parent VI while you watch. You get a choice to "hide" or "show" the code by allowing LabVIEW to shrink or expand your block diagram with the code from the subVI. If you choose to "hide" the code, you get a flat sequence structure that is approximatly the size of a subVI icon, if you choose to show the code, your diagram is expanded to hold a flat sequence structure with the code from the subVI.

In LV2010 there is a checkbox on in the properties so you don't have to physically place the code in the diagram. That why I said there is no longer a code boundary (as if you had placed the code in the diagram) however it is still represented as a sub-vi.

Link to comment

In LV2010 there is a checkbox on in the properties so you don't have to physically place the code in the diagram. That why I said there is no longer a code boundary (as if you had placed the code in the diagram) however it is still represented as a sub-vi.

Chris is right - I'm still on 8.6. And this is why I generally stop posting on LAVA once I'm a version or two behind -- most of my issues/questions have become deprecated. sad.gif

Link to comment

Chris is right - I'm still on 8.6. And this is why I generally stop posting on LAVA once I'm a version or two behind -- most of my issues/questions have become deprecated. sad.gif

It's been a long time since I used a FN., but I tried replicating your image (in 2009) and sizeofDim(x,1) evaluates to "0". My output array is identical to the input.wacko.gif

Link to comment

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.