LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Feedback node misunderstanding

Hi community,

 

I've prepared TEST.vi with 3 different scenarios implying a feedback node. I have a circular counter and I expect it to count indefinitely. I've created subVI Version1.vi and it works fine as long as a single instance is used within the same loop. If I put more instances, it does not work. As a workaround, I created subVI Version2.vi where the feedback node was moved outside of the subVI and this does work.

 

Anybody knows why?

 

Thanks.

 

 

Download All
0 Kudos
Message 1 of 8
(1,092 Views)

It's because your subVI is non-reentrant. What that means is that all instances share the same memory space. In other words, the same function is used for each and every function call. When you have four different instances of your subVI in Test 2, you will call the same function four times. Since the feedback node inside the subVI is affected by these inputs, then you'll be basically resetting everything each time you call the subVI without any new inputs.

 

Another way to think about it is that, even though there are four function calls to the subVI, there's only one feedback node in memory that gets called with each function call.

 

Version 2 doesn't store any state info inside the subVI, so no matter how many instances of them you call, there's only one feedback node- the one in TEST.vi.

 

If you want version 1 to work, you can get that by changing your reentrancy setting. Go to File, VI Properties, then Execution, and change it to "Preallocated clone reentrant execution". Preallocated clones means that each subVI you drop onto the block diagram gets its own memory space, rather than a non-reentrant where the subVI gets its own memory space regardless of the number of subVI's you're using.

 

(And just for completeness, "Shared clone reentrant execution" means that multiple different subVI calls CAN happen in parallel, but they share memory spaces. Use this when you don't have internal state data but you want to be able to call the same VI multiple times in parallel.)

0 Kudos
Message 2 of 8
(1,064 Views)

A little demo to show when you can use Shared Clone reentrant. Download all of these to the same folder, then open "Wait Demo" and try out the three different tests.

 

Basically it's just a While loop with an indicator on its Loop count terminal. Inside are three cases containing either "Wait 1 sec nonreentrant" or "Wait 1 sec shared clone". These subVI's just wait for 1 second but have different reentrancy settings.

 

When you run two instances of "Wait 1 sec nonreentrant" in the same loop, it has to call the same function twice, meaning it takes 2 seconds to execute. When you run two instances of "Wait 1 sec shared clone", then it can run both of the VI's at the same time, since they get their own memory spaces.

Message 3 of 8
(1,059 Views)

@AlexDarsigny wrote:

I've prepared TEST.vi with 3 different scenarios implying a feedback node. I have a circular counter and I expect it to count indefinitely. I've created subVI Version1.vi and it works fine as long as a single instance is used within the same loop. If I put more instances, it does not work. As a workaround, I created subVI Version2.vi where the feedback node was moved outside of the subVI and this does work.


As has been said, if each subVI instance should have it's own memory space, you need to make it reentrant.

 

Still, your entire code has a weird smell. Can you explain what your definition of a "circular counter" is and what it should do based on the decimation factor? Even what you define as "works" seems to behave quite chaotically, especially since you are using greedy loops. What's the significance of the 192 wired to N? Why can't you coerce to constants instead of reading front panel properties? What's the point of the local variables?

 

For example if you want to make sure the values is 1 or larger, all you need is the following: 

 

altenbach_0-1692134726577.png

 

You have inner feedback nodes and outer shift registers fighting each other. I have the feeling whatever you are trying to do could be done with 10% of the current code. Can you define the exact requirements what the subVI should do and how it should be used? What's the purpose? (For example if the decimation factor is 8 or 12, nothing ever happens!)

 

 

 

0 Kudos
Message 4 of 8
(1,009 Views)

Thanks everyone for the very clear explanation. Don't bother about how relevant my circular counter is, it was just a small part of a massive project.

 

In this project I have about 60 subVIs and a lot of them have several instances called in the main vi. "Preallocated clone reentrant execution" seems to be the only valid setting for me and I wonder if I should just set all my 60 subVis this way. I don't understand how the 2 other options would be useful in any situation. Is it just a matter of CPU usage optimization ?

0 Kudos
Message 5 of 8
(949 Views)

@AlexDarsigny wrote:

In this project I have about 60 subVIs and a lot of them have several instances called in the main vi. "Preallocated clone reentrant execution" seems to be the only valid setting for me and I wonder if I should just set all my 60 subVis this way. I don't understand how the 2 other options would be useful in any situation. Is it just a matter of CPU usage optimization ?


Are these 60 differently named, but identical subVIs? In that case you only need one reentrant version.

 

Since reentrant clones have their own memory space, the impact is mostly on memory utilization, which is probably insignificant unless they operate on huge arrays.. Having reentrant VIs can potentially improve computation speed if you have multiple cores, because several can execute in parallel.

 

If a reentrant subVI retains data between calls (e.g. in an uninitialized shift register), you need to use preallocate reentrant to ensure that they don't step on each others toes. Shared clone reentrant is useful if they don't retain data and should run in parallel as much as possible but dataflow ensures that only a few can run in parallel and the compiler can figure out how many are really needed. Shared clone is also needed for recursive calls, e.g. if the subVI calls itself.

 

I still have the nagging feeling that your project is overly complicated and could be dramatically simplified. If you share more about the project, we can probably give some constructive advice. Maybe you can operate on arrays instead of herding cats scalars?

0 Kudos
Message 6 of 8
(931 Views)

The 60 subVIs are all different. I use a single instance of about 50 of them. I would probably set these 50 subVIs to "Non-reentrant execution" and the 10 others to "Preallocated clone reentrant execution" since I have several instances of them in my main vi.

 

It's a data acquisition project using DAQmx library. Its complexity is the amount of settings before starting a data logging. I have no performance problem on a decent PC.

 

Thanks again for the information!

0 Kudos
Message 7 of 8
(921 Views)

The entire question of reentrancy (which kind, why, how does it work, how to get it working) will go away if you put the state of the VI (the value of the FB node) in a wire.

 

An input\output cluster would do. Even the single value... I'd use a class.... The data (object) would live in a shift register, one for each loop.

 

Cloning the callers would become a non-issue.

 

Less complexity, less headaches.

0 Kudos
Message 8 of 8
(851 Views)