LabVIEW Idea Exchange

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

New in-place element structure option - class property node read/write - to ensure access to parent node private data is done in-place

Status: Completed
Available in LabVIEW 2013

I love lvoop but I hate that you have to suffer a huge performance hit when accessing parent class private data via access vi's, especially if it is large datastructures.  

 

As access vi's can also be invoked using property nodes, make a read/write property node pair accessible via an IPES - this will instruct the compiler that this access to the parent class' data should be done in-place.

26 Comments
AnthonV
Active Participant

A question about all my existing classes and their access functions (with property nodes) - would it be sufficient then if I edit each one and remove the error/noerror case structure, but leave the error in error out control and indicator and simply wire control to indicator - this doesn't break any of my calling vi's but removes the case structure.

AristosQueue (NI)
NI Employee (retired)

No that would not work because inlining would then add a sequence structure around the (un)bundle node to guarantee that the (un)bundle happened before whatever was downstream on the error wire. Being inside a sequence structure would break the inplaceness. 

 

I caution folks against doing that for other reasons -- not only is it unusual practice for a node to return non-default outputs when an error goes into the node (unusual but sometimes acceptable), the presence of the error terminals encourages wiring the error through those nodes which can do nothing for your diagrams other than make them less efficient, for two reasons. Reason 1 is just that LV has to route that signal through another VI. Reason 2 is because it encourages programmers to serialize operations that have no data dependencies on each other.

AristosQueue (NI)
NI Employee (retired)

I should note also that really good APIs would not have the Object Out terminal on property read VIs, only on write VIs, for the same "encourages over serialization" reasoning. I used to think this was ok practice, but after years of observing user wiring patterns, I've come to realize that any by-value type being passed through a node that does not modify that value is a bad idea.

AnthonV
Active Participant

So you are proposing the following to all who are interested in the performance (speed specifically) when accessing parent class data:

1) When creating an Read access function to a class' private data, don't use the provided menu option as it wires the object through the vi.  Rather simply create a new vi with only one input terminal (the input object) and one output terminal (the data that was unbundled).  Don't use property nodes and done add error terminals even if they are simply wired through.  The Write access function would have 3 terminals, object in and out and data in.

2) In the calling vi, to ensure inplaceness, these two vi's (matching read and write vi's) must be inside the same frame, don't even put them in different frames of a sequence diagram as this would break the inplaceness.

3) To access multiple data elements of a class, in the calling vi branch the object to several of the Read accessor vi's and for each one have a matching Write accessor vi - hmm - so here I have to wire the object serially through the Write vi's don't I?  Does the order now matter for inplaceness?

 

My original idea which is to have a new IPES option to read/write parent data seems a bit neater?

AristosQueue (NI)
NI Employee (retired)

1) Not quite. Keep using the menu option but delete the output terminal afterward. It's still lots easier to work from the template and remove that one output than to build it yourself. But do use the option that does not have error terminals (which will rule out using it from the property node anyway I think -- I didn't write that feature and don't have the details of that interaction right now).

2) Yes. If you could draw an IPE with those as the border nodes, then they're in a good place. An IPE can't cross structure boundaries because it is a structure itself.
3) If you just want to read properties, yes, fan out to all the properties you want to read. If you want to read and then write a single property and then read and then write another single property, make the reads serial after each of the previous writes. That's fine. But if you want to read multiple properties, modify them all and then write them back, you need a method on the class that reads all those properties in a single unbundle node and a matching write. This is an area where LV's compiler may improve in the future if we can teach it to fuse multiple unbundles and bundles.

 

Your original idea is dead on arrival because it requires making private data public.

AnthonV
Active Participant

If my original idea of creating IPES read/write nodes for parent class data only applies to parent class public data (data that is already visible via accessor vi's) then hopefully it still has some potential?  It would make simultaneous reading and writing multiple data elements a lot simpler.

 

AristosQueue (NI)
NI Employee (retired)

Well... that gets into a whole other problem... if you go through the accessor VIs, there's no way that the IPE can promise to meet its guarantees. It would depend upon the content of the VIs themselves. An accessor VI might compute values. Or it might range check values on write.

 

Binding those into the IPE would be conditional on analyzing the block diagrams of the VIs and deciding "this is nothing more than an unbundle/bundle node" and breaking the IPE if it was anything else. But doing that would violate one of the key reasons for using the accessors instead of public data -- that it gives you a place for validating and debugging reads/writes without breaking caller code. As a result, using the accessors as subVIs and letting the compiler discover the optimization works but using the IPE and asking LV to guarantee the optimization doesn't.

 

To truly get the optimizations you are asking for, you need a whole hierarchy optimizer, which LV has discussed building from time to time for the Desktop and RT systems (we already have that for FPGA). Rather than compile each VI as an individual VI, you build a single executable out of all the VIs in the hiearchy (with cut points for any VIs that are flagged as "dynamically loaded" or "dynamically called").

AnthonV
Active Participant

I can see things are getting complicated. Ill give your suggestions of a multiple element write vi a go once I have 2013. 

Until then I might try replacing all my parent class data members with dvrs of those members. This will allow me to use any combination of parent data in the child class and there will only be a small performance hit because of the dvr ipes dereferencing. For large data members this should be ok, but wouldnt be a as good as your suggestions for absolute performance. 

It also makes the parents methods a bit unconventional-looking when it is accessing its own data.

Which session at niweek would you suggest I attend if im interested in the compiler, performance an lvoop?

 

 

AristosQueue (NI)
NI Employee (retired)

Um... Anthon, using the DVR for just parts of the class changes the entire syntax of your classes and is generally a disaster in the making. I generally advise people against that approach. Making a class partially by value and partially by reference generally results in some situation where you  needed to make a copy and so you just did a simple wire fork but since you didn't call a formal copy method, your DVR ends up shared while the ret of your data isn't shared. Bad juju.

 

I don't know the sessions at NIWeek this year. You'll have to look through the program and make your own decisions. Most of my NIWeek time is taken up with other meetings so I won't be in many sessions. The only presentation I am doing this year is on Thursday at 11am is in the Tech Theater and has nothing to do with LVOOP.

AnthonV
Active Participant

Yes not ideal at all but the only way (apart from SEQ I suppose) to access large parent data efficiently?