LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
Intaris

Explicit Constant Folding

Status: New

As LabVIEW evolves more and more, the compiler takes over an awful lot of code optimisation for us.  This leads us to situations where relatively large and important pieces of code can be evaluated at compile time and constant folded which can greatly aid execution speed.  This is good.

 

Constant folding can be a great aid when programming but at the moment, it's usage is a bit "hit and miss" due to the opaqueness of the process.  We already have constant folding highlighting, which really helps things (even if the feedback is sometimes very hard to understand).  But this doesn't always give us enough feedback.

 

What I would like is the option to declare a portion of code as "Requires constant folding" (like a "Precompile" structure).  In this way, I can, as a programmer, designate some code which is meant to be evaluated at compile time.  If the compiler is unable to constant fold this code, then the VI should be broken.  My motivations are three-fold.

  1. Sometimes we want to specifically make use of the constant folding capabilities of the compiler, but a small change can result in the code no longer being constant folded.  I would like explicit feedback when code I want constant folded is not constant foldable.
  2. I have no idea whether code complexity has an effect on the ability to constant fold.  Other compiler optimisations (Like unbundle-unbundle inplaceness) are dependent on code complexity.  Explicit declaration is not code complexity dependent.
  3. When looking at FPGA designs, the ability to perform constant folding of data otherwise requiring resources or affecting performance is very powerful.  In such a "Constant folding" code, we could also allow mathematical functions to be used which are otherwise not supported on the target (max/min of an array in a timed loop for example), or creating default data for an array (to be used as Block RAM) based on an existing equation where constants are defined as DBL.

 

One example of FPGA code is automatic latency balancing of several parameter pathways into a process where the code accepts abstract parameter objects whose latency is queried via a dynamic dispatch VI which simply returns a constant.  I use dependency injection to tell the sub-VIs which communication pathways they are being given and they can then query the latency and do some static timing calculations for the delays required on different pathways.  Tests have shown that this is constant folded and that it is thus possible to write very robust FPGA code which auto-adjusts request indices for parameters in multiplexed code.  At the moment, things seem to work but the ability to specifically designate such code as being constant folded would be welcome to make sure I don't accidentally produce a version which doesn't actually return a constant (and my compiles fail, I get timing errors, or just over-use resources)....  In the code below, all of the code circled in blue is constant-folded when compiling the FPGA code.  In the sub-VIs I have to do some awkward calculations because certain functioanlity is not available on FPGA.  By defining this code as requiring explicit constant folding, I could theoretically utilise the full palette of LV functions and also be guaranteed a compile error (LabVIEW error, not Xilinx) if the code thus designated can not be constant folded.

 

2016-09-15 10_13_00.png

 

So in a way, it's similar to the In place element structure which, when all goes well, should not be needed but there are cases (I've run into some myself) where either small changes in code can make the desired operation impossible or where the code complexity can cause the optimisation to not be performed.  As such, it is still required at times to explicitly designate some code paths as being In-Place.  I would like to have the same functionality for "Constant folding".

23 Comments
Intaris
Proven Zealot

Of course one can at least run such optimisations outside of timed loops so that loops and so forth can be used, but I always have a weird feeling in my stomach doing this because I need to verify that the code has actually been constant folded by compiling a version with and without the adaptive code and observing the resource utilisation.

 

That gives me another idea.

Darren
Proven Zealot

So if we had a function that broke your VI if anything non-constant-folded was wired to its input, would that satisfy your idea request? Something like this?

 

c.png

Intaris
Proven Zealot

Something like that, yes.

 

But it would need to work with dynamic dispatch on FPGA.

Intaris
Proven Zealot

I've thought a bit more about Darren's suggestion and it only goes part of the way to allowing what I was thinking of.  This would still limit the availability of functions to those already supported on the target, no Array min and max on FPGA for example.  No VI Server parsing (for log creation for example).

 

If we could have a structure which allowed all functions to be used which are available on the development machine but which must output either no values (a pre-compile function for writing environment data to file for example) or constant values, this would hit the spot.  So ensuring only constant output is only part of the idea.

AristosQueue (NI)
NI Employee (retired)

Intaris: 

I liked this idea as you originally posted it, but I'm uncomfortable with the clarification you just posted.

 

Suppose you have a double "1.1" and a double "1.2" wired to an Equal node and you say "must be constant". On desktop, that would compute to "false". On a target where floating-point is coerced to integers, those would convert to "1" and "1" and compute to "true".

 

This is a forced example -- I'm not even sure if we have any targets that coerce floats that way. But my point is that the code itself can be massaged for a given target and running in that target's context would result in different values of the constant.

 

Is that sort of difference in behavior desirable? Acceptable? Explainable?

Intaris
Proven Zealot

Ah, but it's exactly the "coerced to integers" which I am trying to clarify.  I see no reason if the code is required to be constant-folded that it should need to coerce at all, why not simply parse it as floating point.  Since it'll be constant folded, it is never actually FPGA code in the first place, only the RESULT will ever be present on FPGA.  The compiler is free to execute it as it requires.  It's like a mini "My Computer" target within the source code.  The code within the structure should NOT be tied to the target on which the resulting constant will be used.

 

I realise my posting of this idea is completely detached from any effort such a structure would require.

 

I suppose it would amount to a "Run VI before compiling" option in current builds, but with the added bonus of being defined right there in the source code and being already in the right place instead of having to use scripting to find and replace constants (OK, one could use constants wrapped in sub-VIs).

AristosQueue (NI)
NI Employee (retired)

> I see no reason if the code is required to be constant-folded that it should need to

> coerce at all, why not simply parse it as floating point. 

 

I guess that's my point -- whose rules for type propagation should control the computing of the constant value? You want the desktop rules. Is that always desirable? It strikes me as very odd to have a piece of code whose RESULT is on the target but whose value was computed by rules that do not govern that target. I'm not saying it is wrong, just that it is very strange to me, and I'm concerned that it wouldn't be desirable in many cases.

 

> The code within the structure should NOT be tied to the target on which the resulting constant will be used.

 

And that's exactly what I'm questioning. 🙂 I definitely understand what you're asking for. I'm just very unsure that it is a good idea.

 

A secondary concern: there would be no way to debug such a thing because the code would be run exclusively by the compiler, so it is already done by the time the Run button is pushed. We might need two different Run buttons, or a run button on the structure itself to just execute that region of code.

 

This secondary request definitely adds significant complexity to the request. Might be the right thing to do, but I'd like to hear from some more customers.

AristosQueue (NI)
NI Employee (retired)

-- even more complicated... since the value of the constant would depend on what machine did the compilation in the first place... if two desktop targets have different behaviors... ug. We don't have any cases like that today that I know of, but there are things I can see on the horizon that might raise issues. We'd need a canonical "this is how the compiler executes these nodes".

 

-- On second thought, I can think of one... a Flatten To String that uses "native, host order" for byte ordering. We'd need to pick a standard endianness for the compiler to use in all cases so that it doesn't matter who does the flattening. Yes, that's an edge case, no question, but it is the sort of thing that a feature like this would have to take into account. Not a showstopper, I'm just looking for edge/corner cases.

Intaris
Proven Zealot

Will the LabVIEW IDE be ported to non x86 processors?

AristosQueue (NI)
NI Employee (retired)

It has been in the past. It is not at the moment. I have no idea about the future. Hardware diffs, OS diffs... any environmental setting that is different from the target that affects runtime behavior would be a concern for me.

 

I'm not saying this is a bad idea. I am saying I'd want that thoroughly explored before committing to it as a good idea. 🙂