• No results found

Why Should I Care About Multi-threaded and Parallel Programming?

In document Leanpub.more.Coding.in.Delphi.2015 (Page 115-118)

Good question. It should be pretty easy to answer. Moore’s Law²² marches on. Historically, Moore’s Law meant more transistors on a single CPU chip. It recently took a bit of a detour. The ability to add transistors to an individual CPU core became more difficult, and so instead of putting the transistors into one CPU, chip makers started putting multiple CPU cores into a single CPU chip.

What has happened to make Moore’s Law still relevant is that CPUs have become multi-cored – the transistor count still increases, but they increase by adding more cores. That is, a given CPU chip actually has multiple CPUs in it. I don’t know the clock speed of the CPU in this computer I am writing on, but I do know that it has four real cores, and eight virtual ones. In addition, the cache on chips is growing, as is the memory attached to them. Shoot, even my phone has a multi-core CPU in it.

Multi-threaded and parallel programming aims at taking advantage of these multiple cores. If you have multiple cores but tie your application to only a single core, you aren’t fully utilizing the speed and power of your machine. The days of fixing performance by using better hardware are now sadly gone. Your application needs to use all the cores within your CPU.

All of this boils down to two things that multi-threaded and parallel programming will get you: better speed and better responsiveness. Obviously, if you separate a task into multiple execution paths, it is going to run faster. In addition, if you split the task into parallel threads, your application can remain responsive while doing complicated and intense calculations because the main thread – where the user interface runs – has its own, separate lane. Almost all of the demo applications we’ll look at can be moved and sized while intense calculating is going on in them.

That’s why you should care about multi-threaded and parallel programming.

²²http://en.wikipedia.org/wiki/Moore%27s_law

A Long Task

In order to illustrate the use of the Multi-threading and the PPL, we need a method that takes up some serious CPUtime. Most demos I see use the good oldSleepcommand, but I don’t want to do that. I want my demos to do something at least semi-real. Instead, let’s use a very inefficient algorithm for calculating prime numbers, and then check for the “primeness” of a fixed group of numbers. Calculating the total number of primes between 2 and 100,000 should take some serious CPU time – just what we are looking for. This task will do well for taking up the CPU time we need to illustrate parallel programming.

Here’s the code we’ll use:

// An incredibly inefficient way to calculate primes function SlowIsPrime(aInteger: integer): Boolean;

var

i: integer;

begin

Assert(aInteger > 0);

// Remember, 1 is not prime if aInteger = 1 then begin

Thus, you can call something like thePrimesBelow(200000)function, which will take the CPU time we need to illustrate a time-consuming process. On my machine, the following code:

Stopwatch := TStopwatch.StartNew;

Total := PrimesBelow(200000);

ElapsedSeconds := StopWatch.Elapsed.TotalSeconds;

WriteLn('There are ', Total, ' primes under 100,000');

WriteLn('It took ', ElapsedSeconds, ' seconds to calculate that') ; ReadLn;

reports taking about six seconds to run, which ought to serve our purposes very well. We can adjust this to createPrimesBelow(50000)andPrimesBelow(100000)as needed or desired.

We are also going to use simple VCL apps to run our code, because part of using threads involves producing responsive applications during CPU-intensive processes. Part of what I’ll ask you to do when you run the code we’ll be looking at is to try to move the application using the title bar. Without multi-threading, a CPU-intensive application is usually not responsive to simple requests like moving the main window. However, that’s not good, and we’ll see how you can use threads and parallelism to both speed up your applications while at the same time keeping them responsive. Nice, eh?

Okay, with all that scary talk out of the way, let’s get started.

Introduction

When Delphi 1 was introduced – way back in 1995 – it was a 16-bit tool that ran on Windows 3.1. Those were the days, eh? Anyway, Windows 3.1 didn’t do multi-threading; it did something called “cooperative multitasking.” This meant that the OS would manage the “passing of the baton” around to different processes, simulating a multi-threaded system. Problems could and would easily occur when an application refused to give up the baton. It was sub-optimal to say the least.

Delphi 2 came out about a year after Delphi 1, and it was a 32-bit system running on Windows 95. Windows 95 allowed for true multi-threading, and thus Delphi 2 supported threading via a class calledTThread. Delphi 2’sTThreadwas fairly straight forward, and since then,TThreadhas been enhanced and expanded, taking advantage of things like anonymous methods.

This chapter will cover the basics of TThread. We won’t delve into the low-level Win32/64 API calls that

TThreadencapsulates. Instead we’ll stick to the functionality that Delphi provides.

In document Leanpub.more.Coding.in.Delphi.2015 (Page 115-118)