I am trying to understand how the UI Thread Execution System works.
Under VI Property, I choose UI Thread, which means there should only be one thread running.
However, when I make two for loops that run forever, with indicators connected to each iteration terminal, the two loop seems to runs in parallel.
Furthermore, if I make around 50 of the loop described above, all of the loops are still running in parallel.
(Obviously the indicator update rate gets extremely choppy since I am using the UI thread).
Something else I realized is when I check task manager and observe all cores (8 in my case), the loops seem to be run by all core, since no one single core's CPU usage seem to go to max %.
From my understanding, if we are only using one thread (UI thread), then we should not expect the loops to run in parallel.
But obviously, that isn't the case. Could someone point out where my understanding went wrong?
P.S. I am using LV 2018.
Thank you so much.
Solved! Go to Solution.
LabVIEW was multithreaded way before CPus with multiple CPU cores became popular. Even a single thread can run multiple loops "seemingly" in parallel, even though the UI thread is quickly alternating between running these loops.
Even a single thread is not locked to any specific CPU core forever and typically the OS has algorithms to balance core usage to even out the thermal load. there are always many threads running on a given computer (just look at the task manager!), and your UI thread will probably get a different core whenever the OS schedules it to get a piece of the pie.
We are graphical programmers, so instead of giving a potentially ambiguous description of what you are doing, please attach a small example VI. Do these loops have a 0ms wait?
An interesting experiment is described here. (VI is set to run in the UI thread!)
Running 50 greedy loops will make everything "choppy", UI thread or not. Are you just playing around or are you trying to fix a specific problem?
Just to add to the reply - LabVIEW doesn't execute your VI in a single go with the one thread. Allocating the particular thread (UI) simply means that it is the only thread that will ever execute your code but it won't necessarily do it in one go - your VI is broken down into parts and each part is executed in one go at any one time - data flow controls the order.
You can think of the execution conceptually (albeit crudely) like a producer/consumer process where the producer is the compiler working out the 'clumps' of code and them pushing them into a queue for processing and the consumer is the UI thread ready to dequeue and execute those 'clumps' of code. That means the UI thread could be executing pieces of code from multiple VIs, one at a time.
If you weren't using the UI thread but one of the execution systems with multiple threads ready, then each thread simply picks up a clump to execute from the queue and the overall result is less execution time (if you have more than one CPU core of course).
Naturally you can imagine there is a lot more complexity than this simple view, especially around sharing state (eg. how does data from one clump get used as in another clump?).
Have a read further in the help: https://zone.ni.com/reference/en-XX/help/371361R-01/lvconcepts/labview_threading_model/.
This link with some background on the compilation process is also interesting but perhaps a bit beyond your question: http://www.ni.com/tutorial/11472/en/
Thank you guys for your answers.
It all makes sense to me now 🙂
LabVIEW has its own "clumping" algorithm to determine which pieces of code to execute in which thread, and then the threads are then managed by the OS to decide which logical core to execute in. LabVIEW itself determines how many threads by the number of logical cores and depending on the execution system.
Also, I apologize but this wasn't actually a question related to my application.
I took the NI Performance course, and was reviewing the materials and actually testing out concepts by writing simple codes.
Once again, thank you guys!!!