Announcement

Collapse
No announcement yet.

Please implement Short-Circuit evaluation for Blueprint

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #46
    Originally posted by John Alcatraz View Post
    Haha

    Thanks very much luny, but I think I'm not much of a prophet, Epic already announced quite a while ago that they work on a BP->C++ converter, so I don't predict anything, I just repeat what Epic said I think it's very³ experimental in 4.11 and should be usable in 4.12.

    I am absolutely not saying that BP is a complete waste of time. Even with the BP->C++ converter, you will still write BP. It's just that once you package your project, the engine automatically converts your BP code into C++ code, so you no longer have the worse performance from Blueprints (like 10 times slower than C++).

    So you should still learn Blueprint
    I believe the BP to C++ conversion would not change anything. I don't think Blueprint's AND and C++'s "AND" runs the same way ( obviously form the lack of SC).
    I haven't tried the nativize BP thing recently but If i remember correctly, all it does is to re-write all the BP function in C++ using K2 nodes ( which it he Blueprint node anyway ) .
    Developer at AmmoboxStudios.



    Eximius ( An FPS/RTS Hybrid )

    Comment


      #47
      Originally posted by SaxonRah View Post
      I think I have an idea how to fix this problem. Temporary variables and the comma operator!
      Instead of "return A && B;" you should write
      "bool ABool, BBool;
      return (ABool=A), (BBool=B), (ABool && BBool);
      "

      I think this would make it so that it would tell the compiler to force a sequence of actions.
      I could have sworn i submitted this as a pull request. Maybe i didn't for a reason i don't remember anymore. But this should theoretically fix/add the SC
      Youtube
      Machine Learning C++ Plugin
      Lindenmayer System C++ Plugin

      Comment


        #48
        Definitely an interesting reaction to a pretty standard part of C/C++ and C# (and probably many others) - I would hope that BP would end up working this way eventually!

        [MENTION=155]TheJamsh[/MENTION] - I tend to do use this in C++ when I want an elegant way to only perform expensive but rare checks only when needed. If you've got two conditions, where one is unlikely to to be true but is cheap, and the other is likely to be true but expensive, you can put the cheap one first, which fails most of the time, and the AND will almost never try the expensive check. I love it

        +1

        Comment


          #49
          +1 for Short circuit evaluation

          Comment


            #50
            +1 on this feature! I am just learning BP, but I come from a background in other languages, and I was pretty shocked that this basic optimization was missing.

            Comment


              #51
              Originally posted by SaxonRah View Post
              I could have sworn i submitted this as a pull request. Maybe i didn't for a reason i don't remember anymore. But this should theoretically fix/add the SC
              Where would you implement to full code btw? does it interfered with the Blueprint Ubergraph compiler?
              Please Re-submit. Am sure looking forward for it.
              Developer at AmmoboxStudios.



              Eximius ( An FPS/RTS Hybrid )

              Comment


                #52
                I upvote the shortcircuit evaluation, I think this is a basic feature of most of the well known programming language. Besides, I'll add that the select node should work the same way.

                Here is my interpretation of the select node in C++ (I don't know if it is the most intuitive) :

                // Supposing this is, into blueprint, a member variable

                TArray<float> MyArray;

                // The nodes chain for select A/B

                float funcA() { return 0.0f; } // getting zero.
                float funcB() { MyArray[0]; } // getting the first element.

                // My representation of the select node

                float SelectFloat( bool pickA )
                {
                if (pick A)
                return funcA;
                else
                return funcB;
                }

                // Now if I do this, I systematically get warnings

                float MyFloat = SelectFloat(MyArray.IsEmpty());



                All of this code can be done with pure only blueprint node, so it does not seem obvious to me how redesign my blueprint code for not having the warning.
                Last edited by Jo_sky; 08-18-2016, 10:12 AM.

                Comment


                  #53
                  Upvote this, it is a pity blueprint does not have this feature, can simplify and speedup development a lot.
                  Wanted to see a Blueprint a good rich functional language with lazy evaluation of nodes, but looks like it is not. I am disappointed.

                  Yes I agree if you are an artist you have no idea of such feature and you don;t care, but if a programmer start to use Blueprint - everything is very unfamiliar. And hope it is better to teach nonprogrammers of good practices, not of bad one. I don't know any good programming language without that feature.

                  Comment


                    #54
                    The only reason to do short circuit evaluation is for performance.
                    For correctness / side effects, you have the white execution lines, which you already have control over.

                    If you add short-circuit evaluation, then you probably also should take advantage of the "pure" marker, to not re-evalute a "pure" function that has already been evaluated.
                    And you should not update the value that's returned by a variable node when it's re-used later in the graph.
                    This would allow you to treat the entire graph as lazily evaluated, and do aggressive evaluation graph transformations, that could actually lead to real performance benefits.
                    (See functional language optimization, like ML and Haskell, for how this can be effectively implemented.)

                    Now, the draw-back is that this would be a semantics-changing change. It would actually change the semantics to be better, in my opinion, but it would have a non-small impact on some existing scripts.
                    I think the benefits might actually outweigh that cost, if it's pre-announced and handled in a good way (perhaps some command that could turn a blueprint graph into its older sibling by inserting the correct read/write/duplicate nodes.)

                    This is the most confusing part of blueprints to me, and it's also the saddest, as it precludes so many possible optimizations:

                    Click image for larger version

Name:	blueprint.png
Views:	1
Size:	151.9 KB
ID:	1120866

                    I think it should print the same value twice, as the data is sourced from the same node, but it prints the value and then the incremented value.
                    I think fixing this would be worth it (and would give much better defined semantics to short-circuit evaluation!)

                    Comment


                      #55
                      My thinking may be affected by having got used to how blueprints work, but first and foremost I'm a programmer, and I find the idea of that graph printing the initial value twice extremely counter-intuitive.

                      You seem to essentially be saying that all nodes be executable nodes under the hood, just that the 'pure' ones be implicitly plugged into the execution chain at the point that one of their outputs is first used? What about when a getter node was used from disjoint (asynchronous) execution paths in an event graph - when does it get reevaluated? Or behaviour changing as a result of cutting a value wire in a different section of the graph? I think this would introduce far more issues than it solved.

                      I agree there are issues in BP with unexpected reevaluations of pure nodes that can lead to performance concerns, but personally I don't think BP performance should be a top priority. It was never intended as a full substitute for C++ anyway.

                      For me a bigger BP issue is the fact that node pins in event graphs behave like class scope variables. This leads to at least two issues - 1. recursion in event graphs is a no-no; 2. a blueprint will (generally without user intention) retain a strong reference to a UObject that at any point passed through a pin on its event graph, until either the pin value is overwritten, or the blueprint instance is destroyed. The latter had me stumped for a fair while, and could in some cases cause a significant memory/resource problem.

                      Comment


                        #56
                        Hey there!

                        I've looked over the thread here and I can see where there are opinions of varying amounts of for and against. I went ahead and put this discussion into a report to be further examined. No promises one way or the other on how it will turn out, but please keep up the feedback and reasoning, as it really helps our teams see what you want improved and how.

                        Thanks!
                        Twitch /unrealalexander| Twitter @UnrealAlexander
                        How to report a bug? | Installation & Setup issues?
                        Call me to a thread by posting this: [MENTION]Alexander Paschall[/MENTION]

                        Comment


                          #57
                          Originally posted by Alexander Paschall View Post
                          Hey there!

                          I've looked over the thread here and I can see where there are opinions of varying amounts of for and against. I went ahead and put this discussion into a report to be further examined. No promises one way or the other on how it will turn out, but please keep up the feedback and reasoning, as it really helps our teams see what you want improved and how.

                          Thanks!
                          Hello, Alexander, first big thanks for hosting so cool and useful Twitch life streams. They are very enjoyable to watch.

                          For me some simple rules would be enough.
                          1) Shortcircuiting is a must for selecting which pure node should be run.
                          2) When execution flow goes to impure next node it gathers all connected needed pure nodes through it inputs and execute them if needed (that why shortcircuiting is a must feature, it can be used to cutoff unneeded pure nodes on that step) - (not: that is called lazy evaluation, many functional languages have it. And Blueprint in general look like one of them)

                          All other optimizations are not so important. But maybe some pure node result caching can be implemented - still here is a problem, pure nodes values can be affected by other impure nodes executed before (like in jwatte example), and even Pure nodes can affect state of other pure nodes so caching optimizations here are quite impossible without further complicating the blueprint language. And that why second rule is important - pure nodes should be calculated just before they are used, otherwise some side effects of previous impure nodes can be lost (but actually I have not met that situation yet, that mean it work that way now, but I don't have habit to modify objects in pure nodes, and actually it look like that some pure nodes are calculated long before they are used)

                          The idea here is that Pure nodes are not only property getters, they even can access some unavailable components (if some flags are not set, and select node was used) or even can make some (relatively) complex computations. Shortcircuiting is a very cheap and natural concept to understand, I think many people think it works by default without knowing it actually does not work. Select node semantics just tell that you are selecting which pure node you are accessing, accessing them all and than getting appropriate value is not what some can expect.

                          So that code will print only "false" string, once, now it prints "false" and "true"

                          Click image for larger version

Name:	d4dcb1318ef747418e097653b43a55e4.png
Views:	1
Size:	42.0 KB
ID:	1122522
                          Click image for larger version

Name:	6cec5d528c221546e6cb31e1c97e369c.png
Views:	1
Size:	58.8 KB
ID:	1122525

                          And that code should print only "Option2Log" string, not all "Option0Log", "Option1Log", "Option2Log"

                          Click image for larger version

Name:	8a48d418312d4ac36cafe85826724a65.png
Views:	1
Size:	61.8 KB
ID:	1122523
                          Click image for larger version

Name:	c8d2bbfecb83f8137f09016da21731db.png
Views:	1
Size:	77.5 KB
ID:	1122524


                          Originally posted by jwatte View Post
                          I think it should print the same value twice, as the data is sourced from the same node, but it prints the value and then the incremented value.
                          I think fixing this would be worth it (and would give much better defined semantics to short-circuit evaluation!)
                          I disagree with you in this, while yes, in one case some form of wiring can be used as optimization, in your example it is quite clear that value have changed between two prints, and it is expected to print different values.
                          Also shortcircuiting can be used not only for optimization, but also for evading unneeded side effects. (like log printing, casting, accessing unavailable objects)

                          On the other hand reroute nodes can be used as a hint for the need of caching the pure value (actually like that is done with impure node results)

                          Click image for larger version

Name:	1e27c08bcdbd0c96fff0759b9ce36faf.png
Views:	1
Size:	86.7 KB
ID:	1122526

                          Like here Position can be cached between two Use Position calls, on the other hand if we don't need caching we can call that node twice.

                          Click image for larger version

Name:	5da62b8096d8f5d36ac1945ad0cdf09f.png
Views:	1
Size:	89.1 KB
ID:	1122527

                          And I would like to see such optimization. But it can break a lot of existing code. And the whole caching logic can be unclear for nonprogrammers or blueprint firstcommers.


                          PS. Also there is some cryptic Const flag on function nodes. And I don't know why is it different from Pure and what for is it in general. (In functional languages "pure" means that function is cons in some way and does not have any side effects - like changing states of any object. In blueprint Pure is only the way node is represented)

                          Comment


                            #58
                            If pure nodes are re-evaluated on access, what then is the semantics of "pure"?
                            Does "pure" then mean "ha ha just kidding, re-evaluated at some points in the control flow that are not obvious!"
                            So, in essence, the only thing "pure" actually does is remove some implicit control flow (white) wires, at the expense of then not being obvious about when those (implicit) wires actually get there?
                            If so, the word "pure" should probably be changed to "implicit" ...

                            Comment


                              #59
                              ^"Pure" actually means it does not change any variables.

                              I myself am for short-circuit implementation in Blueprints.
                              Last edited by Raildex_; 02-04-2017, 01:35 PM.

                              Comment


                                #60
                                I've always wanted this behavior. For my Generic Shooter asset, there are tons of cases where the performance gain is real.

                                I ended up making a set of really ugly macros called XAndSeq, so I can easily 'and sequence' or 'ghetto short circuit' conditionals. That way I don't have branches everywhere.

                                Attached Files

                                Comment

                                Working...
                                X