←to practical programming

Multiprocessing

Symmteric multiprocessing and threads

Symmetric multiprocessing (SMP) referes to computer hardware where two or more identical processors are connected to a single shared main memory and are controlled by a single instance of an operating system. Most ordinary computers today use the SMP architecture.

When a program uses two or more processors on an SMP computer—to share the workload and speedup execution—it is broadly refered to as multiprocessing or parallel computing. A part of a program that can run independently on a single processor is refered to—in this context—as a thread. Multiprocessing is generally achieved when the master thread of a program—the one where the Main function runs—forks off a number of extra threads which execute blocks of code in parallel on the available processors.

Threads in C-sharp

In C-sharp the namespace System.Threading contains classes to work with threads. In particular, the System.Threading.Thread class can create a separate thread that will executes a given function (a delegate). The operating system will then be able to run this thread on a separate processor.

The delegate to be run in a separate thread can be of two types: a void function without arguments, or a void function with one argument of type object,

public static void procedure_without_arguments();
public static void procedure_with_one_argument(object? obj);
/* "?" signifies the object can be null */
	
The function can cast the argument to whatever type it needs.

Example: calculatiion of the partial harmonic sum, Σi=a…b 1/i, in a separate thread:

public class data { public int a,b; public double sumab; } /* data to pass to/from harmonic_sum */

public static void harmonic_sum(object obj){ /* the function to run in a thread */
	data x = (data)obj;                  /* cast the argument to type "data" */
	x.sumab = 0;
	for(int i = x.a; i < x.b; i++) x.sumab += 1.0/i;
	}

public static void Main(){
	data x = new data();
	x.a = 1; x.b = 1001;                 /* prepare data */
	Thread t = new Thread(harmonic_sum); /* prepare a thread */
	t.Name = "my new thread";            /* you can give it a name, if you wish */
	t.Start(x);                          /* run the t-thread with object x as argument to harmonic_sum */
	/* meanwhile do some work in the main thread */
	t.Join();                            /* join the t-thread with the main thread */
	WriteLine($"harmonic sum from {x.a} to {x.b} equals {x.sumab}");
}

Note that the in-thread summation variable "sumab" has to be local to the thread to avoid the so called "race condition" when several threads try to access a shared variable at the same time.

Dotnet parallel programming

In addition to the Thread class dotnet implements System.Threading.Tasks.Parallel.For and System.Threading.Tasks.Parallel.Foreach loops (and several other parallel constracts) which might automatically distribute the computational load over several processors.

Parallel make

Actually, "make" can execute tasks in parallel if you give it "-j" ("--jobs") option. It will then analyse your Makefile, trying to find out which targets are independent, and will build these targets in parallel.

Consider, for example, the following snippet in a Makefile,

test: out1 out2 out3 out4
out1 : main.exe ; mono main.exe -terms:1e8 -threads:1 > out1
out2 : main.exe ; mono main.exe -terms:2e8 -threads:1 > out2
out3 : main.exe ; mono main.exe -terms:3e8 -threads:1 > out3
out4 : main.exe ; mono main.exe -terms:4e8 -threads:1 > out4
	
The command "make -j4 test" will run these four recipies in parallel.

Parallel batch processing

One can also run several tasks in parallel via a shell script (or manually, if you must) using "&" modifier which launches the given command in a separate background process. Consider, for example, the following shell script (let's say in a file "script.sh")
mono main.exe -terms:1e8 -threads:1 > out1 &  
mono main.exe -terms:2e8 -threads:1 > out2 &
mono main.exe -terms:3e8 -threads:1 > out3 &
mono main.exe -terms:4e8 -threads:1 > out4 &
	
The command "sh script.sh" will execute the four lines in four separate processes in the backround.