Jump to content

Reentrant LVOOP Method VIs


Recommended Posts

When developers release their reusable LVOOP libraries, do they make all their method VIs reentrant?

My other reusable code (functions etc... ) are reentrant unless for a specific reason. But when I create applications that use classes, on a whole, I don't normally have to make those classes' methods reentrant, and I don't feel I have any performance penalties (on a PC target) because of this decision. And these reusable classes are usually a replacement for those classes.

One of the quirks of LVOOP is that the dynamic dispatch code must have the same reentrancy level throughout the hierarchy. So the developer who is extending the class is forced to use reentrancy on those overriding methods in their application code.

I am trying to weigh up the need for performance versus ease of debugging (as it might not be just me who is using them). I know you can probes wires outside of the class normally, debug clones with breakpoints, and unit tests should be used to validate code etc... so is this really a big issue?

Anyone got anyone thoughts on this?

Cheers

JG

Link to comment

If it works for VIs generally, then you should keep the same policy for methods of the class. Classes are just a system for organizing the VIs you'd write anyway. And being reentrant does mean all overrides have to be reentrant, but that shouldn't be a problem. For one thing, method overrides are generally adjustments to the parent's behavior, so if the parent didn't need synchronization, neither will the override. And if it really needs synchronization, the override can call a subVI.

  • Like 1
Link to comment

If it works for VIs generally, then you should keep the same policy for methods of the class. Classes are just a system for organizing the VIs you'd write anyway. And being reentrant does mean all overrides have to be reentrant, but that shouldn't be a problem. For one thing, method overrides are generally adjustments to the parent's behavior, so if the parent didn't need synchronization, neither will the override. And if it really needs synchronization, the override can call a subVI.

Thanks for your reply AQ.

As always I like to know what others are doing to make sure I am on the right track.

I will keep as is, and stick with reentrancy.

Link to comment

You should note that reentrancy does not necessarily mean improved performance. When you have reentrant VIs, there needs to be memory allocation and book keeping for each instance, something which will have a greater impact the more reentrant VIs you have (although I don't know how pronounced this effect is). This is supposed to be mitigated if you use the shared pool for clones option available in 8.5 and later (since only N instances are allocated for each reentrant VI). Obviously, you also won't gain performance if your non-reentrant VIs aren't actually blocking. I'm assuming that the execution trace toolkit NI sells should help you with seeing which VIs are bottlenecks, although the standard profiling tools might also be enough if you simply look at the number of runs.

Link to comment

You should note that reentrancy does not necessarily mean improved performance. When you have reentrant VIs, there needs to be memory allocation and book keeping for each instance, something which will have a greater impact the more reentrant VIs you have (although I don't know how pronounced this effect is).

....Obviously, you also won't gain performance if your non-reentrant VIs aren't actually blocking.

Thanks Yair.

Yes, it will be dependent on the application.

I do not (currently :) ) have performance issues that I am looking to solve.

But I am trying to find out what other people do/how other people distribute their reusable LVOOP classes!!

This is supposed to be mitigated if you use the shared pool for clones option available in 8.5 and later (since only N instances are allocated for each reentrant VI).

FWIW, referring back to my original post (RE: DD methods), a dynamic dispatch VI cannot preallocate a clone for each instance, so it must be set to shared re-entrancy only.

Given you post, do you not use reentrancy for you reusable VIs?

Cheers

JG

Link to comment

When developers release their reusable LVOOP libraries, do they make all their method VIs reentrant?

Ooooo.... good question. Here's what I do when I'm designing reusable code:

1. Purchase crystal ball

2. Look into it to see how the code will be used in client apps

3. Code the reuse module according to expected use cases

4. Act surprised when somebody (possibly me) uses it in an unforeseen way

5. Use crystal ball for target practice

Your question is, I think, a variation of the tradeoff between writing bigger, more complex code that can be used in many different situations and writing smaller, simple code with more limited applicability. (The difference being that this decision adds to debugging complexity rather than code complexity.) It doesn't matter where you draw the line between those competing goals; some users will complain your code is bloated, others will complain it doesn't provide enough functionality. My take-away is I can't write code that is going to fit all future use cases, so I don't bother trying. I write code that meets my immediate needs with some wiggle room for predictable and likely future needs. When I run across a use case that violates the assumptions I based my reuse module on, it's time to write new code. (Could be app-specific code to deal with the special case, a new version of the reuse module, or a completely new reuse module.)

This is a round-about way of saying no, I don't automatically make them reentrant. 98% of the time I don't need it. Of the 2% of the time where I do need it, often it is predictable and I can designate that VI as reentrant. For me, the 1% increase in code applicability I'd gain by making everything reentrant doesn't justify the increased hassle in debugging the other 99% of the code. That said, I'll be the first to admit I probably don't think about reentrancy enough. There are a couple places that I need to go back and check that I've set it correctly.

Link to comment

Given you post, do you not use reentrancy for you reusable VIs?

Not unless they need it as part of their functionality or if I would have reason to suspect their performance would be improved by it. As far as I can tell, this is also NI's policy with vi.lib (you'll note that most VIs there are not reentrant).

Link to comment

Not unless they need it as part of their functionality or if I would have reason to suspect their performance would be improved by it. As far as I can tell, this is also NI's policy with vi.lib (you'll note that most VIs there are not reentrant).

Thats interesting I thought NI would recommend re-entrancy and use it too! :wacko:

I thought if I was calling a lot of functions in parallel (i.e from reuse library (vi.lib, OpenG, my library) it would be good to use re-entrancy?

Interesting!

Link to comment

Your question is, I think, a variation of the tradeoff between writing bigger, more complex code that can be used in many different situations and writing smaller, simple code with more limited applicability. (The difference being that this decision adds to debugging complexity rather than code complexity.)

Well no, not really, (for the first part) and yes (for the second part) :)

I just want to know if I should set re-entrancy on my class methods.

The reason being I believe it will effect debugging by the developer (not functionality).

Its just that if you (can) write a resuable function, document it well, have a good interface to it (descriptive controls labels etc..), chances are the user does not have to go into the VI to work out what it does (or that would be the point).

However, with classes, I am sure you may want to get in there and have a looksy because it is more complex than a single function.

And being re-entrant can make that process a little harder (although it can sure sharpen up your debugging techniques).

My take-away is I can't write code that is going to fit all future use cases, so I don't bother trying. I write code that meets my immediate needs with some wiggle room for predictable and likely future needs. When I run across a use case that violates the assumptions I based my reuse module on, it's time to write new code. (Could be app-specific code to deal with the special case, a new version of the reuse module, or a completely new reuse module.)

I like your style! Right now I am looking to release code that e.g. serves as a base each thing I do all the time for my apps. So my use cases are well defined for extending the class.

The other thing I do is password protect these distributions on release which serves to hide the private methods (in any library) and no one can accidentally edit those classes.

This posses the same problems as the re-entrancy by decreasing the ease of debugging , (if you don't know the password) you can't see block diagram.

Does anyone do this? and how do they find it?

Link to comment
Thats interesting I thought NI would recommend re-entrancy and use it too! :wacko:

Yeah... I thought that too until our Chief Architect came to have a talk at my desk after I converted one batch of VIs to reentrant and caused LV's Getting Started Window to quintuple its memory allocation.

Normal reentrancy solves concurrency issues at the cost of memory allocation. The vast majority of subVIs are never under parallel contention, so making those subVIs reentrant simply increases memory usage, which generally means a performance slowdown because things start paging in and out of memory, take longer to load from disk, and generally aren't cached because all the parallel copies keep knocking each other out of the caches. Only when you have parallel contention do you get a performance gain from use of normal reentrancy.

Shared reentrancy is a different beast. Only one clone is in memory. If two subVI calls to that clone try to happen at the same time, a second clone is allocated. Once allocated, that clone stays allocated (I think as long as the VI stays in memory without being edited, but it might only be as long as the VI stays running... I'm not sure which). What this means is that you take a performance hit when that second clone gets allocated, but thereafter you get most of the benefits of parallel execution. There's slight thread friction each time the caller VI accesses the clone pool at the start of the subVI call, but that's minimal compared to the friction of being entirely serialized. Shared reentrancy appears in empiric tests to be a good compromise.

There's a new feature on the horizon that will introduce yet another variant to consider, but you'll have to wait to August to hear about it (unless you join the beta program and help LV by doing a bit of testing in exchange for early enlightenment).

Link to comment

Shared reentrancy is a different beast. Only one clone is in memory. If two subVI calls to that clone try to happen at the same time, a second clone is allocated. Once allocated, that clone stays allocated (I think as long as the VI stays in memory without being edited, but it might only be as long as the VI stays running... I'm not sure which). What this means is that you take a performance hit when that second clone gets allocated, but thereafter you get most of the benefits of parallel execution. There's slight thread friction each time the caller VI accesses the clone pool at the start of the subVI call, but that's minimal compared to the friction of being entirely serialized. Shared reentrancy appears in empiric tests to be a good compromise.

Yes that is interesting! :)

I have been talking about using Shared Reentrancy for my classes.

What bothers we know is that my reuse library is in 8.2 so the only option is Preallocated Reentrancy (which I use).

Would a better choice be None?

Therefore some uses cases for Preallocated Reentrancy would be:

  • Where state must be maintained for each instance
  • When non-blocking calls are required and we require better determinism - e.g. on a RTOS Shared Reentrancy could increase jitter.

Are there anymore?

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
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
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.