Transcript

Document Type: Tutorial NI Supported: Yes Publish Date: Aug 3, 2007

Building Multithreading Applications with LabWindows/CVI

Overview

As personal computers continue to advance into more industries and advanced applications, developers are pushing the limits of power and flexibility required for their solutions. Microsoft is attacking Unix workstations with Windows NT servers in areas traditionally dominated by Unix, such as network administration and transaction processing. These efforts are starting to introduce new terms into the vocabulary of general-purpose PC users, such as multithreading and multiprocessing. Unfortunately, confusion still exists about what these technologies offer and the advantages you can expect as you develop applications. This document introduces these concepts and explains how multithreaded systems benefit developers of data acquisition and instrument control applications including improved throughput, responsiveness, and more efficient background processing. An example developed with LabWindows/CVI 5.0 will be discussed in detail to illustrate these benefits in a real-world solution.

Table of Contents

1. Multitasking and Multithreading 2. Multithreading Advantages for Instrumentation Users 3. Maximizing Multiprocessor Performance 4. Building Multithreaded Applications in LabWindows/CVI - A Simple Example 5. Conclusions

Multitasking and Multithreading

The terms multitasking, multithreading, and multiprocessing all refer to distinctly different concepts, but are often used interchangeably. Multitasking refers to the ability of an operating system to switch between tasks quickly to give the appearance of simultaneous execution of those tasks. In a single-threaded environment, such as Windows 3.1, a task is an application – Microsoft Word, Excel, PowerPoint, and so on. These applications are written to share processor time with other Windows 3.1 applications. For example, each application performs operations and then gives up control of the microprocessor at certain points so that other applications can use it. This form of time sharing with the processor resources is also called non-preemptive multitasking, because the application itself controls how much time it uses and when it gives up control of the processor. Window NT and Windows 95 offer the enhanced capabilities of preemptive multitasking, which transfers the control of processor time switching to the operating system, rather than relying on applications to yield voluntarily. This feature has a major impact on applications; when running in a preemptive multitasking system, applications can be suspended at any time. Therefore, they must be able to respond to changes in the system that occur while processor control is taken away from them in mid-operation. With multitasking working properly, all executing applications on the system appear to progress in parallel. In many cases, however, those applications themselves can be divided into multiple tasks that can also execute in parallel. Multithreading extends the idea of multitasking to apply within applications, giving applications the ability to separate their own tasks into individual threads. The operating system can then divide processing time on these threads similar to the way it divided processing time between whole applications on the solely multitasking system. Thus, a multithreaded application can have multiple tasks progressing in parallel on the operating system along with other applications. While multithreading offers many advantages on single processor machines, implementing multithreading on machines with more than one processor is absolutely necessary to take advantage of the additional hardware for your application. Multiprocessing refers to multiple processors in one computer, executing the threads that are ready to run. In a symmetric multiprocessing (SMP) system, the operating system automatically uses all of the processors in the computer to run any threads. Once you implement a multithreaded program, it can take full advantage of any number of processors within the system automatically. With multiprocessing power, your multithreaded application can truly run multiple threads simultaneously, finishing more tasks in less time. Single-threaded applications may experience little performance improvement by switching to a new multiprocessor machine. Single-threaded applications execute on either one processor or another, but never all at once as multi-threaded applications do. In fact, single-threaded applications can experience an adverse affect on performance through the overhead of the operating system switching the application from one processor to another. To achieve maximum performance from multithreaded operating systems and/or multiprocessor machines, an application must be multithreaded.

Improve your ni.com experience. Login or Create a user profile.

Page 1 of 5Building Multithreading Applications with LabWindows/CVI- Developer Zone - National...

2/21/2008http://zone.ni.com/devzone/cda/tut/p/id/3066

Windows NT, Windows 95, some Unix operating systems, and other popular platforms are multithreaded systems today. These operating system run either on a single-processor machine or on an increasingly popular multiprocessor desktop system. The multithreading software and multiprocessor computer technology are in place and readily available. You can take full advantage of these systems by implementing multithreading in your applications.

Multithreading Advantages for Instrumentation Users

Multithreading can offer numerous benefits to the user, especially in PC-based data acquisition and instrument I/O applications. On single-processor machines, multithreading can help in applications with situations where some tasks take a much longer amount of time to execute than others; where some tasks need a better deterministic outcome than others, or where user interface activity may run concurrently with hardware communication. On multiprocessor systems, a multithreaded application takes advantage of the additional hardware, usually resulting in greatly improved overall performance. Preventing Blocking PC-based instrumentation applications often communicate with either plug-in data acquisition (DAQ) boards, or stand-alone instruments using standard interfaces such as GPIB, VXI, and serial, to acquire necessary data for test, measurement, and control. These applications sometimes encounter synchronous acquisition calls to an instrument or board that take some time to finish executing and return to the program. For example, if you configure your plug-in DAQ board to synchronously acquire 10,000 points at a rate of 100 points/s, it will take a while for this operation to execute. Or, more commonly, you may wish to poll a serial port for data. In a single-threaded application, that call effectively prevents the application from performing any other internal tasks that can be done until the acquisition is completed. During that synchronous acquisition call where the single-threaded application no longer uses the processor, the operating system switches to another thread on the computer that is ready to run and can use the processor. On the other hand, a multithreaded application can have other parts of the program on different threads ready to run so that the operating system can simply switch the processor to another part of the program, allowing it to progress while waiting for the acquisition to be completed. Reducing Interference between Execution and User Interface As PCs have moved from the DOS character-based user interfaces to the more powerful Windows graphical user interfaces, users have experienced a quantum leap in PC usability. However, this enhanced GUI comes with a price. In many experiments requiring continuous acquisition and display of waveform data, the user interface is the gating factor. When the acquisition, analysis, and display code of an automated experiment run within the same execution thread, it is possible for the DAQ board to overwrite data in the input buffer in memory before the PC is able to process or display the previous buffer data. With a multithreaded application that takes full advantage of the multithreaded OS, you can achieve better overall system throughput. If you separate the user interface display on a different thread from the execution system, then each thread can run independently, at the highest possible speeds. In many cases, the user interface simply provides a real-time monitor of the ongoing acquisition, but it is not vital to display every point. By separating the user interface from your acquisition with different threads, your DAQ operation is free to run at high-speeds, no longer limited by the performance of the user interface.

Maximizing Multiprocessor Performance

Finally, multithreaded applications can take full advantage of multiple processors to gain simultaneous execution of tasks. A well-implemented multithreaded application efficiently uses all the processors available for its own tasks, whereas a single-threaded application must wait for each task to execute before continuing with the rest of the application. At no time can a single-threaded application execute on more than one processor in the system. Multithreading applications can help the operating system distribute the processor time more evenly among the different tasks it needs to complete, so that all tasks can move quickly towards resolution. With multithreading, an application can efficiently maximize the use of the operating system and the computer processors to achieve better responsiveness, minimize blocking problems, and gain better performance overall.

Building Multithreaded Applications in LabWindows/CVI - A Simple Example

Building multithreaded applications can be a very complex and difficult operation. Threads within a single program usually share data so communication among the threads to coordinate data and resources is vital. If multithreading is not programmed properly in your application, you may experience unexpected behavior. Conflicts can occur when multiple threads either request shared resources simultaneously, or share data space in memory. Describing the details of building multithreaded Windows programs in C is beyond the scope of this note. We recommend that beginners refer to the Microsoft web site for articles and technical papers on multithreading. However, to illustrate the benefits of multithreading for data acquisition or instrument control systems, we will review a simple example implemented in LabWindows/CVI, an ANSI C programming environment designed for scientists and engineers, recently upgraded to Version 5.0, which includes multithreaded libraries. With multithreaded libraries you can use your favorite C/C++ programming environment, from Microsoft to Borland. In addition, you can build multithreaded applications within the LabWindows/CVI environment using the new asynchronous timer control as described below. This example uses a simple Windows timer control in LabWindows/CVI to generate and display sine wave data on a strip chart. The timer control generates an event at defined intervals. The event triggers a function to execute. The function generates a single data point and plots it on a strip chart. This is analogous to a simple control loop that acquires a data point, performs a computation, and generates a value based on the computation for each loop iteration. Let’s explore how multithreading can improve the performance of this operation. To help monitor the performance, a second strip chart will be used to display the interval at which the timer control is actually executing the code. For

Page 2 of 5Building Multithreading Applications with LabWindows/CVI- Developer Zone - National...

2/21/2008http://zone.ni.com/devzone/cda/tut/p/id/3066

example, if our timer control is set to execute every 250 ms, as shown in Figure 1, the timer accuracy strip chart should show a flat line at 250 ms. However, when the timer control is delayed by other elements in the program, the timer accuracy trace will show a spike. Figure 1 shows the program operating entirely within a single thread. Notice the smoothness of the sine wave on the upper chart and the flat line on 250 ms on the timer accuracy chart. These both indicate that the timer control is able to execute on time, once every 250 ms, and the computer is able to generate each data point and display it on the strip chart in less than 250 ms.

Figure 1. This sample application uses a timer control to generate and plot sine wave data on a strip chart. The lower chart displays the response time for each timer event. Limitations with Single Threading When nothing else is happening on the computer, this program runs fine in a single thread. However, problems can arise if the generation or display of the data slows down so that it takes more than 250 ms to execute. For example, if the user generates a lot of mouse interrupts by moving the mouse, or if the user grabs the window frame and moves the window to a different location, the execution is penalized. Because the program is running in a single thread, anytime you delay the user interface operation, you are also delaying everything else in the program. The effect of halting the user interface or moving the mouse during program execution is shown in Figure 2a. In Figure 2b, we show the response of the program when the timer interval is reduced to 50 ms per iteration. As you can see, the program is having difficulty displaying the data points fast enough to keep up with the loop speed.

Figure 2a. In a single-threaded environment, the user interface can slow down the entire application. Notice the discontinuities of data and timer response time caused by moving the mouse or dragging the screen.

Page 3 of 5Building Multithreading Applications with LabWindows/CVI- Developer Zone - National...

2/21/2008http://zone.ni.com/devzone/cda/tut/p/id/3066

Figure 2b. Because the user interface update and the data acquisition are running in the same thread, the program’s performance is limited. Notice the inconsistency of the timer response and the distorted sine wave. Better Performance with Multithreading With LabWindows/CVI 5.0, you can easily separate timer control functions onto different threads from the main program execution thread. Therefore, in the previous example, let’s explore separating onto different threads the timer code that generates the sine wave data from the code that plots it on the strip chart and see how it affects our program. In Figure 3, we see the display as shown after moving the mouse and dragging windows with the timer interval set to 50 ms. As you can see, the accuracy of the timer is much better than the single-threaded system running at 50 ms, and the program shows no side effects when the user interface is temporarily suspended.

Figure 3. When you separate the execution of the program into different execution threads, you can achieve

better performance and data integrity. In this example, the timer is able to respond at ±2 ms resolution when the loop speed is set to 50 ms and the user interface is suspended.

How This Example Was Built This example was built using the multithreaded asynchronous timer control in LabWindows/CVI 5.0. A common question for developers new to multithreading is, “How do you create a thread?” In this example, the thread is running the timer control callback function (the function that is called at a particular interval) specified in the NewAsyncTimer function: NewAsyncTimer (interval, count, initialState, callbackFunction, callbackData)

where, delay = the time between each loop iteration

Page 4 of 5Building Multithreading Applications with LabWindows/CVI- Developer Zone - National...

2/21/2008http://zone.ni.com/devzone/cda/tut/p/id/3066

My Profile | RSS | Privacy | Legal | Contact NI © 2008 National Instruments Corporation. All rights reserved. | E-Mail this Page

count = the number of times to iterate through the loop initialState = running or suspended callbackFunction = the function that will be called to do the actual work (in this example, this is function which generates the data and places it into memory for later processing and displaying) callbackData = data to be passed into the callback function The diagram in Figure 4 shows the difference between using single-threaded (a) and multithreaded (b) timer callbacks for this example:

Figure 4a. In the single-threaded approach, the timer callback function must perform all data generation and display operations during one loop iteration.

Figure 4b. In the multithreaded approach, the user interface update is independent from the data generation code,

guaranteeing that the user interface will not limit the performance of the data generation operation.

Conclusions

Multithreading offers numerous benefits for data acquisition, instrument control, and general programming applications. As companies continue to standardize on multithreaded operating systems and symmetric multiprocessing machines, they have growing expectations to reap the benefits of the new systems. In order to take the most advantage of the systems they have, engineers and scientists will want easier ways to achieve multithreading for their applications.

Reader Comments | Submit a comment »

Legal This tutorial (this "tutorial") was developed by National Instruments ("NI"). Although technical support of this tutorial may be made available by National Instruments, the content in this tutorial may not be completely tested and verified, and NI does not guarantee its quality in any way or that NI will continue to support this content with each new revision of related products and drivers. THIS TUTORIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND AND SUBJECT TO CERTAIN RESTRICTIONS AS MORE SPECIFICALLY SET FORTH IN NI.COM'S TERMS OF USE (http://ni.com/legal/termsofuse/unitedstates/us/).

Page 5 of 5Building Multithreading Applications with LabWindows/CVI- Developer Zone - National...

2/21/2008http://zone.ni.com/devzone/cda/tut/p/id/3066


Top Related