Jump to content

Inline sub vi


Recommended Posts

Hello

Would it be possible to write a small app that use scripting and preprocess a vi so that sub vis are inlined like in other programing languages. When execution speed is important as well as readability of the code, then inline functions is essential. Unfortunately function calling in labview is very slow and there is no option to inline the code, thus to make it fast, the code becomes unreadable.

But with scripting i guess it will be possible to use inline functionality as a sort of preprocessor option to just copy and paste the diagram of the sub vi into the main program ??

The subroutines could be reckognised for instance with an _inline_ in their names.

Would this be possible? It would be extremely usefull for apps that need to run fast.

BSvingen

Link to comment

Hi BSvingen:

Welcome to the LAVA forum.

For a long time I was convinced that there was a big overhead in calling a sub-vi in LabView. I'm not sure where I got the idea-- perhaps it was true in the early versions of the language that I started with or perhaps it was always my imagination. At any rate, presistent advice from others and my recent experience with LV suggests that sub-vi calls are very efficient, in most cases with near negligable impact on execution time relative to the same code executed inline in the calling vi.

Perhaps you can tell us what are you trying to do in your sub-vis and how you've measured the impact of the call on performance? There might be a tidier solution than creating in-line code.

That said, I'm sure that if anyone knows how to use scripting to generate inline code, it would be one of the contributors to this forum.

Best Regards, Louis

Link to comment

I have had the opposite experience. It is true that the total amount of overhead in absolute time for 1 mill calls is in the order of 100-500 ms. This therefore does not seem like a problem other than from an academic point of view. However, within such a sub vi you can put an incredible large amount of code doing floating point operation before the total amount of floating point time exceeds the time for one call to that sub vi. What seems like an academic problem is in fact a huge problem when doing floating point math. In fact it is practically impossible in most cases to make a numeric code doing math without loops that takes longer time to execute than it takes to call the code. Below is a snip from a post i did at NI site:

Hello. I did a test as you mentioned. One ordinary sub vi (all debugging etc turned off), one subroutine sub vi, one call by reference to that subroutine and just the diagram in the main program (debugging turned off in the main program). The sub vi was just adding numbers, and it was run i a loop 100000 times. The results in ms for 100000 calls:

Ordinary sub vi: 45

Subroutine sub vi: 11

call by ref: 125

diagram: 1

Then i complicated the sub vi with sine functions, division etc inside a loop that run 1000 times:

Ordinary sub vi: 1850

Subroutine sub vi: 1820 (30-40 less than ordinary sub vi)

call by ref: 1900-1950 (approx 80 more than ordinary sub vi)

diagram: 1850 (approx the same as ordinary sub vi)

All in all i guess this means that it is only the call itself that is affected by the subroutine option. But, the manual and help files say that sub vi call represent only a small overhead that is practically only for the smallest of sub vis. This cannot be true at all. The overhead even for a subroutine sub vi is huge when looking in terms of flop (floating point operation). These numbers show that a call to these different sub vis represent a certain amount of floating point operations:

Ordinary sub vi: 45 floating point operations (labview add, mult etc primitive)

Subroutine sub vi: 11 flop

call by ref: 125 flop

The numbers are actually larger than this since they also contain the overhead for the loop itself.

I also tried different trig, exp functions etc, and they are very efficient and do not cost considerably more than add, mult etc. Therefore, unless the sub vi contains a loop with some hundred iterations at least, making a diagram that cost less than the call to the sub vi itself is almost practically impossible, it will be too much spaghetti at once. 45 "flops" (in labview primitives) is a HUGE diagram and may contain several advanced math function. Other languages have inline functions because of this, and it is very strange that labview does not have this option considering the enormous overhead for sub vi calls in terms of flop.

For applications doing extensive floating point operations the overhead in making function calls makes no sense at all, simply because it is not neccesary. Getting rid of the function call overhead will speed up the application maybe 200 to several thousand percent depending on the amount of looping and the amount of function calls. C/C++ has this inline flag, while FORTRAN has inline subroutines and function by default, and this is not without reason. I have developed a fearly large simulation program in Labview, and i have compared the labview code using pure labview primitives (add, div, mult, subtract etc on vectors) with an optimized C routine. An optimized C routine is approx 150 % faster for pure floating point, but when trying to build sub vis to make the code more readable and easier to maintain, the added overhead makes it a waste of time, even when using the subroutine flag. The penalty is huge. It will be much easier, faster and more maintainable to make a DLL from C even though (presumably) there is som fair amount of overhead in calling that DLL from labview. The reason is mainly that C has this inline functionality. My point is that inline functionality is a very simple trick, but it does wonders for floating point math.

Link to comment

I haven't played much with dynamic code generation, but as far as I know this is more complex than copying and pasting - you have to select only functions and wires (not terminals) and then you have to replace the existing code and link the pasted code to the appropiate place.

As far as I remember wires don't appear properly in the Objects[] property and so probably need to be handled seperately. Also, this will probably make your code really ugly (although if this is only for execution this should matter less). The other thing I would be afraid of is the reliability of thing - you wouldn't want your code to be messed up because the programmer overlooked something or because a scripting feature wasn't fully developed.

If it's that important, it's probably better to do it manually or to write it in a single VI in the first place.

Link to comment
I haven't played much with dynamic code generation, but as far as I know this is more complex than copying and pasting - you have to select only functions and wires (not terminals) and then you have to replace the existing code and link the pasted code to the appropiate place.

You can paste exisiting VIs on to the block diagram of a VI and then wire it up.

Link to comment
If it's that important, it's probably better to do it manually or to write it in a single VI in the first place.

No, it's not that important. Right now the core floating point extensive stuff is programmed in one large chunk. It's fast (fully optimized c code is only approx 150% faster), but not particularly readable although i have added comments all around. Adding too much comments also tends to confuse more than clear up :D . The problem is future modifications adding more complex things, since the complexity now is right on the edge of what is practical without dividing it up in more readable chunks, at least if some other persons is to understand the code within a reasonable amount of time. Doing this with sub vis makes no sense performance vise, so the only alternative is a DLL written in C. Using a DLL is of cource a very good alternative. I had that as a default for sime time, but decided not to simply for the reason of having only one platform and one compiler.

There are two things that could solve this. One thing is a complete overhaul of the formula node, making it a complete C compiler within labview, as it should be IMO :) Right now it is to slow (probably only some scripting thing??) and do not have the ability for making functions, but i use them alot since they are very practical and not too slow for small things. The other alternative is inline functionality within the G compiler. The MathScript nodes of LV8.0 are probably a nice thing if you are used to matlab (which i am not :) ), besides, they are way to slow in both execution and compiling speed to be of any real use for me.

Anyway, I would believe that an inline scripting tool should be fairly simple. You would anly use this for sub vis that othervise would be flagged as subroutines, thus no user intaraction, only strictly specified input and output, and only for simple functions like for instance geometric transformation routines and stuff like that.

Link to comment
You can paste exisiting VIs on to the block diagram of a VI and then wire it up.
I thought the point was to get rid of the subVIs. :nono:
There are two things that could solve this. One thing is a complete overhaul of the formula node, making it a complete C compiler within labview, as it should be IMO :)
Rolf will probably jump in soon enough to tell you that integrating a C compiler into LV is something that would be a huge undertaking and not worth it because that's exactly what LV is not (and you should always listen to Rolf). When he will tell you this he will probably also say that if you're already content to write this in C, you might as well use a real compiler and build the DLL.

Isn't it nice that time is bidirectional and I can tell what will happen in the future? :D

Link to comment

He he :D

I see the point about the C compiler. It will make labview something it is not supposed to be (although the point is more of a religious one than a practical one :) ) But then again, whats the point of a matlab clone (mathScript)? I would think that this is an even greater undertaking and is certainly making LV something it is not :laugh:

Link to comment
I thought the point was to get rid of the subVIs. :nono:

That wasn't my point - I was trying tp point out that scripting is more capable in general than what you said - I should have prefaced my post with: "Although it's not going to help you in this instance, scripting is more capable than..." etc

Link to comment

Wasn't there an undocumented way to select a section of BD and turn it into a so-called "inline" subVI? IIRC, what actually happened was a process similar to the 'create subVI' action, except the code got placed inside a single-frame-sequence which was then shrunk down to the size of a subVI conpane. This, of course, could be copied and pasted.

Does anybody else have a clue what I'm talking about? :blink:

Dave

Link to comment

I played around with some of this a bit trying to make a replace function. Grabbing all the code and sticking it into a frame wouldn't be too hard, but I agree that wiring it back up would be interesting. You could even make it act like an XNode of a sort, though you wouldn't really be able to edit it easily. Rewiring would not look the same as the original wiring half of the time, but it could be done.

You would have to place tunnels on the frame according to where they were on the control pane, but you would have to query the pane to get the right layout. I haven't played with any of that, but I am sure it would be more than interesting. I suppose it could be written to accept just the standard 4x2x2x4 layout.

Just some thoughts...

David

Link to comment
Anyway, I would believe that an inline scripting tool should be fairly simple. You would anly use this for sub vis that othervise would be flagged as subroutines, thus no user intaraction, only strictly specified input and output, and only for simple functions like for instance geometric transformation routines and stuff like that.
Would this inlining tool be run before you execute the VI, or is this something you would run before building an executable?

The problem with creating an inlining tool is that the result would not be reversable unless you could use a rollback mechanism of some sort. So it would probably only be used for a final executable build where you wouldn't care about reversing this action.

Link to comment
He he :D

I see the point about the C compiler. It will make labview something it is not supposed to be (although the point is more of a religious one than a practical one :) ) But then again, whats the point of a matlab clone (mathScript)? I would think that this is an even greater undertaking and is certainly making LV something it is not :laugh:

The idea with the mathscript node is if you have a few functions already written in Matlab, you don't need $5k Matlab licence to run on multiple machines; just cut and paste the matlab code into the mathscript node.

I like it.. its like having Matlab for free on your PC!

Neville.

Link to comment
Would this inlining tool be run before you execute the VI, or is this something you would run before building an executable?

The problem with creating an inlining tool is that the result would not be reversable unless you could use a rollback mechanism of some sort. So it would probably only be used for a final executable build where you wouldn't care about reversing this action.

You are probably right. Each sub vi marked as "inline" would have to be replaced with the equivalent inline code. But if those inline sub vis could be put into a frame and shrunked as mentioned earlier, then i guess it also would be possible to reverse the process? It is however difficult to see that this can be done without ending up with a duplicate set of files, and maybe the end result would just be too messy to weigh up for the increase in speed for anyting but a final executable where the diagram is irrelevant.

I think the increase in speed could be large because a typical structured labview program has several layers of sub vis calling other sub vis and where the sub vis in the lowest hierarchy doesn't really do all that much, sometimes only some kind of wrappers around very simple primitives. The spline interpolation backage in LV8 is a typical example of this.

Link to comment
I thought the point was to get rid of the subVIs. :nono:

Rolf will probably jump in soon enough to tell you that integrating a C compiler into LV is something that would be a huge undertaking and not worth it because that's exactly what LV is not (and you should always listen to Rolf). When he will tell you this he will probably also say that if you're already content to write this in C, you might as well use a real compiler and build the DLL.

Isn't it nice that time is bidirectional and I can tell what will happen in the future? :D

Well, by predicting the future you basically changed the timeline that could lead to such an event and prevented it from happening :D . That is what you get if you try to be smarter than what nowadays physics is willing to allow us mere mortals to be able to do.

But in principle you are right. It's not worth doing because LabVIEW is a compiler. So the only reason to do that would be for performance reason and in order to make really a difference that would require a highly optimized C compiler and that is a business only a few crazy people at Intel and some more in the Gnu CC project are willing to tackle :P

Just as trivia here, if you have the Application Builder you already have a C compiler on your system. It is the LabWindows CVI compiler engine packed into an Active X Automation Server. This is used to compile the C stub wrappers and link the final DLL executable image for DLL targets. The C stub wrappers are the actual functions exported from the DLL and take the stack parameters and translate them into LabVIEW datatypes, then invoke the actual VI through the LabVIEW runtime engine and reverse the data translation for any return values before returning to the caller. But LabWindows CVI never has been and most probably never will be a highly optimized C compiler. And it doesn't have to be because it's strength is in the Test & Measurement integration and the shaving off of a few nanoseconds runtime performance is almost never critical to any application that might ever get created in LabWindows CVI. And if you ever happen to get across a function library that needs this high optimation then you will have to get the Intel C compiler and create an object library that you can link into your project, not really that a high investment actually :)

Rolf Kalbermatter

I think the increase in speed could be large because a typical structured labview program has several layers of sub vis calling other sub vis and where the sub vis in the lowest hierarchy doesn't really do all that much, sometimes only some kind of wrappers around very simple primitives. The spline interpolation backage in LV8 is a typical example of this.

Basically almost every LabVIEW application I have written so far spends probably about 99% of its CPU time waiting for user input events and in doing so causes a real CPU load even on lower end machines of a few %.

A project that I'm working on and off for the last 7 years is about controlling a 5 axis motion system over a DLL, some 20 or so serial devices, communication with 3 more devices over TCP/IP, doing image acquisition for position recognization and barcode decoding, writing data files to disk and when running full speed controlling all these devices more or less in parallel (each device is controlled by its own deamon consisting of a dynamically launched VI and communicating its device states through dynamically instantiated LV2 style globals to the main system) CPU load never peaks higher than about 30% even on an 7 year old Pentium machine running Windows NT4.

And there are similar other applications. I really seldom have seen any of these applications peak even a single time close to 100% CPU time other than when switching from a different application to that application on older low end machines when all the user interfaces need to completely be redrawn.

Rolf Kalbermatter

Link to comment

I think some of you are missing the point here ;) To use applications that do not require fast execution as examples of why fast execution is not needed is completely irrelevant.

Not everybody is working on non critical systems where the processor is basicly idling 99% no matter how you bog down the code. It is those applications that need fast execution, or where fast execution improves overall performance i am talking about. Of cource i can use a DLL, code the whole thing in C or whatever, but that is also completely irrelevant and only serves to dodge away from the issue.

For instance, can anyone give me a good reason why a simple x*sin(t) + y*cos(x) takes almost twice as long to calculate in compiled G than compiled C? An answer like "99% of the time there is no need..." just is not good enough, 1 % for you may be 70% for me. There is no need for an "highly optimized" compiler of any kind to do this, any compiler available will compile faster code than G since these functions are standard functions that are optimized several decades ago in terms of algorithms. I think much of the answer lies in the process of function calls instead of inlining which requires overhead and buffer alocations where clearly neither the overhead or the buffers are needed to complete the functions.

From the manuals i can read that the data flow paradign creates (sometimes unessecary) buffers, and indeed manual optimizing of buffer allocations can speed up the code when working with arrays in particular. But when examining another function, z = sqrt(x*x + y*y), in G and a text based language it becomes clear that it is not the dataflow paradigm that is the cause of the buffer allocations, it is function calling itself and the simple fact that the G compiler does not do any optimization even though the the code is contained in a sub VI, it simply "goes by the book". x*x + y*y will be a parallel execution in G and since they call the *function* x^2 (in LV8) or standard multiplication, it creates two buffers, where clearly one buffer is enough to complete the code, namely the buffer for z.

Link to comment
Basically almost every LabVIEW application I have written so far spends probably about 99% of its CPU time waiting for user input events and in doing so causes a real CPU load even on lower end machines of a few %.

And there are similar other applications. I really seldom have seen any of these applications peak even a single time close to 100% CPU time other than when switching from a different application to that application on older low end machines when all the user interfaces need to completely be redrawn.

Rolf Kalbermatter

I agree, but one area that requires every bit of speed and optimization is image processing. The CVS is woefully underpowered for all but the simplest of vision applications and even with a PXI chassis or desktop PC, speed is always a concern.

It is these applications that can benefit from tweaking of the LV code, or sometimes even a transfer of key parts of the code to a dll seems to speed things up by factors of 20-40%.

It would be nice if NI got LabVIEW RT to work with the new INTEL dual-core processors.. <sigh..>

Another area of improvement would be the screen redraws that you mentioned. Hardware acceleration support for a few graphics cards would really help with graphically intense panels that are sometimes required.. I once had a monitoring app that had about 15 tab sheets with 45 plots all told! All at customer request. The app once slowed dramatically because I put a decoration box around some plots but forgot to "move to back" and that transparent redraw was the final straw on the camel's back.

Neville.

Link to comment
And there are similar other applications. I really seldom have seen any of these applications peak even a single time close to 100% CPU time other than when switching from a different application to that application on older low end machines when all the user interfaces need to completely be redrawn.

I agree with bsvingen that even though many applications don't consume much processor power there is still a need for efficient code for those applications that do consume as much processor power as thery can get. If a computationally demanding data-analysis VI doesn't consume all of the available processor power then there is something wrong with the implementation of either the algorythm or LabVIEW. I myself are using LabVIEW to analyze huge amounts of data and it is really slow. However it would take even more time to code all those analyses in C instead of G ;)

Just as trivia here, if you have the Application Builder you already have a C compiler on your system. It is the LabWindows CVI compiler engine packed into an Active X Automation Server. This is used to compile the C stub wrappers and link the final DLL executable image for DLL targets. The C stub wrappers are the actual functions exported from the DLL and take the stack parameters and translate them into LabVIEW datatypes, then invoke the actual VI through the LabVIEW runtime engine and reverse the data translation for any return values before returning to the caller. But LabWindows CVI never has been and most probably never will be a highly optimized C compiler. And it doesn't have to be because it's strength is in the Test & Measurement integration and the shaving off of a few nanoseconds runtime performance is almost never critical to any application that might ever get created in LabWindows CVI. And if you ever happen to get across a function library that needs this high optimation then you will have to get the Intel C compiler and create an object library that you can link into your project, not really that a high investment actually :)

I'm not familiar with LabWindows but as far as I understand if the generated C code is ansi compilant then it could be compiled with any ansi compilant C compiler. So it should be possible to use some other C compiler instead of LabWindows CVI in theory. Intel and PathScale compiler should be very good but new versions of Visual C++ and Gnu compiler are not bad either. Why this option of using some other compiler instead of LabWindows CVI couldn't be possible. All it requires is will from NI to put some effort on it. There could be a new High Performance LabVIEW toolkit that would use high performance compilers from other vendors. Of course it can be that LabVIEW generates code that is far from ANSI C and only LabWindows could be used to compile it.

Link to comment
I myself are using LabVIEW to analyze huge amounts of data and it is really slow. However it would take even more time to code all those analyses in C instead of G ;)

Exactly, this is my experience as well :) But then you start to become more and more irritating when it each dataset takes 20 minutes instead of 5 :beer:

Link to comment
Why this option of using some other compiler instead of LabWindows CVI couldn't be possible. All it requires is will from NI to put some effort on it. There could be a new High Performance LabVIEW toolkit that would use high performance compilers from other vendors. Of course it can be that LabVIEW generates code that is far from ANSI C and only LabWindows could be used to compile it.
I believe you've misunderstood Rolf on this point.

LV does not generate C code, but machine code. There are some exceptions (like LV embedded or (I think) the PDA module), but not the PC version.

If I understand Rolf's explanation correctly, he meant that if you build your VI as a DLL instead of an EXE, LV will use the CVI RTE to generate parts of the DLL. At no time is the LV code translated to C.

Link to comment

I think the basics of what you are asking for can be done, as a one way operation. Several of the peices required are available here on the forums. Not the whole enchilada, but the meat is here, the tortillas there.

Here are a couple of starting points:

Self-reproducing Code

This shows copying code from one VI (in this case itself, beware of this, it can be dangerous to your computer's health) into another VI.

Tunnel Wiring Wizard (unlocked versions)

This one shows getting references to various objects and then wiring inbetween them

Set Alternating Diagram Colors

This little gem by our Founding Forum Father (The FFF) uses recursion to traverse through every structure and get a reference to every object on a block diagram. With minor modifications you can use this as the framework to search through your target VI looking for your inline constants, etc, and use the techniques in the other stuff above to do the replacement part of your problem.

If you do this, it would be interesting to me and I think to the group, to see you post an example and some benchmarks showing what some of your performance results were.

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.