Thursday, March 19, 2009

Why Are You Still Using Loops in Your Functional Globals?

Are you still creating Functional Globals (a.k.a. LV2-style globals) that look like this?

If you're programming in LabVIEW 8.5 or later, do this instead!

In LabVIEW 8.5, Feedback Nodes gained the ability to live on the top level diagram of a VI... no loop required. This feature gives us the identical functionality of a single-iteration loop with an uninitialized shift register. And let's be honest here...the uninitialized shift register on a single-iteration loop is kind of a hack.

Not only does the Feedback Node clean up our diagrams, but it is slightly faster (sometimes by about 5-10%) than a loop with an uninitialized shift register. This is largely due to the removal of loop overhead.

So get over your Feedback Node (and backwards wire) hangups like I did and make your functional globals more efficient!


  1. I love the feedback node. I didn't use it in 7.0 where it was still immature, but in 8.6 I use it all the time, mainly due to two improvements:

    1. The ability to change its direction. When it's pointing to the right, code which uses it usually becomes much more readable. To be fair, this may have been around in 7.0 too, but I'm not sure.

    2. The ability to place it inside a structure and initialize it from several layers out. This is essentially a buffer which is held inside a single case of a case structure.

    I don't really use the way you posted for a simple reason - I find the loop method to be more readable. When you have to start figuring out how it works and when, it's easier to just use where it's much clearer (to me) which data is being used, when it's initialized, etc.

    This might simply be a matter of conventions, but I get the distinct feeling that it isn't and that you would REALLY need to get used to that notation before you find it natural. And to be honest, the loop doesn't take up THAT much space.

    I think I'll try using this method a bit to see how it works out and then I'll be able to tell.

  2. Would there be any penalty for using this method to create FG's on the CLD exam?

    I don't have a problem with this method but it does break convention. Especially the idea of maintaining left to right data flow.

  3. Yair: Let me know if it becomes more natural to you after you've tried it out. For me, I always felt like a hack using the single-iteration loop method, so it was a very welcome and natural progression for me.

    FLAnatic: I used the Feedback Node for my functional globals on both the CLD and the CLA, along with comments on the diagram explaining my rationale.

  4. Thanks for the information, Darren. You're right that the While Loop adds extra complexity that's not needed for Functional Globals, and the performance benefit is great, too! I wonder if the performance benefit is only significant for small data structures in the FN/SR or if the benefits are for large data structures, too.

  5. Jim: I just did a quick test with some relatively simple data types, and some more complex data types, and I'm seeing similar performance improvements (on the order of a few percent) when using the Feedback Node over the traditional approach.

  6. Darren: while you're testing, can you see if there's a similar (few percent) performance improvement for very large data (not just complexity, but actual data size)? The reason that I ask is that that data size is one of the major performance issues with "by reference" frameworks.

  7. a. I checked, and LV 7.0 did not have the change direction feature.
    b. Stephen did say once (here) that USR globals have some optimization.
    c. I tried converting some globals to feedback nodes, but I didn't really like it. Changing the direction on the nodes made it better (as shown in the top image here), but I find that the nodes aren't visible enough this way. For someone who knows LV2 globs, the pattern sticks right out.

    It might be nice if we had the ability to split the feedback node into two, as we can do today with locals. Maybe like this. The local method works (as shown in the previous image), but has its own disadvantages and I never used it.

  8. And here are a couple of alternate renditions.

  9. Yair: Another alternative for improving the feedback node readability could be changing the graphic of the wire that is going through the feedback node in some way to show that the data is being fed back.

    I guess this can be a difficult task in itself since this wire can also branch to non feedback nodes as well.

  10. The more I think about it, the more I like my second suggestion (the one with the curving arrows). We could have it as a right click option on a feedback node (i.e. "Split Node").

    What do others think? Darren, is there any way of giving this more weight as a feature request?

  11. Jim: I'm still seeing very slight performance gains with the Feedback Node when dealing with large data sets, but I see the gain become smaller as the data set gets larger. This lends credence to my earlier assertion that the main performance benefit has to do with eliminating loop overhead. As the data sets get larger, the loop overhead becomes a smaller and smaller part of the overall execution time.

    Yair: All of my functional globals have "FG" in their VI name, and I typically keep them all in the same folder when developing an app. They also have different colored icons to set them apart on block diagrams. And when I use Feedback Nodes to store data in the functional global, the feedback nodes are always at the very top of the diagram. All of these factors together make functional globals very obvious in my code.

    As for your feature suggestion, I really don't see enough of a difference between your mockups and uninitialized shift registers. Honestly, a feedback node stands out more to me on the diagram than two separate nodes would, especially if the feedback nodes are consistently placed between diagrams. Nevertheless, feel free to submit it as a suggestion.

  12. Darren: Thanks for the performance info on data size. That's what I expected, too.

  13. Let's not forget my favorite feature of the feedback node compared to a shift regsiter: The option to "globally initialize" a standalone feedback node. This means they can easily be initialized with good default data even inside a FGV, eliminating e.g. the possible need for a "first run?" primitive and such.

  14. I tried to benchmark this (LV8.6) by taking an "AE" who had two "actions" (true and false) and each action was to invert the current state. In one AE, the current value of the boolean is stored in a USR and in the other I removed the single-cycle while loop and replaced the shift register with a feed-back node.
    I used sequence structure and used "get time in seconds" converted to a double (which seems by the numbers it returns to give better resolution (useconds) than the tick count (mseconds). Got start time, used for-loop with constant wired to N and called my "AE", got the end time (after N iterations) and compared.

    I could not find any significant difference between the two methods. If anything I found that the USR method tended to have a lower standard deviation than the feed-back node, indicating more consistent performance.

    Since the "buffer" only holds a single boolean value, the question of size/complexity of the data should be minimized and the effect of the loop-overhead maximized.

    So, since all of you seemingly find a 5 to 10% improvement, I'm feeling silly for not being able to reproduce this?! If anyone has example code posted on a forum, could I please have a link to it posted here? Or here

    Note that in the thread above, the USR comes in at "0.51" and the feed-back at "0.62" so assuming those are times, their benchmark shows USR to be faster???

  15. I have posted a response on the original NI Forums thread here.