![]() |
![]() HP OpenVMS Systemsask the wizard |
![]() |
The Question is: Dear Wizard, I am having difficulty grasping the the "kernal" thread concept. I have written serveral programs taking advantage of the PTHREADS interface. I understand the two- level schedualing and virtual processors. Even "UPCALLS" make sense to me. No problem! What makes a thread a "KERNAL" thread? When should I use the thread linker options: THREADS_ENABLE., /THREADS_ENABLE=MULTIPLE_KERNAL_THREADS /THREADS_ENABLE=UPCALLS I have written a print server (sort of; there's actually a little more than printing involved), which creates a thread for each client (TCP). When a "print" request is received, the client thread scans a list of worker threads for an available worker. When a worker thread is found the client thread a ssigns it the job to the worker. If no workers are available, a new worker thread may be created if the "configured maximum" has not been reached. 1) How do I determine how many worker threads should be allowed? At some point they must to cost more than they're worth. Are there any formulas based on # of clents and processors etc....? How might I measure the effectivness of this model? 2) Which linker options should I be using? 3) What about "multiple kernal threads"? What is the difference between a "thread" and a kernal thread? Please provide any insight that you possess on this subject. Thank, John The Answer is : Given that you understand two-level scheduling and virtual processors, then answering your first question is easy: from your perspective, a "kernel thread" is a virtual processor. On the other hand, from the operating system perspective, a "kernel thread" is the context required by the operating system kernel to schedule execution on a processor. So, in concrete terms, if you link your program without enabling multiple kernel threads, then DECthreads will create only one virtual processor; however, if you enable multiple kernel threads, then DECthreads will create as many virtual processors has there are CPUs on the machine. Thus, in order to achieve true parallel execution, your application must be linked /THREADS and run on an SMP Alpha machine. With respect to commenting on your printserver model, the answers are, unfortunately, more fuzzy. Your general approach seems pretty reasonable, although this Wizard prefers a self-scheduling model (i.e., put the new work item in a queue and signal a condition variable; have workers wait on the condition variable for work; create extra workers if all are busy and the count is less than the "configured maximum"), because it's simpler than scanning the list of threads and having to synchronize with the one which is to receive the item. Regarding determining the maximum number of worker threads, there is no hard and fast formula which will yield the answer. The right number depends on the behavior of the threads while they are actively processing a task. If they are completely compute-bound, then there is probably no point in having more worker threads than there are available CPUs. However, if they perform a mixture of compute activity and blocking activity (i.e., blocking for I/O or on condition variables -- don't count mutex waits, which should be short), then there is an opportunity to support more workers. This Wizard would recommend tuning based on testing. Regarding the choice of linker options, the answer depends on the requirements of the application and the components which it uses. Linking /NOTHREADS (which is the default), is least likely to trigger problems due to lack of thread-safe code; on the other hand, it also results in the application using only one CPU and in unpleasant latencies in blocking system service calls, such as for I/O. The latencies can be addressed by linking /THREADS=UPCALLS, and this will generally not disturb other parts of the code (although it typcially does substantially change execution timing relative to /NOTHREADS, and this might expose latent bugs). Nevertheless, if your code will tollerate it, this Wizard heartily recommends linking /THREADS (which implies both UPCALLS and MULTIPLE_KERNEL_THREADS), as this gives your program best access to the full capabilities of the machine. Please, note that turning on upcalls does make certain operations (e.g., AST delivery) more expensive. The expectation is that the performance loss due to the additional overhead will be more than made up for by removing the blocking latencies and improving the parallelism of the application execution. However, some performance testing might be in order before deciding whether to enable upcalls or not. (Note that DECthreads will not create multiple virtual processors if upcalls are disabled, because DECthreads cannot provide an environment for the application which is "culturally consistent" if there are multiple kernel threads without upcalls.)
|