English | 中文 | Русский | Français
2,556 Posts served
8,271 Conversations started
Part 1 of this article described how the original design of Windows User Mode was highly advanced and suitable for the parallel world, but in time the concepts and goals behind this design were lost and forgotten. This part of the article describes the evolution of UNIX systems in regards to parallel operations. This article is a background information for a collection of articles that will explain a new design model called Operation View Model.
UNIX
UNIX operating system had a great advantage when it comes to parallelism because in its foundations we find the network. This means that the OS was designed to support distributed applications.
It is noticeable that a great deal of attention was given to parallelism and flow control in the basic design of this operating system. One of the most basic elements is a queue. UNIX attaches an input queue and an output queue to many of the basic system components for example the console input and output, serial port, parallel port, etc. Furthermore the operating system support output redirection as an input to another application (Pipe). Redirecting the output queue to an input queue of the next level is purely Task Oriented Design. The problem with this model is that it was conceived at the very early days of computers and therefore the problems that it solves and the implementation are relatively simple and primitive in today's standards. Back then the keyboard had a 16 characters buffer (queue). Today a simple USB device uses a four layer network communications with larger buffers. This design and implementation is not widely used, and when it is – many times it is just for ease of use and not as part of a good parallel design.
UNIX has also introduced wide support for network communications. In this model every application creates a network socket and is listening to it. When you want an operation to be performed, you connect to that socket by its number, send the message, and close the socket when done. This model is also very good in its parallelism. Every service provider takes a socket with a predefined number. Every element in the system that has a request communicates to that socket. In other words every element in the system can initiate an operation on a given service provider identified by its socket id. In this model the system is a collection of event handlers called Services and every application can initiate a Task with each Service by sending data to its socket queue. Services can of course receive service from other Services. This model allows applications to be distributed with little to no effort. Like the other parallel models this model was long forgotten and got rejuvenated lately as SOA.
Last but not least important technique provided by the UNIX OS is called Fork. Forking is an operation performed by a process in which it is completely duplicated. Some sort of a "Copy – Paste my process" if you like. The two copies are almost identical and the only way to tell which is the original and which is the clone is by testing the value returned from the command Fork. If you are the original then you receive the clone's ID and if you are the clone then you receive and empty ID (NULL). This is a very advanced parallel computing model. In this model all global resources are 'thread-safe' because the process memory is not shared. This is in comparison to Windows where you create threads and all threads in the same process share the same address space. The Fork mechanism also takes care or system wide resources such as files etc. When the process is cloned then all Handles are duplicated. Duplicating a Handle instead of using the same handle means that the File-System manages all access rights and employs locks when required. These locks are real locks that can block access, and not a simple flag (like a MUTEX). Windows cannot employ this methodology because process creation and even thread creation is a really heavy procedure on Windows OS.
With all complements that Fork gets, it was really early days in the computer world when this technology was conceived. Soon enough you will have 128 cores and need to create for example 20 parallel execution elements (threads, processes, etc.). Performing a Fork operation to spawn 19 new clones is somewhat of a problem. Another problem is joining all clones and waiting for all of them to complete and combining all data between them. Think about an image processing application. Think about video encoding – frame by frame.
When we have 20 processes performing the same operation it is Force Duplication. A different model called a Pipeline can be employed. In the second model you don't just have all work elements doing the same job, you have several workers collecting data, several doing the processing, and several are saving data. It is very possible to have several processes in a single operation flow. For example: Read image, Remove noise, make black/white, clean edges, detect faces, compress, save image. Launching a single process to clone into all these components is very difficult. Data transfer is also problematic. Original UNIX solved this using a Pipe between several process applications but the problem is that this method is heavily using memory and memory access and might miss the whole point of massively using the CPU because the memory might becomes a bottleneck in this case.
In time UNIX developers slowly forgot about these features and instead of improvements we got replacements such as threads and locks. These are the very things that Fork was designed to avoid (exposing resources to all running elements and using locks to serialize the access to these resources).
Bottom line we get good design and concepts that were eventually misunderstood and forgotten, and in time replaced by alternatives that make it harder to make the best out of a multi-core CPU because Task Oriented Design was not one of the design efforts.
Next to follow, Part 3 will explore the Windows NT Kernel as an example of an excellent parallel system. Part 4 will talk about DOS.
