LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Functional Global Variable on Hold

Solved!
Go to solution

Hello everyone,

 

I understood, by reading threads on the forum, that a call to a Functional Global Variable will block its execution if the FGV is already being accessed by another VI, correct? Is there any other way it would block, apart from the stated?

The motive of the question is that I have one FGV (non-reentrant) that is read by 8 subVIs concurrently (they are, actualy, the same vi, but configured to reentrant) and whose access time varies, strangely, based on the number of subvis running.

When less than 5 VIs are trying to access the FGV, the execution is blocked (I assumed it, because when the FGV is disabled and replaced by a constant there is no problem with the execution) and the access lasts at least 50 ms; if this number is between 5 and 8, the execution is done much faster. My first guess was that the FGV hasn't been initialized until the fifth subVi is called, but I don't know how to check that.

 

I can figure that there is something wrong with the FGV, but can't put my finger on it. Any ideas?

 

Thank you in advance for any help.

0 Kudos
Message 1 of 19
(4,684 Views)

my nugget on Action Engine talks about how access to them is blocked when executing in another thread (see here).

 

YOu could monitor the AE with execution highlightighting on to get more info. If you puase the AE (or breakpoint it) the font selection box morphs into a call chain indicator so that may give you a clue who is calling the AE

 

Post images we may be able to offer more help.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 2 of 19
(4,671 Views)

Thank you for your response, Ben

I'll try to explaing the problem better with the images that follow.

I have 8 concurrent instances of the "bitDefiner.vi" - shown below - in the program.

bitDefiner.vi

 

It reads from the AE (a simple read-write one) and it's the only one to call it besides the writer (that generates the appropriate signal), gets the rising edge of a waveform and determines how long it takes until the falling edge, giving a category to this time later on. If it doesn't determine the period between rising and falling edge before the timeout runs out, it aborts the execution of the while loop. This VI execution is setup like this:

 

betDefineConfig.JPG

-------------------------------------------------------------

That being said, let's go to the problem.

Assuming there is nothing using the AE but one instance of the bitDefiner, it won't get the rising edge, due to the fact the signal is not being generated, resulting in a timeout. The return value on the diff indicator should be next to the one defined to timeout(image below)

 

birDefinerPanel.JPG

 

However, when the subvi concludes its execution, the diff indicator shows 54ms intead of 15ms; so I concluded that the AE is taking to long to process the call. Besides that, I'm quite positive that there is only one thread accessing the AE.

After this result, I ran the other instances of the bitDefiner and after the 5th one got activated, the diff went to the expected 15 ms Smiley Frustrated (I'm still thinking how to show that on picture).

 

I tried highlighting the execution, but it didn't show me anything unsual. The call chain just present that the caller is the bitdefiner VI as expected.

 

Any thoughts on that?

 

 

0 Kudos
Message 3 of 19
(4,664 Views)

If I understand your issue correctly, you have 5 or more reentrant VIs and 1 FGV that all VI reentrants need to access, well that kills your reentry when accessing the FGV (assuming they all access at the same time). Reentrant VI can only be reentrant when they're able to run data seperate and independant, no pun intended.

0 Kudos
Message 4 of 19
(4,652 Views)

Hmmm never thought of that. But what I meant is that it works correctly when there is 5 or more threads running. With less than that, there's the malfunction (quite counterintuitive if you ask me).

0 Kudos
Message 5 of 19
(4,647 Views)

Try using the Preallocate" flavor of reentrant. You may be running into an issue with allocating the VI on the fly that is somehow reduced when you have more active.

 

If it makes a difference the answer to your question (and mine) would be revealed using the Desktop trace Execution toolkit.

 

You have me curious and will look for any updae you can share.

 

 

Now I don't want to stir up too much mud while you are searching for answer but your code sgguests using "Subroutine" priority since it should run fast. Doing so would let you using a more advanced approach taking advantage of the "Skip-if-busy" sub-VI call set-up. YOu would first using the AE before entering the loop as a standard sub-VI call. THe result would be kept in a SR of the loop. Inside the loop you use the same AE but selecte "skip if busy" and monitor a boolean returned by the sub-VI that is true when called. The returned boolean would be used as input to a select operator with the value from the AE wire to the True input and hte SR wired to the false option. If the AE is busy it will be skipped returning a false so you use the value from the SR. If the sub-VI is not busy and not skipped the true boolean would selecte the value from the AE.

 

But don't worry about that stuff until you have a handle on what is going on.

 

take care,

 

Ben 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 6 of 19
(4,632 Views)

Yes use "Preallocate" flavor if that works. It appears that you must because your reading shift register data. If plan to use lvclass you may be block from "Preallocate".

 

A different workaround for the FGV though is to use a Global variable with only 1 writer and many readers. This may even work out faster. Well hope that helps.

0 Kudos
Message 7 of 19
(4,624 Views)

@richjoh wrote:

Yes use "Preallocate" flavor if that works. It appears that you must because your reading shift register data. If plan to use lvclass you may be block from "Preallocate".

 

A different workaround for the FGV though is to use a Global variable with only 1 writer and many readers. This may even work out faster. Well hope that helps.


 

The last time I used a normal global I ran into this problem where some of my timed loops would finish late. Tossing the global and switching to an Action Engine to flag the stop fixed the finished late problem. The issue was repeatable and the issue was the global. Never did get a good answer to that question.

 

Ben

 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 8 of 19
(4,620 Views)

Yes Ben your correct, nevertheless global should be carefully handled. Whether every nano-second is needed is to be determined.

 

From Help Context -

"

Memory Considerations when Using Global Variables

When you read from a global variable, LabVIEW creates a copy of the data stored in that global variable.

When you manipulate large arrays and strings, the time and memory required to manipulate global variables can be considerable. Manipulating global variables is especially inefficient when dealing with arrays because if you modify only a single array element, LabVIEW stores and modifies the entire array. If you read from the global variable in several places in an application, you create several memory buffers, which is inefficient and slows performance."

 

It appears Edmi0 is reading a waveform! Maybe the use of "In Place Element Structure" smart here.

 

From the Help Context -

"Many LabVIEW operations require LabVIEW to copy and maintain data values in memory, thereby decreasing execution speed and increasing memory usage. The In Place Element structure performs common LabVIEW operations without LabVIEW making multiple copies of the data values in memory."

0 Kudos
Message 9 of 19
(4,615 Views)

Well... update time:

 

1st I tried changing the allocation to "Preallocate" and got absolutely no result. Less than 5, big timeout value; more than 5, ok result and proper functioning (Fun fact, decided to start disabling loops and the magical number seems to be 3. What does that mean? When there's 5 loops, it only starts to work properly when 2 loops or more are running; if there's 6, you need at least 3 and so on)

 

2nd trial consisted in changing the AE priority to "Subroutine" and something came up. At first, it timeouts correctly, i.e. near the number setup as input, but it does not seem to be able to read from source. The source is running and generating the points of the waveform (it is a waveform but I only process one point at a time, therefore shouldn't exist the problem with the big data structure) but the VI timeout continuously when the expected would be to catch the rising edge. Beats me Smiley Frustrated

 

I appreciated your idea, Ben. But how could I use a boolean to know if the AE was skipped or not? Have it as "False" for default and make the AE changed it to "true" when accessed?

 

After putting some thought on working this around, I would like opinion on another solution I came to (to be honest, I'm somewhat skeptical about it). What if I read the AE from the main VI, updated an indicator and, later on, passed this indicator reference to the subvi. How great would be the losses regarding efficiency and memory management? I figured this could, at least, prevents multiple access to the AE and perhaps solve the problem regarding the number of running threads.

 

Looking forward to hear whatever comes up.

0 Kudos
Message 10 of 19
(4,593 Views)