{"id":306,"date":"2019-03-08T14:45:06","date_gmt":"2019-03-08T13:45:06","guid":{"rendered":"https:\/\/www.kth.se\/blogs\/pdc\/?p=306"},"modified":"2019-03-28T10:52:40","modified_gmt":"2019-03-28T09:52:40","slug":"parallel-programming-in-python-multiprocessing-part-2","status":"publish","type":"post","link":"https:\/\/www.kth.se\/blogs\/pdc\/2019\/03\/parallel-programming-in-python-multiprocessing-part-2\/","title":{"rendered":"Parallel programming in Python: multiprocessing (part 2)"},"content":{"rendered":"<div class=\"post-content-wrapper\"><p class=\"p1\">In the <a href=\"https:\/\/www.kth.se\/blogs\/pdc\/2019\/02\/parallel-programming-in-python-multiprocessing-part-1\/\">previous post<\/a> we introduced the <code style=\"color: black;background: transparent\">Pool<\/code>\u00a0class of the <code style=\"color: black;background: transparent\">multiprocessing<\/code>\u00a0module. In this post we continue on and introduce <a href=\"https:\/\/docs.python.org\/dev\/library\/multiprocessing.html#the-process-class\">the\u00a0<code style=\"background: transparent\">Process<\/code>\u00a0class<\/a>, which makes it possible to have direct control over individual processes.<\/p>\n<p class=\"p1\">A process can be created by providing a target function and its input arguments to the <code style=\"color: black;background: transparent\">Process<\/code>\u00a0constructor. The process can then be started with the <code style=\"color: black;background: transparent\">start<\/code>\u00a0method and ended using the <code style=\"color: black;background: transparent\">join<\/code>\u00a0method. Below is a very simple example that prints the square of a number.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">import<\/span> multiprocessing <span style=\"color: #800000;font-weight: bold\">as<\/span> mp\r\n\r\n<span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 <span style=\"color: #800000;font-weight: bold\">print<\/span><span style=\"color: #808030\">(<\/span>x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span>\r\n\r\np <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Process<span style=\"color: #808030\">(<\/span>target<span style=\"color: #808030\">=<\/span>square<span style=\"color: #808030\">,<\/span> args<span style=\"color: #808030\">=<\/span><span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">5<\/span><span style=\"color: #808030\">,<\/span><span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\np<span style=\"color: #808030\">.<\/span>start<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\np<span style=\"color: #808030\">.<\/span>join<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p><!--more--><\/p>\n<h2>Process and Queue<\/h2>\n<p class=\"p1\">In practice, we often want the process and the function to return the computed result, rather than just printing the result as in the previous example. This can be achieved with help from <a href=\"https:\/\/docs.python.org\/dev\/library\/multiprocessing.html#multiprocessing.Queue\">the <code style=\"background: transparent\">Queue<\/code> class<\/a> in the <code style=\"color: black;background: transparent\">multiprocessing<\/code> module. The <code style=\"color: black;background: transparent\">Queue<\/code> class includes the <code style=\"color: black;background: transparent\">put<\/code>\u00a0method for depositing data and the <code style=\"color: black;background: transparent\">get<\/code>\u00a0method for retrieving data. The code in the earlier example can be changed as follows so that it returns the result (rather than printing it). In this example, a <code style=\"color: black;background: transparent\">Queue<\/code>\u00a0object named <code style=\"color: black;background: transparent\">qout<\/code>\u00a0is used to save the result.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">import<\/span> multiprocessing <span style=\"color: #800000;font-weight: bold\">as<\/span> mp\r\n\r\n<span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">,<\/span> q<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 q<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span>x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span>\r\n\r\nqout <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Queue<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\np <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Process<span style=\"color: #808030\">(<\/span>target<span style=\"color: #808030\">=<\/span>square<span style=\"color: #808030\">,<\/span> args<span style=\"color: #808030\">=<\/span><span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">5<\/span><span style=\"color: #808030\">,<\/span> qout<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\np<span style=\"color: #808030\">.<\/span>start<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\np<span style=\"color: #808030\">.<\/span>join<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\nresult <span style=\"color: #808030\">=<\/span> qout<span style=\"color: #808030\">.<\/span>get<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n<span style=\"color: #800000;font-weight: bold\">print<\/span><span style=\"color: #808030\">(<\/span>result<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">Now we can parallelize the code by creating multiple processes and running them simultaneously.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">import<\/span> multiprocessing <span style=\"color: #800000;font-weight: bold\">as<\/span> mp\r\n\r\n<span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">,<\/span> q<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 q<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span>x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span>\r\n\r\nqout <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Queue<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\nprocesses <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>mp<span style=\"color: #808030\">.<\/span>Process<span style=\"color: #808030\">(<\/span>target<span style=\"color: #808030\">=<\/span>square<span style=\"color: #808030\">,<\/span> args<span style=\"color: #808030\">=<\/span><span style=\"color: #808030\">(<\/span>i<span style=\"color: #808030\">,<\/span> qout<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n\u00a0\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #800000;font-weight: bold\">for<\/span> i <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">range<\/span><span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">2<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">10<\/span><span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">]<\/span>\r\n\r\n<span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 p<span style=\"color: #808030\">.<\/span>start<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\n<span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 p<span style=\"color: #808030\">.<\/span>join<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\nresult <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>qout<span style=\"color: #808030\">.<\/span>get<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">]<\/span>\r\n<span style=\"color: #800000;font-weight: bold\">print<\/span><span style=\"color: #808030\">(<\/span>result<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">We would expect the output to be as follows.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre>[4, 9, 16, 25, 36, 49, 64, 81]\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">However the values in the <code style=\"color: black;background: transparent\">Queue<\/code>\u00a0object will be stored in the order in which the individual processes finish. This means that the order of the squares in <code style=\"color: black;background: transparent\">qout<\/code>\u00a0will not necessarily be in accordance with the ascending order of the input values to be squared. To demonstrate this, we can introduce some randomness in the execution time of the square function. This mimics what happens in realistic calculations where the computational load is not perfectly balanced amongst the processes.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">from<\/span> time <span style=\"color: #800000;font-weight: bold\">import<\/span> sleep\r\n<span style=\"color: #800000;font-weight: bold\">from<\/span> random <span style=\"color: #800000;font-weight: bold\">import<\/span> randint\r\n\r\n<span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">,<\/span> q<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 sleep<span style=\"color: #808030\">(<\/span><span style=\"color: #008000\">0.01<\/span> <span style=\"color: #44aadd\">*<\/span> randint<span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">0<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">100<\/span><span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n  \u00a0 q<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span>x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">Then, for example, we might obtain the following results, instead of the list of square numbers in ascending order.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre>[36, 9, 16, 81, 25, 64, 4, 49]\r\n<\/pre>\n<\/div>\n<\/div>\n<p>Bear in mind that the randomising function is only introduced in this short example to show the effect of asynchronous execution of processes. In realistic code that would perform far more calculations than in the short example, the order of the output values is almost always different from the order of the corresponding input values.<\/p>\n<p class=\"p1\">If we want the results to be output in the same order as the input values (so that in the initial short example the results would be in ascending order), we can pack each input value and the resulting value for its square in a tuple, and save the tuples in the <code style=\"color: black;background: transparent\">Queue<\/code>\u00a0object.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">,<\/span> q<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n    sleep<span style=\"color: #808030\">(<\/span><span style=\"color: #008000\">0.01<\/span> <span style=\"color: #44aadd\">*<\/span> randint<span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">0<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">100<\/span><span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n    q<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">(<\/span>x<span style=\"color: #808030\">,<\/span> x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">After the processes have been executed, the ascending order is recovered by sorting the results saved in <code style=\"color: black;background: transparent\">qout<\/code><span style=\"font-family: Consolas, Monaco, Lucida Console, monospace\">.<\/span><\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\">unsorted_result <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>qout<span style=\"color: #808030\">.<\/span>get<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">]<\/span>\r\nresult <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>t<span style=\"color: #808030\">[<\/span><span style=\"color: #008c00\">1<\/span><span style=\"color: #808030\">]<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> t <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">sorted<\/span><span style=\"color: #808030\">(<\/span>unsorted_result<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">]<\/span>\r\n<span style=\"color: #800000;font-weight: bold\">print<\/span><span style=\"color: #808030\">(<\/span>result<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p>You may have noticed that the above example is special in that the order of the processes coincides with that of the input values. However, more generally, if the input values are not in ascending order, we need to index the output values using the &#8220;process index&#8221; or &#8220;input index&#8221;, rather than the actual input value, in order to obtain the output values in the desired order. This is illustrated in the following code.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">import<\/span> multiprocessing <span style=\"color: #800000;font-weight: bold\">as<\/span> mp\r\n<span style=\"color: #800000;font-weight: bold\">from<\/span> random <span style=\"color: #800000;font-weight: bold\">import<\/span> randint\r\n<span style=\"color: #800000;font-weight: bold\">from<\/span> time <span style=\"color: #800000;font-weight: bold\">import<\/span> sleep\r\n\r\n<span style=\"color: #800000;font-weight: bold\">def<\/span> square<span style=\"color: #808030\">(<\/span>i<span style=\"color: #808030\">,<\/span> x<span style=\"color: #808030\">,<\/span> q<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n    sleep<span style=\"color: #808030\">(<\/span><span style=\"color: #008000\">0.01<\/span> <span style=\"color: #44aadd\">*<\/span> randint<span style=\"color: #808030\">(<\/span><span style=\"color: #008c00\">0<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">100<\/span><span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span> \r\n\u00a0 \u00a0 q<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">(<\/span>i<span style=\"color: #808030\">,<\/span> x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\ninput_values <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span><span style=\"color: #008c00\">2<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">4<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">6<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">8<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">3<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">5<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">7<\/span><span style=\"color: #808030\">,<\/span> <span style=\"color: #008c00\">9<\/span><span style=\"color: #808030\">]<\/span>\r\nqout <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Queue<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\nprocesses <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>mp<span style=\"color: #808030\">.<\/span>Process<span style=\"color: #808030\">(<\/span>target<span style=\"color: #808030\">=<\/span>square<span style=\"color: #808030\">,<\/span> args<span style=\"color: #808030\">=<\/span><span style=\"color: #808030\">(<\/span>ind<span style=\"color: #808030\">,<\/span> val<span style=\"color: #808030\">,<\/span> qout<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">)<\/span>\r\n\u00a0\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <span style=\"color: #800000;font-weight: bold\">for<\/span> ind<span style=\"color: #808030\">,<\/span> val <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">enumerate<\/span><span style=\"color: #808030\">(<\/span>input_values<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">]<\/span>\r\n\r\n<span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 p<span style=\"color: #808030\">.<\/span>start<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\n<span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n\u00a0 \u00a0 p<span style=\"color: #808030\">.<\/span>join<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\nunsorted_result <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>qout<span style=\"color: #808030\">.<\/span>get<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">]<\/span>\r\nresult <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>t<span style=\"color: #808030\">[<\/span><span style=\"color: #008c00\">1<\/span><span style=\"color: #808030\">]<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> t <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">sorted<\/span><span style=\"color: #808030\">(<\/span>unsorted_result<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">]<\/span> \r\n<span style=\"color: #800000;font-weight: bold\">print<\/span><span style=\"color: #808030\">(<\/span>result<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p>The output would then be as follows, where the values are in one-to-one correspondence with the input values <code style=\"color: black;background: transparent\">[2, 4, 6, 8, 3, 5, 7, 9]<\/code>.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre>[4, 16, 36, 64, 9, 25, 49, 81]<\/pre>\n<\/div>\n<\/div>\n<h2>Example: computing \u03c0<\/h2>\n<p>Now let&#8217;s revisit the example of computing \u03c0 in the <a href=\"https:\/\/www.kth.se\/blogs\/pdc\/2019\/02\/parallel-programming-in-python-multiprocessing-part-1\/\">previous post<\/a>. As mentioned before, the computed result from each process should be saved in a <code style=\"color: black;background: transparent\">Queue<\/code>\u00a0object. We therefore need to modify the <code style=\"color: black;background: transparent\">calc_partial_pi<\/code>\u00a0routine.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">def<\/span> calc_partial_pi<span style=\"color: #808030\">(<\/span>rank<span style=\"color: #808030\">,<\/span> nprocs<span style=\"color: #808030\">,<\/span> nsteps<span style=\"color: #808030\">,<\/span> dx<span style=\"color: #808030\">,<\/span> qout<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n    partial_pi <span style=\"color: #808030\">=<\/span> <span style=\"color: #008000\">0.0<\/span>\r\n    <span style=\"color: #800000;font-weight: bold\">for<\/span> i <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">range<\/span><span style=\"color: #808030\">(<\/span>rank<span style=\"color: #808030\">,<\/span> nsteps<span style=\"color: #808030\">,<\/span> nprocs<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">:<\/span>\r\n        x <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">(<\/span>i <span style=\"color: #44aadd\">+<\/span> <span style=\"color: #008000\">0.5<\/span><span style=\"color: #808030\">)<\/span> <span style=\"color: #44aadd\">*<\/span> dx\r\n        partial_pi <span style=\"color: #44aadd\">+<\/span><span style=\"color: #808030\">=<\/span> <span style=\"color: #008000\">4.0<\/span> <span style=\"color: #44aadd\">\/<\/span> <span style=\"color: #808030\">(<\/span><span style=\"color: #008000\">1.0<\/span> <span style=\"color: #44aadd\">+<\/span> x <span style=\"color: #44aadd\">*<\/span> x<span style=\"color: #808030\">)<\/span>\r\n    partial_pi <span style=\"color: #44aadd\">*<\/span><span style=\"color: #808030\">=<\/span> dx\r\n    qout<span style=\"color: #808030\">.<\/span>put<span style=\"color: #808030\">(<\/span>partial_pi<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">Then we can set the number of steps and step size for numerical integration, as well as the desired number of processes. Ideally we would like to have one process per CPU core.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\">nsteps <span style=\"color: #808030\">=<\/span> <span style=\"color: #008c00\">10000000<\/span>\r\ndx <span style=\"color: #808030\">=<\/span> <span style=\"color: #008000\">1.0<\/span> <span style=\"color: #44aadd\">\/<\/span> nsteps\r\nnprocs <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>cpu_count<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">Based on the desired number of processes, we prepare a list of input arguments and create the processes.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\">qout <span style=\"color: #808030\">=<\/span> mp<span style=\"color: #808030\">.<\/span>Queue<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\ninputs <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span><span style=\"color: #808030\">(<\/span>rank<span style=\"color: #808030\">,<\/span> nprocs<span style=\"color: #808030\">,<\/span> nsteps<span style=\"color: #808030\">,<\/span> dx<span style=\"color: #808030\">,<\/span> qout<span style=\"color: #808030\">)<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> rank <span style=\"color: #800000;font-weight: bold\">in<\/span> <span style=\"color: #400000\">range<\/span><span style=\"color: #808030\">(<\/span>nprocs<span style=\"color: #808030\">)<\/span><span style=\"color: #808030\">]<\/span>\r\nprocesses <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>mp<span style=\"color: #808030\">.<\/span>Process<span style=\"color: #808030\">(<\/span>target<span style=\"color: #808030\">=<\/span>calc_partial_pi<span style=\"color: #808030\">,<\/span> args<span style=\"color: #808030\">=<\/span>inp<span style=\"color: #808030\">)<\/span>\r\n             <span style=\"color: #800000;font-weight: bold\">for<\/span> inp <span style=\"color: #800000;font-weight: bold\">in<\/span> inputs<span style=\"color: #808030\">]<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p class=\"p1\">After asynchronous execution of the processes, the computed value of \u03c0 is obtained.<\/p>\n<div class=\"highlight-default\">\n<div class=\"highlight\">\n<pre style=\"color: #000000;background: #ffffff\"><span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n    p<span style=\"color: #808030\">.<\/span>start<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\n<span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">:<\/span>\r\n    p<span style=\"color: #808030\">.<\/span>join<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span>\r\n\r\nresult <span style=\"color: #808030\">=<\/span> <span style=\"color: #808030\">[<\/span>qout<span style=\"color: #808030\">.<\/span>get<span style=\"color: #808030\">(<\/span><span style=\"color: #808030\">)<\/span> <span style=\"color: #800000;font-weight: bold\">for<\/span> p <span style=\"color: #800000;font-weight: bold\">in<\/span> processes<span style=\"color: #808030\">]<\/span>\r\npi <span style=\"color: #808030\">=<\/span> <span style=\"color: #400000\">sum<\/span><span style=\"color: #808030\">(<\/span>result<span style=\"color: #808030\">)<\/span>\r\n<\/pre>\n<\/div>\n<\/div>\n<p>For a simple example like computing \u03c0, the <code style=\"color: black;background: transparent\">Process<\/code>\u00a0class provides very similar scaling to the <code style=\"color: black;background: transparent\">Pool<\/code>\u00a0class introduced in the <a href=\"https:\/\/www.kth.se\/blogs\/pdc\/2019\/02\/parallel-programming-in-python-multiprocessing-part-1\/\">previous post<\/a>.<\/p>\n<h2 class=\"p1\">Summary<\/h2>\n<ul>\n<li>The <code style=\"color: black;background: transparent\">Process<\/code>\u00a0class makes it possible to control the processes directly.<\/li>\n<li>The <code style=\"color: black;background: transparent\">Queue<\/code>\u00a0class can be used to save results from the processes.<\/li>\n<li>The processes are executed asynchronously.<\/li>\n<li>The order of the output is not guaranteed to correspond to that of the input values.<\/li>\n<\/ul>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>In the previous post we introduced the Pool\u00a0class of the multiprocessing\u00a0module. In this post we continue on and introduce the\u00a0Process\u00a0class, which makes it possible to have direct control over individual processes. A process can be created by providing a target function and its input arguments to the Process\u00a0constructor. The process can then be started with [&hellip;]<\/p>\n","protected":false},"author":1140,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"jetpack_post_was_ever_published":false,"footnotes":""},"categories":[5],"tags":[9,19],"class_list":["post-306","post","type-post","status-publish","format-standard","hentry","category-performance","tag-parallelization","tag-python"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p9W9Im-4W","_links":{"self":[{"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/posts\/306","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/users\/1140"}],"replies":[{"embeddable":true,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/comments?post=306"}],"version-history":[{"count":34,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/posts\/306\/revisions"}],"predecessor-version":[{"id":382,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/posts\/306\/revisions\/382"}],"wp:attachment":[{"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/media?parent=306"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/categories?post=306"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.kth.se\/blogs\/pdc\/wp-json\/wp\/v2\/tags?post=306"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}