Michael Eriksson
A Swede in Germany
Home » Software development | About me Impressum Contact Sitemap

Do not multi-thread...


This page was originally written in 2012, but was among the many that went unpublished until much later (here: 2024). While the single version checked in was marked as work-in-progress, I publish it almost as is, in order to expedite the clean-up of all those delayed texts.

The main discussion is sound, but a bit simplistic and not always ideally formulated. In addition, there are potentially important sub-topics that are not mentioned, including multi-threading in a server context and to what degree a computationally heavy application uses the processor(s)/core(s) and to what degree the graphics card(s).

Looking back, the focus on multi-core processors/systems, as opposed to multi-processor systems, which have a longer history, might seem odd, but this relates to how the average consumer computer (as opposed to server computers, professional workstations, etc.) only gained true parallelism with multi-cores, which changed the market situation radically. (Note that the parallelism present on a single-CPU and single-core system is simulated.) The general idea does, of course, extend to multi-processor systems and other systems with true parallelism too.

...just because an application runs on a multi-core system.

Since the introduction of multi-core processors, variations of the following complaint have been common:

Multi-core processors are great—but only when software is actually multi-threaded. Alas, most software is still not multi-threaded and until the industry gets going a higher CPU frequency is more important than the number of cores.

In many ways, this claim is correct; however, in many others it misses the point. Most notably, for a great many applications, multi-threading will bring little or no benefit, because the computational requirements are not high enough to challenge even a single core for a non-trivial amount of time or because other bottle-necks make the issue moot (waiting for I/O operations, e.g.).

Further, multi-threading can bring many complications (e.g. problems with several threads accessing the same data in an unexpected order, or the need to wait for one thread to complete before letting another proceed). Such complications are infamous for causing unforeseen bugs—and if there is no major benefit from multi-threading in the individual case, these complications might well do more harm than the benefits do good.

Correspondingly, the use of multi-threading in any given application should be done on an individual basis and only when and where it truly makes sense. Indeed, in many cases, the multi-threading that brings benefits will do so even on a single-core system—e.g. to avoid that an email client freezes up when it communicates with a mail server, and other instances of actually parallel and independent tasks; or by allowing various components to work in asynchronous cooperation,

The remaining cases where multi-threading does make sense usually fall into two categories:

Firstly, the “naturally parallel” problems, where there is a reasonably obvious way to divide the work into (almost) independent packages that can be distributed over several or many threads. The corresponding programs are often already multi-threaded (having a history on workstations or other computers that normally have more than one processor—and have had so for far longer than PCs have had multiple cores) or among the first to actually be converted.

Secondly, problems that are highly intensive in CPU time, but not naturally parallel. Here the original complaint is valid and should be taken seriously. However, the proportion of programs that fall into this category is small.

In the mean-time, multi-core processors have benefits even without multi-threading (although the returns on every additional core are diminishing very rapidly). Consider being able to run several applications that are semi-high to high in CPU-load at the same time, without them getting in each others way and without the computer freezing up. Or: Not having to spend ten minutes trying to kill a run-away process that monopolizes the one core. (Avoiding such monopolization could be a further argument against multi-threading on a system with few cores.)

When push comes to shove, the main issue is not whether the average application is sufficiently multi-threaded, but how much benefit, e.g., an 8- or 16-core system can, at all, bring to the average user. (With reservations for improvements through other means, e.g. compilers or operating systems that help divide the computational burden on multiple cores in a transparent manner—without the need to alter every individual application.)