Parallel computing is a type of computing in which many functions are run simultaneously without blocking each other. Large problems are often divided into subproblems and then can be computed parallel so that user don’t have to wait to execute one program to start the other program. In our regular computer there are multiple cores which perform and process multiple functions at a time so that user don’t have to use only one program at a time. This phenomenon is also called multitasking means doing multiple tasks at one time.
In programming languages, this can be achieved by multi-threading and multi-processing. In web there is an ajax call which is the asynchronous call that execute the action without blocking the main thread, that is why you don’t have to wait for the execution to be done after clicking a button.
In this section, we will focus on multi-threading and multiprocessing in python.
Figure 1 shown above explains that multi-threading is a technique of creating multiple tasks within the same process. Threads can communicate with each other in multi-threading and coordinate.
Suppose we have two functions and both of the function loops from 0 to 20 and print function1 and function2 on each iteration respectively. The standard way of programming means synchronous programming will not start function 2 until function 1 is executed as follows:
If we run the above code func2() will execute after func1() is executed. However, we can make it asynchronous to run parallel by multi-threading as follows:
Now if we run the above code, the output will be one after the other. There will be no block of code, and both will run asynchronously just like this:
What is Threading?
Running several threads at the same time is similar to running multiple programs at one time. Multiple threads within the same process share the information and can also communicate with each other. Threads are also called lightweight processes, and memory requirement is also very low.
In python3 we can use _thread and threading the 2 modules, but it is advised to used threading as _thread is the older and depreciated version. We can also use threading within a class. Threading can only be used with function and with the class, not with the following code. Following way is used in threading with the class:
The above example is using thread in classes. We first inherit threading module into our class, and we initialize threading instance in init. Then in a run function we make a for loop from 0 to 5. Then we make 2 threads and execute both run parallel without blocking to each other. Following is the description of the built-in function that we have used previously.
Start (): The start method starts the new thread by calling the run method. It is to be noted here we have to make a run function in our class to start a thread otherwise start () function will not recognize which function to call.
Join (): The join function will wait for the function to completely execute and then it will terminate the function.
Multi-processing uses different memory space and multiple CPU cores that is why multiprocessing is faster than multi-threading. Although the coding style is approximately same as we have done in multi-threading.
In multiprocessing there is no communication between two processes. The worked independently without any coordination. Similar to multi-threading they can be use along with the function and classes. We cannot use it with synchronous code. Following method is used for the execution of the function:
When you run in the idle, this function will not be executed because multiprocessing function can only be executed in the terminal. Outside the terminal, it will show no output.
By the pool process, we can create the number of workers in multiprocessing which are the number of processes. By this procedure we can pass multiple values at a time which will be executed concurrently. Following code is the practical application of the poll process in python:
The above code is a function that converts the number to rise to the power of 4. Here we have given 7 numbers in the list which are given to the function without making any for a loop. If we run this program in a terminal, we will get the following output:
It is not necessary to write if __name__ == '__main__': in multiprocessing. It is actually a convention to write but bot compulsory without it the code will work fine.
This was the introduction of multi-threading and multiprocessing. Nowadays these modules are not used vastly due to the presence of an efficient application program interface. We will see in higher level what are the new modules and what is the disadvantage of using these modules till than practice on multi-threading and multi-processing to know the core of these two modules.