Migrating legacy applications to multicore: Not as scary as it sounds
Legacy migration to multicore comes with its fair share of challenges, but they can be mitigated successfully when developers divide and conquer, then leverage the right tools for the job.
Multicore processors bring significant performance and power usage benefits to embedded systems, but they also add the complexity of multiprocessing to the legacy migration workload. Nonetheless, development teams can successfully manage their transition to multicore by following some straightforward techniques.
Port to a portable standard
Often, migrating to multicore involves more than moving to a new processor. In many cases, developers must first port the legacy code to a new programming language, compiler, or OS. Using an open standard such as POSIX is highly recommended, in light of its support of many general-purpose and real-time operating systems. Doing so will help ensure that large portions of the application, including its interface with the OS, are portable. Just as important, the POSIX standard has a proven history in multiprocessing systems, and a multicore processor is simply a multiprocessing System-on-Chip (SoC).
Divide and conquer
The OSs that support Symmetric Multiprocessing (SMP) are the best option for homogenous multicore processors. SMP leaves the complex details of allocating CPU resources to the OS, rather than to the application. From the application's point of view, the interface to the OS remains the same, regardless of the number of cores, from 1 to N. Consequently, the application can scale easily as more cores are added.
A multicore system running in SMP mode provides true parallelism, but some legacy applications were never designed for parallel execution. Often, large portions of the code do not use threads, which would allow different parts of the application to run in parallel or use threads only to isolate blocking system calls such as file or network I/O.
Another typical pitfall occurs when code uses a priority scheme to control access to shared memory. For instance, in a uniprocessor embedded system, the software developer can often assume that a high-priority thread and a low-priority thread will not access the memory simultaneously, since the high-priority thread will always preempt the low-priority thread. Thus, many programs fail to use a mutual exclusion lock (mutex) to properly synchronize access to the memory. In an SMP multicore system, however, both of these threads can run in parallel and, as a result, access memory simultaneously with unpredictable results. Other insidious problems might exist due to synchronization errors that work perfectly on a single processor system but surface only in multiprocessor execution.
To solve such problems, developers can divide and conquer: isolate the problem code on a single core of the multicore chip until the code can be fixed. To do this, developers can use Bound Multiprocessing (BMP), an extension to SMP that allows selected processes to run on only a specified core or CPU. In effect, BMP provides a single-core, nonparallel execution environment for legacy code while allowing other code to leverage the full parallelism of SMP. The development team can subsequently remove the CPU binding once they have modified the legacy code to behave properly in its new parallel environment.
Leverage the tools
Development teams must also use the right tools. In particular, they need visualization tools that help them pinpoint areas where code is misbehaving in a parallel environment. Mostly, this effort involves the detection and correction of the synchronization bugs mentioned earlier.
Once an application is operating properly, it may still fail to take advantage of all of the multicore chip's CPU capacity. Visualization tools can help here, too, by allowing developers to reduce contention for shared resources (hot spots), eliminate excessive thread migration or communication between cores, and find opportunities for parallelizing code. As the number of cores increases in multicore platforms, visualization tools will be the key to successfully leveraging the performance benefits that multicore offers.
To provide such analysis, multicore visualization tools must reach beyond the scope of conventional debug tools. They must, for example, track threads as they migrate from one core to another and diagnose messages flowing between cores. They must also offer flexible control over which events are recorded and when, so that developers can focus on areas of concern.
Making the transition
"Multicore" does not need to be a bad word nor add another roadblock to legacy migration. Adopting portable programming standards such as POSIX, using OSs designed for multicore platforms, isolating legacy code to run on a single core, and using visualization tools all make the transition less daunting.