LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Threading Question

I havn't been able to find an cut and dry answer to this question so mabie someone out there knows.


When I write a function to become a thread that has only local variables and I spawn two threads from that function do each of functions get their own seperate and independent copies of the variables that will not interfere with each other?

My inital though is that yes the variables are independent unless they are defined static. This leads to another question, what does it mean to threading it I define a function as static i.e. "static int CVICALLBACK ClientThreadFunction (void *data)" vs "int CVICALLBACK ClientThreadFunction (void *data)".


What I am hoping to accomplish is to write a function that I can span multiple threads and each thread will be self contained and none of the variables will interfere with each other. Is this possible and what do I need to do to accomplish this?

Thanks
Tyler
0 Kudos
Message 1 of 9
(5,084 Views)
Yes, different threads will have their own instances of the function variables; the only exception is static variables.
 
Declaring a function as static simply limits the scope of the function; static functions can only be referenced within the same compilation unit (.c file). Non static functions are visible in all files in the project. The rules for the variables in the function are not affected by this.
 
Hope this helps,
 
-alex
0 Kudos
Message 2 of 9
(5,077 Views)
Thanks,

That was exactly what I was thinking, just need someone else to tell it to me 🙂
0 Kudos
Message 3 of 9
(5,076 Views)
RadioAct -

Each thread gets its own stack, program counter, and register set.   In Win32 each thread also gets "thread local storage" unique to each thread - see Win32 SDK for how to use TLS.  NI offers a thread storage mechanism as well (though I suspect it uses TLS underneath).  And the "golden rule of parameterization" tells us that parameters are the same as automatic local variables (stack variables).

It's your responsibility to ensure that access to any common resource (globals, files, etc.) is properly interleaved so that the threads don't interfere with each other.  static doesn't prevent this - all static means is that the name isn't exported to the linker - the name's scope is restricted to the file.  (Well, it also means that a static variable is allocated off the heap, not the stack, and that it's initialized to zero by default).  If you have two threads active within code from a single compilation unit (file in c) it's entirely possible to improperly interleave access to a static variable.  And since threads within a process all have access to any of that process's resources, there's plenty of ways to go wrong if you're not careful.  But I wouldn't be afraid of trying multi-threading - it's a very powerful mechanism - generally all commercial Windows applications are multi-threaded.

"Multithreading Applications in Win32" by Beveridge and Weiner is a great book.  ISBN 0-201-44234-5.  Showing its age, but there's no good substitute for it.

Hayes
Message 4 of 9
(5,034 Views)
Really nice description of how variables are handled by a thread menchar, I'll give it 5 stars.  So much of this can be compiler specific, for example the way that function scope static variables are initialized if multiple threads call the same function.  I agree that Beveridge and Weiner is worth the time to read.  
0 Kudos
Message 5 of 9
(5,011 Views)
Thanks for the details,

First sorry about the 'static' function call question, I knew it was not related to the threading question, more of a I can't remember what that means 🙂

I have written very specific multi-threaded applications before so I am familiar with the use of threadsafe variables and such, for this task I was trying to make a very generic thread that would get much of it configuration info at run time so if I need more processing power for a calculation I can just spawn more threads and pass them a configuration object and they will go on to perform their task.

I did a quick lookup on TLS and the impression I get is that it provides memory for storing data that can not be accessed from anyone but the thread that created it. If that is correct then is there any benifit to using it rather then the common process memory space to store variables. At the moment all my memory is malloc'd inside the threads (which I assume comes from the shared process memory pool). Although the memory is technically shared between all threads, the other threads never access it.


On a side note when writting a UI, is it commonplace to multi-thread the applicaiton? I'v noticed that in order to get a responcive application I can't have anything running on the same thread as the UI. Just wondering if threading the UI is a common pratice.

Thanks
Tyler

Message Edited by RadioAct on 05-09-2006 11:16 AM

0 Kudos
Message 6 of 9
(5,006 Views)

I guess about 15% of my CVI apps use a multi-threading approach. Usually I reserve it for when I need tight control and response from a custom piece of hardware - normally combined with raised thread priorities as well. For 'normal' OS/GUI type apps I just stick to the one thread. Careful choice of timer callbacks and calls to ProcesssystemEvents() can offer a very high performance level (CPU @ 100%) at the same time as maintaining GUI Control responsiveness.

Don't make the mistake of thinking that more threads == more processing power. One CPU gives you X amount of processing power, no matter how many slices you cut the pie into. It can seem that you are making things better, certainly if you also raise priorities as well, but it is not a magic bullet solution to performance issues.

JR

0 Kudos
Message 7 of 9
(4,994 Views)
Yes more threads does not mean more processing power, Perhaps that was not the best way to phrase it. The types of tasks I perform usually involve waiting for data from external sources with little actual CPU processing; Im more interested in multitasking these actions rather than number crunching.

Now that you mentioned thread priorities...
I am writing a sort of first come first serve priority scheduler to launch these task threads and allow tasks which are more important to be run before less important ones and I was wondering how changing the thread priorities effect the amount processing time each thread gets. For example 5 tasks are submitted to run in the following order. Task priority is from 1-5 with 1 being the lowest.
Task A has priortiy 1
Task B has priortiy 1
Task C has priortiy 1
Task D has priortiy 1
Task E has priortiy 5
If there are three threads in the thread pool, the scheduler will look at the list and decide that Task E is of the most importantce so it gets run then it chooses Task A and finally Task B then waits for some one to finish before it launches a new task. So now we have 1 high priority task running and two low priority tasks running at the same time with approx the same amount of processing time assigned to each.

If task E is important would it make sence to increase its thread priority to increase the amount of CPU time it gets? Is the gain significant or would it make more sence to 'pause' the other threads until this one is finished. Keep in mind that these tasks are not overly critical, its more along the lines of Task E is a user invoked task that a actual person is waiting for and Tasks A-D are a background task that is being done because there is nothing better to do.

Thanks for the insight
Tyler


0 Kudos
Message 8 of 9
(4,989 Views)

RadioAct -

You are correct, as  a general rule most threads actually spend most of the time waiting for I/O.  Creating multiple threads simply allows better utilization of compute bandwidth.  You can use the Windows task manager to prove to yourself that this is the case - there are typically hundreds of threads active and CPU utilization is below 10% for a typical mix of desktop applications.  And you'll be able to see that almost every active process is multi-threaded.  Heck, even the idle process is multi-threaded on a hyperthreaded or multi-cpu system! 

If you ever see a Win32 based system compute bound for more than a moment or two it's very likely a case of a misdesigned process.

Bear in mind that (save for the "Task Manager" the term task isn't used in Win32 - it's processes and threads.  All processes have at least one thread.  In computing science a "task" is generally considered to be a process with a single thread.

All scheduling in Windows is on a thread priority basis.   The scheduler uses a priority based scheme to decide which thread to schedule and allocates it a quantum of time (typically a few tens of milliseconds)  to execute.  All threads from all processes are kept in a series of queues at the various thread priority levels.  Bear in mind that the thread scheduler algorithm varies somewhat from OS to OS (NT's is a bit different from Win2K's, etc.)

Windows uses a "priority class" concept that groups the thread priorities for a given process into one of several groups - realtime, high priority, etc.  The names and number of priority groups varies by OS too BTW 😉  You can change the priority class programatically (which changes the priority of all of the threads in the process) as well as the priority of an individual thread.   See the Win32 SDK for details.

You should be able to set thread priorites at process / thread startup so as to get desired behavior - the whole point of the OS's multi-level process thread scheduling scheme is just that - so you don't have to be dickering with them all of the time.  Most user processes work best at the "normal" priority class - that 's the design intent.  The scheduler will boost thread priority at certain times based on heuristics Microsoft has built in.  It also varies the number of execution time "quanta" as part of the scheme - the amount of time a thread is allowed to execute before pre-emption.  It can be a challenge to get a complete and accurate description of the scheduler's behavior for a particular Win32 OS.  It varies even by the OS version for some of them.

You might find that changing the thread priorities has less of an effect than you'd imagine.

Windows also allows you to establish a more general behavior of the thread scheduler by characterizing the systems operation as emphasizing "normal" user interface processes or background (service) processes.  This tailoring is usually buried somewhere in the control panel.

In VC++/MFC there's the concept of user interface threads and worker threads.  User interface threads respond to windows messages (generally equivalent to user interface events in CVI) while worker threads do not.  

As a design goal you likely want the user interface to stay responsive (an "Abort" button is classic need).

The Win32 thread schedulers don't have the hard determinism of a real-time OS like VxWorks or QNX.  Well, Windows CE does have strict priority based scheduling but none of the others do.  And I'd stay away from the realtime priority class.

The Win32 SDK documents the calls needed to change thread priorities.

I could go on forever but don't have the time 😉  Read Beveridge and Weiner.  Read the NI whitepapers on multi-threading.  Read the Win32 SDK docs on processes and threads.

Hayes

 

Message 9 of 9
(4,976 Views)