LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Is this roughly how the labVIEW Execution Systems work?

Greg,

You stated:

... you do this, you might as well allow all threads to access the panel objects. And that would mean adding lots and lots of mutexes to protect things. And since the panel objects are so highly connected, you would often only have a single thread active at a time anyway. In other words, in our opinion LV is better off like this, or single threaded.

............................

...lots and lots of mutexes... You know, that's a bit of an exageration. You can protect the whole front panel, each control, or every individual byte of data associated with a control. On the surface of it, it would seem the granularity of your mutexing is wholely up to you. And besides, from the diagram side of things you only need mutexes around controls with local variables, control references, and perhaps referenced property nodes. If the panel is open, the control values, at least, are already mutexed. From your statement the reader might get the impression you'd need additional mutexes around every front panel object in every vi throughout their entire application.

Your statement "would often have only a single thread active anyhow" suggest that a thread is suspended by a mutex. I had actually hoped LV was dealing with the mutexing so that a thread wouldn't be suspended.

Anyway, as you seem to want to know why I go off on these tangents, the wanting to know everything about everything, it is simply because there was a noticeable degradation in the performance of my application when it was migrated from LV4.1 to LV6.0.

Boolean arrays is one area, another is the table control. It doesn't draw as fast, doesn't scroll as smoothly, etc. One reason for this could have been that my other diagrams were sharing the user interface thread. All my GUI front panel diagrams use referenced property nodes, and I assumed they were now being run in the user interface system because of the differences between the execution environment in LV4.1 and LV6.0. It was my understanding that LV4.1 used a single threaded prioritized queue for its diagrams and another threaded queue for the GUI. I assumed the threading changes you had made to execution environment were causing the degradation.

Last night though, I single threaded LV6.0 and compared the control performance in LV6.0 with that in LV4.1 and found that it had nothing to do with threading. The drawing performance of the table control in LV6.0 compared to LV4.1 just stinks. Sorry, but it does.

Obviously something has changed. ...I also notice the vi was using twice the memory in LV6.0 as LV4.1 so now I'm thinking perhaps LV6.0 is using Unicode for the front panel display causing some of the degradation in performance... I really don't believe that, but you can have the benefit of the doubt.

Actually, if you told me the table control in LV6.1 performs much better than LV6.0, I would have a very visual reason for justifying why I spent $$$$.

......

On another note... It is good to know that idle threads go to sleep. I was wondering if their boredom might distract my other threads.

Kind Regards,
Eric
0 Kudos
Message 11 of 18
(1,878 Views)
Greg,

You stated:

... On another topic, LV doesn't currently return data when a VI finishes. There is an ini setting for doing this, but it really affects performance, adds lots of non-determinism, and tends to fragment memory to the point where the process uses quite a bit of extra memory. So the current setting is to have subVI temporary buffers remain allocated until the VI leaves memory or is recompiled...

I know what indeterminate means, what is non-determinism and how does it apply?

I guess your telling me that if I pass a 30 Mbytes array to a subvi and it makes a copy to do some work, that it is going to retain that copy until the vi is recompiled or leaves memory. The next time its called with a 8 byte array it uses 8 of its current 30 Mbytes? In other words, it remembers the maximum amount of memory required to perform its function and never gives it back until the vi leaves memory? I understand the logic of that... avoiding the reallocation and memory fragmentation are compelling arguments.

But... I admit that contrary to NI's recommendations I use anxiousMemoryDeallocation. (Somehow this makes me feel like I'm at an AA meeting.) I ran some test a long time ago and decided the penalty wasn't substantial. But as you seem to indicate it's a bad idea, I'll take another look at it.


Next topic ......................

You stated:

There are VIs that are pure functions, which will work whether reentrant or not, but making them reentrant gets rid of contention. This doesn't mean anything runs faster, but it allows for preemption and particularly for higher priority items to cut in line.

I don't disagree, but it just seems to me there must be a penalty associated with checking if a resource is busy and a penalty to suspending a task when threads collide on a resource. I do not know how to determine the relative cost of checking a mutex, the number of collisions, nor the relative cost of those collisions. Therefore, to be safe, the logical solution to this potential problem seems to me to be removing it.

It is true that making pure functions reentrant does not guarantee improved performance, but it is also true that making them non-reentrant guarantees less than optimal performance, particularly on a multiprocessor machine. ...but then perhaps I'm merely stating the obvious.

Kind Regards,
Eric
0 Kudos
Message 12 of 18
(2,199 Views)
> I know what indeterminate means, what is non-determinism and how does
> it apply?

Technically, it means it isn't deterministic, but really I meant that
the timing isn't deterministic. Meaning that the timing of the VI, or
of diagrams will vary alot with the same inputs. It is also called
timing jitter.

> called with a 8 byte array it uses 8 of its current 30 Mbytes? In
> other words, it remembers the maximum amount of memory required to
> perform its function and never gives it back until the vi leaves

It isn't that the buffer never gets resized, in your example, it would
shrink to 8Mb. On the otherhand, if a VI is called many times in a
loop, and each time it is passed a 2Mb array, the temporaries are
already setup and very little time is spent allocating, resizing, or
freeing memory.

....
> I don't disagree, but it just seems to me there must be a penalty
> associated with checking if a resource is busy and a penalty to
> suspending a task when threads collide on a resource. I do not know
> how to determine the relative cost of checking a mutex, the number of
> collisions, nor the relative cost of those collisions. Therefore, to
> be safe, the logical solution to this potential problem seems to me to
> be removing it.

Mutexes, critical sections, and other protection mechanisms vary greatly
depending on the machine architecture. It can be as small as a couple
instructions, but of course more if the threads collide ... Since so
many OS resources have to be protected, mutexes and other protections
mechanisms are some of the better optimized code in the OS.


> It is true that making pure functions reentrant does not guarantee
> improved performance, but it is also true that making them
> non-reentrant guarantees less than optimal performance, particularly
> on a multiprocessor machine. ...but then perhaps I'm merely stating
> the obvious.

And this is where things get tricky. When the difference between
optimal and typical performance is very small, how much time and money
is it worth to be optimal. As stated before, correctness comes first,
then measure the performance. If you see problems, then look to modify
those sections.

Greg McKaskle
0 Kudos
Message 13 of 18
(2,197 Views)
> ..lots and lots of mutexes... You know, that's a bit of an
> exageration... And besides, from the diagram side of things you
> only need mutexes around controls with local variables, control
> references, and perhaps referenced property nodes. If the panel is
> open, the control values, at least, are already mutexed. From your
> statement the reader might get the impression you'd need additional
> mutexes around every front panel object in every vi throughout their
> entire application.

I'm more than happy to answer questions, but correcting these statements
does not seem to be the most productive way to go about things. But
here we go. Controls without locals can still be accessed via the
connector pane, additionally, the user can be modifying a control's data
at the same time as the diagram wishes to read it. Both of these
situations mean that a mutex is needed or control data, even with no
local, no properties. Add in the fact that the VI Server allows for
references to labels, captions, colors, fonts, and you can't even use
static analysis to determine which pieces need protection and which not.

So, the current system allows for one thread to perform all of the UI
tasks and the other threads do diagram execution. The requires a few
mutexes at the boundaries, but not as many as would be needed if other
threads were allowed in the panels. If you think I'm exagerating, fine.
I have access to the LV source code and I deal with thread access and
mutexes on a regular basis.

> Your statement "would often have only a single thread active anyhow"
> suggest that a thread is suspended by a mutex. I had actually hoped
> LV was dealing with the mutexing so that a thread wouldn't be
> suspended.

In C code, two threads approach a mutex, each getting the CPU for a
short amount of time. The first that reaches it acquires and goes past.
The second thread tries to acquire and is blocked. Ideally it is
suspended and wastes no CPU resources. The OS continues to give time to
the unsuspened threads until the thread that has the mutex gets to the
end of the protected code and releases it. Typically this is when the
OS gives the suspended thread some time to execute. A thread is simply
a stack, register values including an instruction pointer, and a bit of
other storage for things local to the thread. A thread executes one
instruction after another and has no way of jumping around. Instead,
the OS jumps around activating various threads in order to execute
different code.

The threads in LV's execution systems are no different, but the code
that the threads execute frequently return to the scheduler, where they
are given code to execute from their priority queues. When not in the
scheduler, the threads indeed get blocked and suspended at the whim of
the OS, priorities, and mutexes.

.... It was my understanding that LV4.1 used a single
> threaded prioritized queue for its diagrams and another threaded queue
> for the GUI. I assumed the threading changes you had made to
> execution environment were causing the degradation.

LV4.1, like all LV's before LV5 when threading was introduced executed
all VIs using the UI thread. There was no need for mutexes since there
was only one thread. Bad part of this was that drawing a graph or table
meant no diagram was executing. Similarly a single DLL or CIN would
bring all of LV to a halt until it returned the one and only thread to
do something else.

> ... to do with threading. The drawing performance of the table control in
> LV6.0 compared to LV4.1 just stinks. Sorry, but it does.

No need to apologize. Let's get to the bottom of this. I'm using a Mac
at home, so threading won't affect my timings at all since both LV 4.1
and 6.1 on mac are single threaded. Building strings and sending them
to a table I got times that showed that the LV6.1 does tend to be a
little slower than LV4.1 table. With some table shapes they are
virtually identical times, with other shapes I get somewhere around 50%
more time spent in 6.1. I wasn't testing any attributes/properties, so
I really don't know what your numbers are. If you will build an example
showing the performance difference and send it to NI tech support,
someone can look into it. It is likely that some feature or set of
features affected the display speed, but it could also be a bug.

> Obviously something has changed. ...I also notice the vi was using
> twice the memory in LV6.0 as LV4.1 so now I'm thinking perhaps LV6.0
> is using Unicode for the front panel display causing some of the
> degradation in performance... I really don't believe that, but you can
> have the benefit of the doubt.

I suspect the memory usage is due to the transfer data that frees the
panel and diagram up. Again, this is just a guess since I can't look at
your VI. Build something that shows the affect, send it to NI tech
support and you should get a better explanation.

And while the unicode is a good guess, LV doesn't use unicode for
display, though it does support dual byte characters. So this doesn't
explain the performance difference.

Greg McKaskle
0 Kudos
Message 14 of 18
(1,878 Views)
Greg,

You said:

...I'm more than happy to answer questions, but correcting these statements does not seem to be the most productive way to go about things...

On the other hand, just answering questions gets boring after a while. If I'm contentious, you get to say "your wrong for the following reasons..."; Admittedly, this too can get boring after awhile. Nevertheless, if I'm wrong, deliberate or otherwise, the person telling me I'm wrong is obligated to tell me why. This generally leads to a more thorough answer than if I just ask a question...

When my brother in-law was in technical school they used to provide him with equations to solve this or that problem. He came to me a couple of times and asked i
f I understood how they arrived at this formula. I tried to show him, but some of the math was outside his background and so we both agreed that it was kinda pointless. I guess he was satisfied knowing that if he invested the time, he could understand circuit models and derive the relationships they were giving him. But his goal was a technical degree, not an engineering degree, and his education provided him the specific tools required to do his job.

I'd say you prefer to provide a technical school answer to specific questions, but I'm reasonably confident you could also teach computer science at the graduate level. I know its not as efficient, but on the otherhand armed with more information, I can go away and solve a rather larger set of problems. In light of that, it would seem whether or not it is productive kind of depends on both of us.

Kind Regards,
Eric
0 Kudos
Message 15 of 18
(1,878 Views)
If someone comes along a couple weeks from now, what will they see.
They will see your post telling everyone how LV works. They might
happen to see my post trying to correct things, but it looks odd. It is
odd.

I answer lots of questions on this forum, I believe that I answer them
just as thoroughly when they are presented in the way that I'm asking.
As a question.

We have been doing this your way, and I'm asking that we try it the
other way.

Greg McKaskle
0 Kudos
Message 16 of 18
(1,870 Views)
Greg,

Point taken... I also understand your motivation to keep things simple. When you say tricky, for example, I know we are getting into an area that potentially could cause someone including myself a lot of headaches, deciding what is and what is not reentrant code, for example. And while I can go away, you have to deal with the aftermath...

Still there are a lot of nuances about labVIEW that are missed. For example, anxious memory deallocation seems to apply to asynchronous vis, but not to subroutine vis, which is probably why I didn't see a performance hit by using it.

At least, that's what I think because the vi profiler tells me my asynchronous vis use a lot less memory than my subroutine vis when I use anxious memory deallocation, and there is a performance hit for asychronous vis were as there isn't for subroutine vis.

So yes, I took the time and went back and examined why I use anxious memory deallocation. And yes when I did it, I had a reason. Having reviewed it again, it would seem your statement about vi memory de-allocation is incomplete... I can of course ask: "How do reconcile your statement with these vi profiling results?" And you can say ... whatever it is you wish to say...

...odd... Hmmm, if I have to setup tests to examine your answers or statements to determine whether they are complete, and I take the time to do that, one has to wonder whether there is a point to coming back and reconciling my findings with you. My personal preference is to give you another opportunity to explain your position, in the hope that perhaps you might clarify your point. Since I can't really ask the question again, I take issue with what you state. And if I'm still not happy, then I'll go away and create the test, and draw my own conclusions. But I'll not publish my findings, the above being a notable exception as it is the case in point. It is not that I expect something you say to be incorrect, rather merely incomplete.

...If you find that odd, maybe I'm just odd... but I will try to conform.

Kind Regards,
Eric
0 Kudos
Message 17 of 18
(1,870 Views)
> Still there are a lot of nuances about labVIEW that are missed. For
> example, anxious memory deallocation seems to apply to asynchronous
> vis, but not to subroutine vis, which is probably why I didn't see a
> performance hit by using it.
>

This makes sense to me. Subroutine VIs are compiled for performance,
with as much entry and exit overhead left out.

> So yes, I took the time and went back and examined why I use anxious
> memory deallocation. And yes when I did it, I had a reason. Having
> reviewed it again, it would seem your statement about vi memory
> de-allocation is incomplete... I can of course ask: "How do reconcile
> your statement with these vi profiling results?" And you can say ...
> whatever it is you wish to say...

This is a newsgroup. Of course the replies are incomplete. I've given
a one hour overview on the execution system before, and I didn't touch
on the nuances of the anxious memory deallocation there either. We are
discussing the design and behavior of tens of thousands of lines of code
which are a part of a much larger system constructed over the last
eighteen years. So of course these emails aren't complete. I read over
them quite a few times and make a number of small VIs to verify what I'm
saying.


>
> ..odd... Hmmm, if I have to setup tests to examine your answers or
> statements to determine whether they are complete, and I take the time
> to do that, one has to wonder whether there is a point to coming back
> and reconciling my findings with you. My personal preference is to
> give you another opportunity to explain your position, in the hope
> that perhaps you might clarify your point. Since I can't really ask
> the question again, I take issue with what you state. And if I'm
> still not happy, then I'll go away and create the test, and draw my
> own conclusions. But I'll not publish my findings, the above being a
> notable exception as it is the case in point. It is not that I expect
> something you say to be incorrect, rather merely incomplete.

I encourage you to experiment and draw your own conclusions. If you
feel that others will benefit, post them here as well, but in at least
the case of the execution engine, the material is already available, and
your summary was inaccurate enough that I fealt I'd better correct it
lest it become a reference point.

Back to my point. When possible, think of this as a Q&A forum. Ask a
question, with background, and let someone answer it.

On the technical topic, if you are dealing with large buffers of data,
you are probably better off not using the anxious memory deallocation
setting as it is a shotgun approach far at the other end of the
spectrum. It trades time for memory by deallocating all diagram
temporaries after each subVI call, but not subroutine call, so the
memory can be reused by other subroutines in the system. Typically,
there are only a few wires and a few temporaries causing the memory
bloating, and with memory as cheap as it is today, the setting typically
causes more harm than good and again, I encourage you not to use it.

Greg McKaskle

Greg McKaskle
0 Kudos
Message 18 of 18
(1,870 Views)